西安交通大学数字图像处理第四次作业Word格式.docx
《西安交通大学数字图像处理第四次作业Word格式.docx》由会员分享,可在线阅读,更多相关《西安交通大学数字图像处理第四次作业Word格式.docx(22页珍藏版)》请在冰豆网上搜索。
高斯低通滤波器是一种常用的空域平滑滤波技术,它是一类根据高斯函数的形状来选择权值的线性平滑滤波器。
二维高斯函数表达式为
根据以上表达式及高斯函数的性质,可以确定一个的高斯滤波模板像素函数为
其中表示模板中像素的坐标,,,表示高斯函数的标准偏差。
观察上式可知,由于在确定大小和标准差后,的值仅与到模板中心的欧式距离有关,因此高斯低通滤波模板应该是中心对称的。
特别地,一个,的高斯低通滤波模板(已归一化使所有位置和为1)为
1.2处理过程及结果
openCV(OpenSourceComputerVisionLibrary)是一种广泛使用的跨平台计算机视觉库,可以运行在Linux、Windows、Android和MacOS操作系统上,它由C++语言编写,主要接口也是C++,但也有大量的Python,Java和MATLAB的接口。
openCV提供的视觉处理算法非常丰富,有大量的图像处理函数可供使用,本文的吐下那个处理操作即是在openCV3.1.0和VS2013环境下进行的。
利用C++编程实现空域的高斯低通滤波,除图像的读写操作以外,编写函数voidmyGaussianBlur(constMat&
src,Mat&
result,intbesarKernel,doublesigma)实现高斯滤波模板的生成和模板的漫游遍历,其中src和result分别代表输入和输出图像对象,besarKernel表示高斯模板边长,sigma表示二维高斯函数的标准差。
对图像test1和test2的处理结果如下图2所示。
a
b
c
d
图2test1.pgm的高斯低通滤波处理结果;
(a)原图像;
(b)-(d)分别
是σ=1.5,边长分别为3,5,7的高斯低通滤波模板处理后的结果
图3test2.tif的高斯低通滤波处理结果;
1.3结果讨论
观察以上两组示例图片的滤波结果可以发现,空域的高斯低通滤波器能对图像起到明显的平滑作用,且模板尺寸越大其模糊效果越明显。
图2的原始图像是经类似正脉冲噪声干扰后的结果,只不过其噪声不是以点状出现,而是以小规模块状形式出现。
这时高斯低通滤波器的去噪效果并不理想,即使不断增大滤波器模板尺寸(边长分别为3~7),仍不能有效地消除噪声,当模板边长为7时,原图像已经发生了严重的模糊失真,很多细节已经难以分辨。
观察图3的原始图像可以发现,人物面部存在一些影响美观的可以看作噪声的黑色斑点,这些斑点随机分布,且其灰度值与原始图像灰度值很接近,和高斯分布的噪声很接近。
这是应用该死低通滤波器的效果就会较好,随着滤波器尺寸的加大,当模板边长为5时既保留了原始图像的绝大部分细节,同时图像噪声(人物面部的斑点)也得到较好的去除,红色矩形内的效果最具比较意义。
可见,空域的高斯低通滤波器并不适合处理带有脉冲噪声的图像,而对一些像高斯噪声这样的随机分布噪声有很好的效果。
2中值滤波
2.1空域的中值滤波算法
中值滤波是一种基于统计排序的非线性平滑滤波器,其主要功能是让与周围像素灰度值的差比较大的像素改变,并取与周围像素相近值,从而消除孤立的噪声点。
中值滤波对处理脉冲噪声(椒盐噪声)非常有效,因为椒盐噪声由灰度很大的正脉冲和灰度很小的负脉冲组成,在对邻域灰度进行排序时,这些噪声点一般处于首末位置,取中值即可避免这些脉冲的影响。
中值滤波的一般性步骤如下:
1使模板在图像中漫游,并将模板中心与图像中的某个像素位置重合;
2读取模板下各像素的灰度值;
3将这些灰度值按从小到大顺序排成一列;
4找出排在中间的灰度值;
5将中间值赋给对应模板中心位置的像素。
二维中值滤波的窗口不必局限于矩形,可以有多种形状,如线状、十字形、圆形、菱形等,不同形状的模板会产生不同的滤波效果,使用时必须根据图像内容和不同要求加以选择[1]。
从经验来看,对于有缓变的较长轮廓线物体的图像,采用方形或者圆形窗口比较适宜;
对于包含有较多尖角物体的图像,则适宜采用十字形窗口;
对于有较多水平或者垂直线条的图像,线状窗口则更为合适。
2.2处理过程及结果
在VS2013环境下,借助openCV库函数,利用C++编写中值滤波函数voidmyMedianBlur(Mat&
dst,constintkSize),其中src和dst分别表示输入图像和目标图像,kSize表示正方形模板的半边长,详细代码见附录源代码2,处理结果如下图所示。
图4test1.pgm的高斯低通滤波处理结果;
(b)-(d)
分别是经过半边长为3,5,7的中值滤波模板处理后的结果
图5test2.tif的高斯低通滤波处理结果;
2.3结果讨论
对比分析图4和图5不同尺寸模板下的滤波效果,再结合2.2中空域高斯低通滤波器的处理结果,可以得出很多有用的结论。
从图4(c)可见,当中值滤波器模板尺寸为5时已经能较好的滤去图像的脉冲噪声,中值滤波器对脉冲噪声的处理效果要明显好于高斯滤波器。
对比图5和图3可知,在处理灰度值接近图像的噪声时,高斯滤波器效果要稍微好于中值滤波器,这在细节放大对比中尤其明显(见图5.1)。
高斯滤波器即使会模糊图像的部分细节,但不会造成类似图5.1(b)中的“水墨画”效应,中值滤波在较粗的线条处往往会产生这种效果。
图5.1空域高斯平滑滤波和中值滤波的细节对比;
(a)空域高斯平滑滤波结果的局部细节放大图;
(b)空域中值滤波结果的局部细节放大,该图像在上下睫毛处出现“水墨画”现象
3图像的非锐化掩蔽(unsharpmasking)
3.1算法讨论
非锐化掩蔽是一种基于空域操作的图像锐化方法,主要思路是用原始图像加上原始图像与平滑图像的差值作为目标图像,以一维信号为例,图6简单地说明了非锐化掩蔽的原理。
图6非锐化掩蔽原理图
图像的非锐化掩蔽的一般性步骤如下[2]:
1将原始图像进行模糊处理得到;
2从原图像中减去模糊图像,得到模板,即
3将模板加到原图像上,得到目标图像
上式中参数决定了模板对目标图像的贡献,当时,称为非锐化掩蔽;
当时,称为高提升滤波;
时,则模板对目标图像的贡献很小。
3.2处理结果
在图像的非锐化掩蔽操作中,本文选取,的高斯低通滤波器平滑图像。
利用openCV库中的函数voidaddWeighted(InputArraysrc1,doublealpha,InputArraysrc2,doublebeta,doublegamma,OutputArraydst,intdtype=-1)实现原始图像和模板图像的加权相加,其中各个图像参数都cv:
:
Mat对象,其作用是为了下述图像运算:
非锐化掩蔽的处理结果如下图所示。
图7test3.pgm的非锐化掩蔽处理结果;
(b)原图像经过σ=3,7×
7
的高斯低通滤波器模糊后的结果(c)非锐化模板(d)使用非锐化掩蔽的结果
对test4.tif同样应用以上非锐化掩蔽算法得到下图。
与test3.pgm不同的是,test4.tif中有较多的斜向边缘,如果说test3.pgm可以用于测试锐化算法在两个相互垂直的坐标轴方向上的效果的话,那么test4.tif中大量的斜向边缘则更能测试锐化算法的一般性效果。
test3.pgm中方块内部充满的大量类似脉冲噪声的突变像素则可以测试锐化算法对灰度突变像素点的作用效果。
图7test4.tif的非锐化掩蔽处理结果;
(b)原图像经过σ=3,7×
的高斯低通滤波器模糊后的结果;
(c)非锐化模板(d)使用非锐化掩蔽的结果
3.3结果讨论
从以上两组图片可以发现,图像的非锐化掩蔽能有效地突出图像中像素值突变的部分,包括景物的边缘(主要是图7)和脉冲噪声点(主要是图6)。
该算法的锐化原理从图6(c)和图7(c)可以很清晰的反映出来,就是在图像灰度值突变处为原图像添加相应的锐化分量,最注重提高这些区域的灰度值以达到锐化的效果。
4Sobel算子与边缘检测
4.1Sobel边缘检测算法
图像中的边缘是指图像局部强度变化最显著的部分,主要存在于目标与目标、目标与背景、区域与区域(包括不同色彩)之间,是图像分割、纹理特征和形状特征等图像分析的重要基础。
图像的边缘有方向和幅度两个属性,沿边缘方向像素变化平缓,垂直于边缘方向像素变化剧烈,边缘上的这种变化可以用微分算子检测出来,通常用一阶或二阶导数来检测边缘。
图像处理中的一阶微分是用梯度幅值来实现的。
对于函数,在坐标处的梯度定义为
该函数具有重要的几何特征,它指出了在处变化率最大的方向。
以3×
3模板为例,对上式中两个方向的梯度进行一次近似处理,以第三行和第一行的差近似方向的差分,以第三列和第一列的差近似方向的差分,得到如下的近似表达式
其中表示原图像中模板覆盖区域某一像素的灰度,如图8所示。
这两个近似表达式可以用模板表示如下图,这就是最常用的Sobel算子。
-1
-2
1
2
图8(a)一幅图像的3×
3区域;
(b)x方向Sobel算子;
(c)y方向Sobel算子
利用Sobel算子进行边缘检测的一种方法就是,分别利用方向和方向的Sobel对原始图像进行两个方向上的边缘检测,然后将两个方向上的检测结果加权求和,权值均为0.5,这个方法相比平方和开根的处理方式效果近似且运算量大大减小。
4.2实验结果
e
f
g
h
在openCV环境下,两次调用函数voidSobel(InputArraysrc,OutputArraydst,intddepth,intdx,intdy,intksize=3,doublescale=1,doubledelta=0,intborderType=BORDER_DEFAULT),其中src和dst分别表示原始图像和经一个方向边缘检测后的结果图像;
ddepth表示输出图像的深度;
dx、dy表示两个方向上差分的阶数,取1或者0;
ksize表示Sobel算子模板边长[3]。
最后利用addWeighted函数对两次的检测结果进行加权相加即可得到最终的检测结果。
对示例图像进行Sobel边缘检测,得到结果如下图所示。
图9test3.pgm及test4.tif的Sobel边缘检测结果;
(a)(e)原始图像;
(b)(f)x方向边缘检测结果;
(c)(g)y方向边缘检测结果;
(d)(h)最终的检测结
果,由于输出的结果图像较暗,这里应用了一次阈值增强算法增强原结果图像
4.3结果讨论
从图9中两组图像中可以看出,基于Sobel算子的图像边缘检测是两个近似正交过程的和过程,即方向的Sobel算子突出方向的边缘,即y方向的Sobel算子突出方向的边缘,最终的结果是两个方向边缘的叠加。
这在(f)(g)两幅图像中展现的尤其明显:
红色椭圆反映了两个方向上的算子在检测方向边缘效果的差异,蓝色椭圆反映了两个方向上的算子在检测方向边缘效果的差异,它们优势互补,共同生成最后的结果图像。
此外,利用Sobel算子进行边缘检测会去除灰度不变或者变化缓慢区域的图像内容,在图像上显示为黑色区域,这种特性在目标检测中非常有用。
选择一个合适的阈值对Sobel算子的检测结果进行二值化,那么边缘就会从整幅图像中突出出来,得到一个仅在目标边缘处不为零的检测结果。
由于openCV的Sobel边缘检测函数voidSobel()包含了一次高斯平滑滤波,其实结果图像中的噪声已经被抑制过了,但是仍然有明显的噪声出现,可见Sobel算子受图像中噪声的影响还是比较明显的。
5Laplace算子与边缘检测
5.1Laplace边缘检测算法
Laplace算子是最简单的各向同性微分算子,具有旋转不变性。
一个二维图像函数的拉普拉斯变换是各向同性的二阶导数,定义为
Laplace算子是一个线性算子,为了将该算子用于数字图像处理,下面给出它的离散形式:
因此合并以上两个方向,得到两个变量的离散Laplace算子是
将上述算子转化为模板操作如图8所示。
其中(b)是Laplace算子最常用的形式,(c)是带有对角化的Laplace算子,它是(b)中模板的扩展形式,对斜向边缘也具有一定的检测能力。
-4
-8
图10(a)一幅图像的3×
(b)常用Laplace算子;
(c)带对角化的Laplace算子
5.2实验结果
本文利用openCV库函数voidLaplacian(InputArraysrc,OutputArraydst,intddepth,intksize=1,doublescale=1,doubledelta=0,intborderType=BORDER_DEFAULT)实现图像的Laplace边缘检测,其中其中src和dst分别表示原始图像和检测结果图像;
ksize表示窗的大小,用于计算二阶导数,必须是正奇数。
对示例图像进行Laplace边缘检测,得到结果如下图所示。
图11Laplace算子边缘检测结果;
(a)(c)原始图像;
(b)(d)边缘检测结果
5.3结果讨论
从图11可以发现,利用Laplace算子进行边缘检测可以同时检测出两个方向的边缘,即该算法对两个相互垂直的坐标轴方向的边缘都是有效的。
与Sobel边缘检测相同的是,openCV的voidLaplacian()函数同样包含一次高斯平滑滤波,该算法同样缺乏对噪声点的抑制能力,很容易将噪声点误当做边缘突出到结果图像中去。
附录
参考文献
[1]赵小川,MATLAB图像处理——程序实现与模块化仿真,北京:
北京航空航天大学出版社,2014.
[2]KennethR.Castleman,数字图像处理,朱志刚,林学訚,石定机,等译,北京:
电子工业出版社,2001.
[3]RobertLanganiere,OpenCV计算机视觉编程攻略,相初银译,北京:
人民邮电出版社,2015.
源代码
1.高斯低通滤波程序(openCV3.1.0C++)
#include<
opencv2/core/core.hpp>
opencv2/highgui/highgui.hpp>
iostream>
usingnamespacestd;
usingnamespacecv;
//定义高斯平滑函数,besarKernel:
模板边长
voidmyGaussianBlur(constMat&
result,
intbesarKernel,doublesigma)
{
//高斯模板半径
intkerR=besarKernel/2;
//定义高斯模板因子
cv:
Matkernel=Mat_<
double>
(besarKernel,besarKernel);
//归一化参数
doublealpha=1/(2*3.1416*sigma*sigma);
doublesum=0;
//模板函数生成
for(inti=-kerR;
i<
=kerR;
i++)
{
for(intj=-kerR;
j<
j++)
{
kernel.at<
(i+kerR,j+kerR)
=exp(-(((j*j)+(i*i))/
(sigma*sigma*2)))*alpha;
sum=sum+kernel.at<
(i+kerR,j+kerR);
}
}
=kernel.at<
(i+kerR,j+kerR)/sum;
}
//输出高斯模板
for(intk=-kerR;
k<
++k)
for(intn=-kerR;
n<
++n)
cout<
<
kernel.at<
(kerR+k,kerR+n)<
"
;
cout<
endl;
result=src.clone();
doublepix;
//遍历图像(i,j)为像素索引
for(inti=kerR;
src.rows-kerR;
++i)
for(intj=kerR;
src.cols-kerR;
++j)
//窗搜索完成高斯模板平滑,(k,n)为模板索引
pix=0;
for(intk=-kerR;
{
for(intn=-kerR;
{
pix=pix+src.at<
uchar>
(i+k,j+n)*
kernel.at<
(kerR+k,kerR+n);
}
}
result.at<
(i-kerR,j-kerR)=pix;
}
intmain(intargc,char*argv[])
Matsrc=imread("
test2.tif"
0);
if(!
src.data)
return-1;
MatgaussFilteredImage;
myGaussianBlur(src,gaussFilteredImage,5,1.5);
imshow("
src"
src);
gaussFilteredImage"
gaussFilteredImage);
//保存结果为bmp文件
imwrite("
test2GaussFiltered_7.bmp"
waitKey(0);
2.中值滤波(openCV3.1.0C++)
#include"
opencv2/imgproc/imgproc.hpp"
opencv2/highgui/highgui.hpp"
cmath>
//中值滤波实现,kSize表示模板半径
voidmyMedianBlur(Mat&
dst,constintkSize)
dst=src.clone();
std:
vector<
vList;
constintnPix=(kSize*2+1)*(kSize*2+1);
//图像源遍历,(i,j)为像素索引
for(inti=kSize;
dst.rows-kSize;
for(intj=kSize;
dst.cols-kSize;
//滑窗进行搜索遍历,(pi,pj)为滑窗索引
for(intpi=i-kSize;
pi<
=i+kSize;
pi++)
fo