本文主要讲述基于vc++6.0 mfc图像处理的应用知识,主要结合自己大三所学课程《数字图像处理》及课件进行讲解,主要通过mfc单文档视图实现显示bmp图片点运算处理,包括图像灰度线性变换、灰度非线性变换、图像阈值化处理、图像均衡化处理等知识,并结合前一篇论文灰度直方图进行展示
。同时文章比较详细基础,希望该篇文章对你有所帮助,尤其是初学者和学习图像处理的学生。
免费资源下载地址:
图像的点运算是图像处理中非常基础的技术,它主要用于改变一篇图像的灰度分布范围,通过一定的变换函数将图像的像素进行转换,最终生成一幅新的图像。点运算的最大特点就是输出像素值只与当前输入像素值相关。定义如下。
点运算(point operation)指对于一幅输入图像,将产生一幅输出图像,输出图像的每个像素点的灰度值由输入像素点决定。
点运算由灰度变换函数(grap scale transformation,gst)确定:b(x,y)=f[a(x,y)]
需要注意一下几点:
(1).与局部或邻域运算的差别,输入像素和输出像素是一一对应的;(2).与几何运算的差别,不改变图像的空间关系;(3).又称为对比增强,对比拉伸或灰度变换。
第一步:在资源视图中menu中添加“图像点运算”菜单栏如下所示:
对应的id值为:
线性变换 id_dys_xxyd(点运算 线性移动) id_dys_xxzq( 点运算 线性增强)
id_dys_xxjx(点运算 线性减小) id_dys_xxqb(点运算 线性求补)
非线性变换 id_dys_fxxpf(点运算 非线性平方) id_dys_fxxhs(非线性函数)
阈值变换 id_dys_yzbh(点运算 阈值变换) 图像均衡化 id_dys_jhh
第二步:打开类向导(ctrl+w),为点运算每个id菜单添加相应的功能处理函数,如下图所示:选择类cimageprocessingview,在选择ids为id_dys_...(点运算)添加函数ondysxxqb()线性求补。
图像线性变换是通过建立灰度映射来调整资源图像的灰度,从而达到图像增强的目的。其中gst函数f(d)为线性的,即:
若a=1,b=0图像像素不发生变化
若a=1,b!=0图像所有灰度值上移或下移
若a>1输出图像对比度增强
若0<a<1输出图像对比度减小
若a<0暗区域变亮,亮区域变暗,图像求补
1.d(b)=d(a)+50
首先是图像移动,代码如下:
同时修改void cimageprocessingview::showbitmap(cdc *pdc,
cstring bmpname)函数中的代码:
运行效果如下图所示,同时我截取了直方图(rgb相同只显示一种)。
可以发现图像的灰度上移了50,图像更白了(黑0-255白)。
2.d(b)=1.5*d(a)
运行效果如下图所示,图像对比度增强,平均灰度122*1.5=181
3.d(b)=0.8*d(a)
运行如下图所示,图像减弱。
4.d(b)=-1*d(a)+255
运行效果如下图所示,它是图像的求补,发现直方图是互补的。
ps:注意图片下面的直方图应该还有一个处理后的直方图,但原理都一样,我不想重复工作,你自己可以去简单实现下,参考第四篇文章。同时这些图片制作还挺麻烦的,只是为了给你更好的呈现它们的变化,希望对你有用和尊重作者,不喜勿喷~
灰度非线性变换主要包括对数变换、幂次变换、指数变换、分段函数变换,通过非线性关系对图像进行灰度处理,下面主要讲解课件中的两个函数对其进行处理。其中对数变换实现了扩展低灰度值而压缩高灰度值的效果,图像灰度分布更符合而你的视觉特征。
1.d(b)=d(a)*d(a)/252
运行效果如下图所示:
2.d(b)=d(a)+0.8*d(a)*(255-d(a))/255
写到此处你会发现图像灰度的线性变换和非线性变换是非常简单的,主要是通过以下步骤完成:
第一步:赋值处理后图像的bmp头信息
file *fpo = fopen(bmpname,"rb");
file *fpw = fopen(bmpnamelin,"wb+");
fread(&bfh,sizeof(bitmapfileheader),1,fpo);
fread(&bih,sizeof(bitmapinfoheader),1,fpo);
fwrite(&bfh,sizeof(bitmapfileheader),1,fpw);
fwrite(&bih,sizeof(bitmapinfoheader),1,fpw);
第二步:通过循环和线性变换或非线性便函函数处理每一个像素
for( i=0; i<m_nimage/3; i++ )
{
fread(&red,sizeof(char),1,fpo);
处理像素rbg 如:red=(int)red*(int)red/255;
fwrite(&red,sizeof(char),1,fpw);
}
第三步:调用showbitmap自定义函数并重绘图像
numpicture = 2;
level=101;
invalidate();
而它的主要应用包括:光度学标定,希望数字图像的灰度能够真实反映图像的物理特性;对比度增强和对比度扩展;显示标定和轮廓线确定(阈值化)。
阈值又称为临界值,它的目的是确定出一个范围,然后这个范围内的部分使用同一种方法处理,而阈值之外的部分则使用另一种处理方法或保持原样。常用的包括产生二值图:当x<t时y=0,当x>=t时y=255(其中t是阈值)。阈值变换在生物学上的应用比较广泛,常用语细胞图像分割等。
打开类向导(ctrl+w)生成选择imageprocessingview类,ids选择id_dys_yzbh后添加相应的函数。代码如下:
运行效果如下图所示,感觉还挺好看的,显然此时的直方图就是0和255两条直线。
灰度均衡化的目的是使一输入图像转换为在每一灰度级上都有相同的像素点(即输出的直方图是平的),它可以产生一幅灰度级分布概率均衡的图像。
换句话说,经过均衡化后的图像在每一级灰度上像素点的数量相差不大,对应的灰度直方图的每一级高度也相差不大。它是增强图像的有效手段之一。
研究思路是通过直方图变换公式实现:
它的步骤如下图所示:
例:有一幅图象,共有16级灰度,其直方图分布为pi, i=0,1,…,15,求经直方图均衡化后,量化级别为10级的灰度图象的直方图分布qi,其中pi和qi为分布的概率,即灰度i出现的次数与总的点数之比。
pi:0.03, 0, 0.06, 0.10, 0.20, 0.11, 0, 0, 0, 0.03, 0, 0.06, 0.10, 0.20, 0.11, 0
步骤1:用一个数组s记录pi,即s[0]=0.03,s[1]=0,s[2]=0.06,…,s[14]=0.11,s[15]=0
步骤2:i从1开始,令s[i]=s[i]+s[i-1],得到的结果是s: 0.03, 0.03, 0.09, 0.19, 0.39, 0.50, 0.50, 0.50, 0.50, 0.53, 0.53, 0.59, 0.69, 0.89, 1.0, 1.0
步骤3:用一个数组l记录新的调色板索引值,即令l[i]=s[i]×(10-1),得到的结果是l:0,0,1,2,4,5,5,5,5,5,5,5,6,8,9,9
这样就找到了原来的调色板索引值和新的调色板索引值之间的对应关系,即
0→0, 1→0, 2→1, 3→2, 4→4, 5→5, 6→5, 7→5, 8→5, 9→5, 10→5, 11→5, 12→6, 13→8, 14→9, 15→9。
步骤4:将老的索引值对应的概率合并,作为对应的新的索引值的概率。例如,原来的索引值0,1都对应了新的索引值0,则灰度索引值为0的概率为p0+p1=0.03;新的索引值3和7找不到老的索引值与之对应,所以令q3和q7为0。最后得到的结果是qi:0.03, 0.06, 0.10, 0, 0.20, 0.20,
0.10, 0, 0.20, 0.11
代码中有详细注释如下:
运行结果如下图所示,图像增强而且异常清晰:
最后介绍下图像对比度拉伸,它就是把你感兴趣的灰度范围拉开,使得该范围内像素,亮的更亮,暗的更暗,从而达到增强对比度的目的。
如下图所示,a、b、c为三段直线的斜率,g1old和g2old表示途中要进行对比度扩展的范围,g1new和g2new表示对应的新值。当g1old=g2old就是二值图像阈值化处理。
由于灰度界别也是255这个约束,所以满足
其中g1old=100,g2old=150,b=3.0的运行效果如下所示:
最后还是希望文章对你有所帮助,如果文章有不足或错误之处,请海涵。最近挺忙的,写这些古老的文章有人说在浪费青春,但我还是准备把这个系列讲完,非常高兴以前的代码注释和风格都不错,回忆起来挺好的,希望你也能养成好的代码和注释风格~