OpenCV与EmguCV中的形态学滤波
来源:程序员人生 发布时间:2016-07-26 13:22:11 阅读次数:7974次
形态学(morphology)1词通常表示生物学的1个分支,该分支主要研究动植物的形态和结构。而我们图象处理中指的形态学,常常表示的是数学形态学。下面1起来了解数学形态学的概念。
数学形态学是由1组形态学的代数运算子组成的,它的基本运算有4个: 膨胀、腐蚀、开启和闭合, 它们在2值图象和灰度图象中各有特点。
简单来说,形态学操作就是基于形状的1系列图象处理操作。
OpenCV为进行图象的形态学变换提供了快捷、方便的函数。基本的形态学操作有2种,他们是:膨胀与腐蚀(Dilation与Erosion)。
膨胀与腐蚀能实现多种多样的功能:消除噪声、分割(isolate)出独立的图象元素和在图象中连接(join)相邻的元素。形态学也常被用于寻觅图象中的明显的极大值区域或极小值区域和求出图象的梯度。
①膨胀 dilate
OpenCV中的函数原型以下:
void dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(⑴,⑴), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
- 第1个参数,InputArray类型的src,输入图象,即源图象,填Mat类的对象便可。图象通道的数量可以是任意的,但图象深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之1。
- 第2个参数,OutputArray类型的dst,即目标图象,需要和源图片有1样的尺寸和类型。
- 第3个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。
- 第4个参数,Point类型的anchor,锚的位置,其有默许值(⑴,⑴),表示锚位于中心。
- 第5个参数,int类型的iterations,迭代使用erode()函数的次数,默许值为1。
- 第6个参数,int类型的borderType,用于推断图象外部像素的某种边界模式。注意它有默许值BORDER_DEFAULT。
- 第7个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默许值morphologyDefaultBorderValue(),1般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
我们也能够使用函数getStructuringElement配合这第3个参数的使用从而得到自定义的核。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
其中,getStructuringElement函数的第1个参数表示内核的形状,我们可以选择以下3种形状之1:
- 矩形: MORPH_RECT
- 交叉形: MORPH_CROSS
- 椭圆形: MORPH_ELLIPSE
而getStructuringElement函数的第2和第3个参数分别是内核的尺寸和锚点的位置。
我们1般在调用erode和dilate函数之前,先定义1个Mat类型的变量来取得getStructuringElement函数的返回值。对锚点的位置,有默许值Point(⑴,⑴),表示锚点位于中心。且需要注意,10字形的element形状唯1依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。
eg。
Mat srcImage=imread("M:/图象处理实验/dilate/src.bmp");
Mat dstImage;
//自定义核
Mat structuringE = getStructuringElement(MORPH_RECT,Size(5,5),Point(2,2));
dilate( srcImage, dstImage, structuringE, Point(2,2), 1, BORDER_DEFAULT);
imwrite("M:/图象处理实验/dilate/dst.bmp", dstImage);
EmguCV中的函数原型:Public Shared Sub Dilate(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, element As Emgu.CV.IInputArray, anchor As System.Drawing.Point, iterations As Integer, borderType As Emgu.CV.CvEnum.BorderType, borderValue As Emgu.CV.Structure.MCvScalar)
参数含义与OpenCV中相同
第3个参数可以使用以下函数来获得自定义核:
Public Shared Function GetStructuringElement(shape As Emgu.CV.CvEnum.ElementShape, ksize As System.Drawing.Size, anchor As System.Drawing.Point) As Emgu.CV.Mat
eg。
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)("M:\图象处理实验\dilate\src.bmp")
Dim StructingElement As Emgu.CV.Mat = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, New Size(5, 5), New Point(2, 2))
CvInvoke.Dilate(img, img, StructingElement, New Point(2, 2), 1, Emgu.CV.CvEnum.BorderType.Default, New Emgu.CV.Structure.MCvScalar(0))
img.Save("M:\图象处理实验\dilate\src-result.bmp")
此函数的参数没有默许值,使用起来比较繁琐。也能够以下调用。
Emgu.CV.Image(Of TColor, TDepth).Dilate(iterations As Integer) As Emgu.CV.Image(Of TColor, TDepth)
膨胀是指将图象(或图象中的1部份区域,A)与核B进行卷积。
核可以是任何的形状或大小,它具有1个单独定义出来的参考点。多数情况下,核是1个小的中间带有参考点的实心正方形或圆盘。核可以视为模板或掩码。
膨胀是求局部最大值的操作。
核B与图象卷积,即计算核B覆盖的区域的像素点最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图象中的高亮区域逐步增长。这样的增长就是膨胀操作的初衷。
因而可知,膨胀和腐蚀操作是对图象中的高亮区域进行的,也就是图象的白色区域。
②腐蚀 erode
OpenCV中的函数原型以下:
void erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(⑴,⑴), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
- 第1个参数,InputArray类型的src,输入图象,即源图象,填Mat类的对象便可。图象通道的数量可以是任意的,但图象深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之1。
- 第2个参数,OutputArray类型的dst,即目标图象,需要和源图片有1样的尺寸和类型。
- 第3个参数,InputArray类型的kernel,腐蚀操作的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们1般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。详细信息可见上文。
- 第4个参数,Point类型的anchor,锚的位置,其有默许值(⑴,⑴),表示锚位于单位(element)的中心,我们1般不用管它。
- 第5个参数,int类型的iterations,迭代使用erode()函数的次数,默许值为1。
- 第6个参数,int类型的borderType,用于推断图象外部像素的某种边界模式。注意它有默许值BORDER_DEFAULT。
- 第7个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默许值morphologyDefaultBorderValue(),1般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。
eg。
Mat srcImage=imread("M:/图象处理实验/erode/src.bmp");
Mat dstImage;
Mat structuringE = getStructuringElement(MORPH_RECT,Size(5,5),Point(2,2));
erode( srcImage, dstImage, structuringE, Point(2,2), 1, BORDER_DEFAULT);
imwrite("M:/图象处理实验/erode/dst.bmp", dstImage);
EmguCV中的函数原型以下:Public Shared Sub Erode(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, element As Emgu.CV.IInputArray, anchor As System.Drawing.Point, iterations As Integer, borderType As Emgu.CV.CvEnum.BorderType, borderValue As Emgu.CV.Structure.MCvScalar)
函数参数含义与OpenCV相同
eg。
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)("M:\图象处理实验\erode\src.bmp") Dim StructingElement As Emgu.CV.Mat = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, New Size(5, 5), New Point(2, 2))
CvInvoke.Erode(img, img, StructingElement, New Point(2, 2), 1, Emgu.CV.CvEnum.BorderType.Default, New Emgu.CV.Structure.MCvScalar(0))
img.Save("M:\图象处理实验\erode\src-result.bmp")
腐蚀和膨胀是1对相反的操作,所以腐蚀就是求局部最小值的操作。
③ 开运算开运算,其实就是先腐蚀后膨胀的进程。
开运算可以用来消除小物体,在纤细点处罚离物体,并且在平滑较大物体的边界的同时不明显改变其面积。
④闭运算
闭运算,就是先膨胀后腐蚀的进程。
闭运算可以用来排除小型黑洞。
eg。(VB.NET、EmguCV)
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)("M:\图象处理实验\2维码\2维码.bmp")
Dim StructingElement As Emgu.CV.Mat = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, New Size(5, 5), New Point(2, 2))
'先膨胀
CvInvoke.Dilate(img, img, StructingElement, New Point(2, 2), 1, Emgu.CV.CvEnum.BorderType.Default, New Emgu.CV.Structure.MCvScalar(0))
'再腐蚀
CvInvoke.Erode(img, img, StructingElement, New Point(2, 2), 1, Emgu.CV.CvEnum.BorderType.Default, New Emgu.CV.Structure.MCvScalar(0))
img.Save("M:\图象处理实验\result\result.bmp")
原图象与进行了闭运算后的输出结果比较:参考文献:
Bradski & Kaebler ·《学习OpenCV(中文版)》· 清华大学出版社 · 2009
冈萨雷斯 · 《数字图象处理》 · 电子工业出版社 · 2011
http://blog.csdn.net/poem_qianmo/article/details/23710721
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠