内容简介:形态变化是基于图像中物体的形态进行一些简单变换,通常在二值化的图像上进行,包括侵蚀/扩张/开运算/闭运算等操作,每种操作还可以设置一个形态学的内核,决定各种操作的表现形式,还是来理解一下官方文档的例子吧。侵蚀的基本思想就像土壤侵蚀一样,侵蚀着物体前景色(白色)的边界。形态学处理内核在图像窗口中滑动,只有当内核下的所有像素都为1时,原始图像中的像素(1或0)才会被视为1,否则它将被侵蚀(变为零)。因此最终的表现就是,所有靠近前景色边界的像素都将而被丢弃,内核尺寸越大丢的越多,即白色的区域会减小。这种操作对于消
形态变化是基于图像中物体的形态进行一些简单变换,通常在二值化的图像上进行,包括侵蚀/扩张/开运算/闭运算等操作,每种操作还可以设置一个形态学的内核,决定各种操作的表现形式,还是来理解一下官方文档的例子吧。
1.侵蚀
侵蚀的基本思想就像土壤侵蚀一样,侵蚀着物体前景色(白色)的边界。形态学处理内核在图像窗口中滑动,只有当内核下的所有像素都为1时,原始图像中的像素(1或0)才会被视为1,否则它将被侵蚀(变为零)。
因此最终的表现就是,所有靠近前景色边界的像素都将而被丢弃,内核尺寸越大丢的越多,即白色的区域会减小。这种操作对于消除小的白色噪声(如我们在色彩空间一章中所看到的)、分离两个连接的对象等非常有用。
下面的例子中,使用一个5x5的内核,来对图像进行侵蚀操作:
def pltShow(img): dst = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(dst) def testErosion(): img = cv2.imread('test.png', 0) kernel = np.ones((5, 5), np.uint8) erosion = cv2.erode(img, kernel, iterations=1) plt.subplot(121),pltShow(img),plt.title("Origin") plt.subplot(122),pltShow(erosion),plt.title("Erosion") plt.show()
这个操作比较好理解,没啥可说的。
2.膨胀
膨胀的效果正好与侵蚀相反,如果内核下至少有一个像素为“1”,则像素元素为“1”。因此,它增加了图像中的白色区域(前景对象)的大小。
在去除噪音的时候,一般采用的操作是侵蚀之后再膨胀。侵蚀消除了白色的噪音,但它也缩小了物体,所以需要通过膨胀来还原。而噪音已经在侵蚀的过程中消失,膨胀的时候也不会再出现。例子:
3.开运算
开运算就是2节中讲到的先侵蚀再膨胀的操作,可以认为是个语法糖吧。
def testOpen(): img = cv2.imread("test2.png", 0) kernel = np.ones((5,5), np.uint8) erosion = cv2.erode(img, kernel, iterations=1) dilateAfterErosion = cv2.dilate(erosion, kernel, iterations=1) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) plt.subplot(131), pltShow(img), plt.title("Origin") plt.subplot(132), pltShow(dilateAfterErosion), plt.title("DilateAfterErosion") plt.subplot(133), pltShow(opening), plt.title("Opening") plt.show()
4.闭运算
顾名思义,开运算与闭运算是相反的语法糖——先膨胀再侵蚀,其作用也可以想象到了,可以填充上物体内部的杂点。
def testClose(): img = cv2.imread("test3.png", 0) kernel = np.ones((5,5), np.uint8) dilate = cv2.dilate(img, kernel, iterations=1) erosionAfterDilate = cv2.erode(dilate, kernel, iterations=1) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) plt.subplot(131), pltShow(img), plt.title("Origin") plt.subplot(132), pltShow(erosionAfterDilate), plt.title("ErosionAfterDilate") plt.subplot(133), pltShow(closing), plt.title("Closing") plt.show()
5.形态梯度
出现梯度变化的地方前景色保留,其它的去掉,用于检测边缘
def testGradient(): img = cv2.imread('test.png', 0) kernel = np.ones((2, 2), np.uint8) gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) plt.subplot(121), pltShow(img), plt.title("Origin") plt.subplot(122), pltShow(gradient), plt.title("Gradient") plt.show()
6.tophat
文档中的描述: =tophat( , )= −open( , )
def testTopHat(): img = cv2.imread('test.png', 0) kernel = np.ones((9, 9), np.uint8) tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) plt.subplot(121), pltShow(img), plt.title("Origin") plt.subplot(122), pltShow(tophat), plt.title("Gradient") plt.show()
7.black hat
=blackhat( , )=close( , )−
def testBlackHat(): img = cv2.imread('test.png', 0) kernel = np.ones((9, 9), np.uint8) blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) plt.subplot(121), pltShow(img), plt.title("Origin") plt.subplot(122), pltShow(blackhat), plt.title("BlackHat") plt.show()
8.自定义内核结构
前面的例子中,变换内核矩阵是用numpy手动生成的n*n矩阵,代表规则的矩形内核,opencv提供了一些函数来获取其它形态的内核,如:
# Rectangular Kernel >>> cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]], dtype=uint8) # Elliptical Kernel >>> cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) array([[0, 0, 1, 0, 0], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [0, 0, 1, 0, 0]], dtype=uint8) # Cross-shaped Kernel >>> cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) array([[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 1, 1], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]], dtype=uint8)
一些形态变换的示例 http://homepages.inf.ed.ac.uk/rbf/HIPR2/morops.htm
以上所述就是小编给大家介绍的《Opencv图像处理系列(五)—— 形态变化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Service Mesh 形态刍议
- 关于二叉树形态的推导
- 一起来学opencv(四):形态转换
- 敏捷DoD和DoR的多种形态
- opencv中的图像形态学——腐蚀膨胀
- 深度 | 解读神经形态计算:从基本原理到实验验证
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。