今天要整理的笔记内容是关于图像形态学的操作。
图像形态学,也叫做数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论,在图像处理中占有相当重要的地位。
在图像处理中,对于图像形态学的应用相当的广泛,主要应用在对于图像的预处理操作当中,尤其是在对二值图像的预处理和分析方面,图像形态学是二值图像分析的重要分支学科。
图像形态学能够从图像中提取出对于表达和描绘区域形状有意义、或者是我们所感兴趣的区域形状的图像分量,使后续的处理工作对于整幅图像而言更具有针对性,能够抓住目标对象最为本质(最具区分能力—most discrimination)的形状特征,例如某一目标范围、边界、连通区域等。
图像形态学主要分为:膨胀(dilate)、腐蚀(erode)、开运算(open)、闭运算(colse)、黑帽(blackHat)、顶帽(topHat)、形态学梯度(gradient)、击中击不中(hit and miss)这些操作。下面逐一来进行简要的整理。
1.膨胀(dilate)
膨胀(dilate)是图像形态学中最基础的两个操作之一,形态学中的其它操作都是基于两种基础操作(另一种是腐蚀(erode),下面再做介绍)做进一步拓展而得到的。
膨胀(dilate)通俗易懂地讲,我们可以把它看成最大值滤波,即用结构元素内的最大值去替换锚点的像素值。这里所用到的结构元素,和对图像进行卷积操作时所使用的卷积核有些类似,也可以把它理解成形态学操作中的卷积核,只不过在形态学中被称为结构元素,而且结构元素的形状选择会更加的丰富。
对图像进行膨胀操作后,由于相当于对图像进行了一个最大值滤波,所以对于灰度图像和彩色图像而言,图像的整体亮度会变亮;对于二值图像而言就是它的白色区域会变大,黑色区域会减少。
当对于二值图像进行膨胀操作时,可以用来桥接不同的连通域,也就是可以把一些原本属于同一对象的、但是经过二值化后又分为不同连通域的区域进行相连,使他们能够再次属于同一个区域。
OpenCV中提供了dilate()
这个API进行图像的膨胀操作,其参数介绍如下:
第一个参数src:输入的多通道或单通道图;输入二值图像进行操作时,必须是黑色背景、白色前景;
第二个参数dst:输出图像,类型与通道数目必须跟输入保持一致;
第三个参数kernel:结构元素,需要事先定义;
第四个参数anchor:结构元素的锚点,默认为结构元素的中心位置;
第五个参数iterations:迭代次数,即进行几次操作;
第六个参数borderType:边缘填充方式,使用默认值即可;
第七个参数borderValue:边缘填充值,使用默认值即可。
下面是代码演示:
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //获取结构元素
Mat image_dilate;
dilate(image, image_dilate, element, Point(-1, -1), 1); //膨胀
imshow("image_dilate", image_dilate);
注意在进行形态学操作前,都需要先定义一个结构元素,这个结构元素很大程度影响了形态学操作的效果。OpenCV中使用getStructuringElement()
这个API来进行结构元素的定义。其参数如下:
第一个参数shape:结构元素的类型,常见的有矩形、圆形、十字交叉;需要用MORPH_RECT
这种格式来定义;
第二个参数ksize:结构元素的尺寸;
第三个参数archor:结构元素的锚点,默认下是选择其中心位置为锚点。
这样,就在OpenCV中实现了对图像的膨胀操作,效果如下:
从图中可以很明显的看出,右图在经过膨胀操作后,其整体亮度是升高了,尤其是猫的眼睛里都泛着白亮的光芒。
2.腐蚀(erode)
腐蚀(erode)是图像形态学中最基础的两个操作之一,形态学中的其它操作都是基于膨胀(dilate)和腐蚀(erode)两种基础操作做进一步拓展而得到的。
膨胀和腐蚀是相对而言的,既然膨胀可以被看作是最大值滤波,那么同样的,腐蚀就可以看成是最小值滤波,即用结构元素内的最小值替换锚点像素值。
对图像进行腐蚀操作后,对于灰度图像和彩色图像而言其整体亮度变暗,而对于二值图像而言就是黑色区域变大、白色区域减少了。
腐蚀(erode)操作可以消除二值图像中微小的连通域干扰,因为它能将一些比较小的连通组件给腐蚀掉,使它也变成黑色背景;或者是用来分离连通域,如果有一些原本并不属于同一物体的像素点经过二值化后被划分为同一个连通域,就可以通过腐蚀操作来断开两个不同物体之间的连接,使其分为两个不同的连通域。
OpenCV中提供了erode()
这个API进行腐蚀操作,其参数如下:
第一个参数src:输入的多通道或单通道图;输入二值图像进行操作时,必须是黑色背景、白色前景;
第二个参数dst:输出图像,类型与通道数目必须跟输入保持一致;
第三个参数kernel:结构元素,需要事先定义;
第四个参数anchor:结构元素的锚点,默认为结构元素的中心位置;
第五个参数iterations:迭代次数,即进行几次操作;
第六个参数borderType:边缘填充方式,使用默认值即可;
第七个参数borderValue:边缘填充值,使用默认值即可。
代码演示:
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); //获取结构元素
Mat image_erode;
erode(image, image_erode, element, Point(-1, -1), 1); //腐蚀
imshow("image_erode", image_erode);
具体效果如下图:
从膨胀和腐蚀操作后的两幅图像对比,很明显的能够看出腐蚀后的图像整体地变暗了,而且暗像素也增多了,尤其是眼珠部分特别的明显。
3.开运算(open)
图像的开操作,就是对图像先进行腐蚀操作,然后再进行膨胀操作。第一步腐蚀操作可以消除部分亮像素点,然后又通过第二步膨胀操作来将整体的亮像素点恢复到原来区域范围。当然了由于先进行了腐蚀操作,所以图像整体的灰度值是会降低的。
开操作对于二值图像来说可以消除掉一些小的干扰连通域,而不影响整体的大的连通域,解决图像二值化之后噪点过多的问题。还可以用来在纤细点处分离物体,将细小的连接处腐蚀掉再恢复原来的大的连通域。还可以消除连通域的毛刺,在平滑较大连通域边界的同时并不明显改变其面积。
而且,对二值图像进行开操作后剩下的连通域,其形状会逐渐趋向于所使用的结构元素,所以当我们想保留二值图像中的某些连通组件时,可以使用与连通组件形状相似的结构元素。例如可以使用与要保留的水平或竖直方向的直线类似的结构元素,来进行开操作,最终结果就可以将这个直线保留下来,达到对目标形状的提取。
OpenCV中提供了morphologyEx()
这个API进行各种形态学操作,其参数如下:
第一个参数src:输入的进行形态学操作的图像;
第二个参数dst:输出结果图像;
第三个参数op:所选择的形态学操作;
第四个参数kernel:结构元素;
第五个参数anchor:结构元素的锚点;
第六个参数iterations:进行操作的迭代次数;
第七个参数borderType:边缘填充方式,使用默认值即可;
第八个参数borderValue:边缘填充值,使用默认值即可;
当使用开操作时,参数op
我们使用MORPH_OPEN
,具体代码如下:
Mat image1 = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\fill.png");
Mat image_gaus, image_binary, image_gray;
cvtColor(image1, image_gray, COLOR_BGR2GRAY);
GaussianBlur(image_gray, image_gaus, Size(), 1, 1);
adaptiveThreshold(image_gray, image_binary, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 35, 10)