目录
一、预备知识
在讲述本节内容之前,我们自然要先讲讲标题中“形态学”一词的含义。
形态学:原来是生物学的一个分支,研究动物和植物的形态与结构。而数学形态学指的是用来表述图象的表态分量。比如说轮廓、边界、骨架、连通分量等等。典型的形态学应用有细化、修建毛刺等等。
想要理解图像形态学的相关知识,我们需要先理解一些数学集合论相关的知识。假设A、B为集合,U为全集,那么:
并集:,可以理解为二值运算的或(OR)操作
交集:,可以理解为二值运算的与(AND)操作
差集:
补集:,也可写作
,它可以理解为二值运算的非(NOT)操作。
用图像表示更为直观,如下图:
反射:,
是B中坐标(x,y)已被(-x,-y)代替的点集,将原集合相对与其原点旋转180°。
平移:,是集合B相对与点z=(
)的平移。
反射和平移都是相对于B的原点进行定义的。我们依然用更为直观的图像去理解这种数学操作:
二、腐蚀与膨胀
1、腐蚀操作
假设A和B是中的两个集合,B对A的腐蚀(A
B)定义为
,这个公式指出B对A的腐蚀是所有点z的集合,条件是平移z后的B包含于A,并且位移是相对与B的原点定义的。也可将腐蚀等效的写为:
,其中
代表空集。
如果还不好理解,我们用一个例子来解释腐蚀操作。如上图,B中间的这个点为原点,腐蚀操作的步骤为:首先随便移动B,但A集合要完全包含B集合,然后保留B中的原点,这些”原点“所组成的集合就是腐蚀后所得的图像。
腐蚀操作的最大用途就是去掉“毛刺”,去掉特别细的线条。我们可以使用OpenCV来实现这一操作,其API与相关参数如下:
dst = cv2.erode(src,kernel[,anchor[,interations[,borderType[,borderValue]]]])
相关参数如下:
dst:返回值,即腐蚀后得到的结果
src:需要处理的图像
kernel:卷积核,是腐蚀操作时采用的结构类型,是个单通道的数组
anchor:锚点,默认情况是(-1,-1),即核的中心位置
interations:腐蚀的迭代次数
borderType:图像边界的处理方式
borderValue:边界值,一般采用默认值
实践:将下图进行腐蚀处理
import cv2
import numpy as np
img=cv2.imread("black_white.jpg",-1)
cv2.imshow("original",img)
kernel=np.ones((3,1),np.uint8)
erosion = cv2.erode(img,kernel)
cv2.imshow("erosion",erosion)
cv2.imwrite("erosion.jpg",erosion)
cv2.waitKey()
cv2.destroyAllWindows()
腐蚀后的结果如下图,可以发现图片的白色部分横向的瘦了。
2、膨胀操作
假设A和B是的两个集合,B对A的膨胀(A
B)定义为
,类似于腐蚀,这个公式是以B相对于其原点反射并将这以反射平移z为基础的。于是,B对A的膨胀就是
的前景元素与A的至少一个元素重叠,所有位移z的集合,并且要注意位移是相对与B的原点定义的。
如果还不好理解,我们再用一个例子来解释腐蚀操作。如上图,B中间的这个点为原点,膨胀操作的步骤为:首先随便移动B,但A集合要完全包含B的原点,然后保留B中所有元素,这些元素所组成的集合就是膨胀后所得的图像。
膨胀操作最大的用处是,能将毛细部分加粗,起到连接的作用。
dst = cv2.dilate(src,kernel[,anchor[,interations[,borderType[,borderValue]]]])
相关参数如下:
dst:返回值,即膨胀后得到的结果
src:需要处理的图像
kernel:卷积核,是腐蚀操作时采用的结构类型,是个单通道的数组
anchor:锚点,默认情况是(-1,-1),即核的中心位置
interations:腐蚀的迭代次数
borderType:图像边界的处理方式
borderValue:边界值,一般采用默认值
同样,将刚刚那副图像进行膨胀操作的代码如下:
import cv2
import numpy as np
img=cv2.imread("black_white.jpg",-1)
cv2.imshow("original",img)
kernel=np.ones((3,1),np.uint8)
dilation = cv2.dilate(img,kernel)
cv2.imshow("dilation",dilation)
cv2.imwrite("dilation.jpg",dilation)
cv2.waitKey()
cv2.destroyAllWindows()
得到的膨胀结果图如下:
三、OpenCV的形态学函数
dst = cv2.morphologyEx( src ,op ,kernel ,[,anchor[,interations[,borderType[,borderValue]]]])
相关参数如下:
dst:返回值,即膨胀后得到的结果
op:操作类型
src:需要处理的图像
kernel:卷积核,是腐蚀操作时采用的结构类型,是个单通道的数组
anchor:锚点,默认情况是(-1,-1),即核的中心位置
interations:腐蚀的迭代次数
borderType:图像边界的处理方式
borderValue:边界值,一般采用默认值
其中op的选项有腐蚀(cv2.MORPH_ERODE)、膨胀(cv2.MORPH_DILATE)、开运算(cv2.MORPH_OPEN)、闭运算(cv2.MORPH_CLOSE)、礼帽(cv2.MORPH_TOPHAT)、黑帽(cv2.MORPH_BLACKHAT)以及击中击不中操作(cv2.MORPH_HITMISS)
四、开运算与闭运算
1、开运算
结构元B对集合A的开运算(AB)定义为
,首先B对A腐蚀,接着B对腐蚀结果进行膨胀操作。它的作用为使对象轮廓平滑,断开狭窄的间断、消除细的突出物,去除小亮点,从某种意义上来说,是对二值图进行“去噪”。总体上来说,开运算体现出“分开”。
我们拿下面这张图做一个开运算,通过对比原图与结果,帮助大家理解(前者是原图,后者是通过开运算后得到的结果):
import cv2
import numpy as np
img=cv2.imread("test.png",-1)
cv2.imshow("original",img)
#核越大消除的部分越多
kernel=np.ones((11,11),np.uint8)
open = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
cv2.imshow("open",open)
cv2.imwrite("open.jpg",open)
cv2.waitKey()
cv2.destroyAllWindows()
2、闭运算
结构元B对集合A的闭运算(A·B)定义为,首先B对A膨胀,接着B对膨胀结果进行腐蚀操作。它的作用为使对象轮廓平滑,融联狭窄的间断和长细的深沟,去除小孔洞,总体来说,闭运算体现出“联接 ”。
其代码与开运算类似只需要把参数cv2.MORPH_OPEN改为cv2.MORPH_CLOSE,此处略过。
五、礼帽与黑帽操作
1、礼帽
礼帽定义为输入图像与图像开运算得到的结果之差,图像的结果往往是被开运算“去噪”的那些盐噪点构成的集合,以及原图的狭窄间断。这个也很好理解,看看开运算去掉的是什么就明白了。
import cv2
import numpy as np
img=cv2.imread("black_white.jpg",0)
cv2.imshow("original",img)
kernel=np.ones((3,3),np.uint8)
tophat = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
cv2.imshow("tophat",tophat)
cv2.imwrite("tophat.jpg",tophat)
cv2.waitKey()
cv2.destroyAllWindows()
2、黑帽
黑帽则定义为输入图像与图像闭运算得到结果之差,图像的结果往往是被闭运算“去噪”的那些椒噪声所构成的集合,以及闭运算融联的部分。同理,看看闭运算增添了什么就明白了这一操作是获取图像小孔信息。
import cv2
import numpy as np
img=cv2.imread("black_white.jpg",0)
cv2.imshow("original",img)
kernel=np.ones((11,11),np.uint8)
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
cv2.imshow("blackhat",blackhat)
cv2.imwrite("blackhat.jpg",blackhat)
cv2.waitKey()
cv2.destroyAllWindows()