Python OpenCV从入门到精通学习日记:图像的形态学操作
前言
图像形态学是图像处理中的一个重要分支,主要关注图像中物体的形状和结构。通过形态学操作,我们可以对图像进行有效的分析和处理,例如图像的腐蚀与膨胀、开运算与闭运算等。腐蚀和膨胀是图像形态学中的两种核心操作,通过这两种操作可以清除或强化图像中的细节。合理使用腐蚀和膨胀,还可以实现图像开运算、闭运算、梯度运算、顶帽运算和黑帽运算等极具特点的操作。接下来开始学习吧!!!
因为内容较多,我列举了目录,如下:
图像的形态学操作
- Python OpenCV从入门到精通学习日记:图像的形态学操作
- 前言
- 1 腐蚀
- 2 膨胀
- 3 开运算
- 4 闭运算
- 5 形态学运算
- 5.1 梯度运算
- 5.2 顶帽运算
- 5.3 黑帽运算
- 小结
1 腐蚀
腐蚀操作可以让图像沿着自己的边界向内收缩。OpenCV通过“核”来实现收缩计算。“核”的英文名为kernel,在形态学中可以理解为“由n个像素组成的像素块”,像素块包含一个核心(核心通常在中央位置,也可以定义在其他位置)。像素块在图像的边缘移动,在移动过程中,核会将图像边缘那些与核重合但又没有越过核心的像素点都抹除,效果类似图12.1所示的过程,就像削土豆皮一样,将图像一层一层地“削薄”。(这里借用书上原图)
OpenCV将腐蚀操作封装成erode()
方法。
dst = cv2.erode(src, kernel, anchor, iterations,borderType, borderValue)
src: 输入图像。
kernel: 腐蚀使用的核,可以自定义或使用OpenCV提供的预设。
anchor:可选参数,核的锚点位置。
iterations: 腐蚀操作的迭代次数,默认为1。
borderType: 边界处理方式,默认为cv2.BORDER_CONSTANT。
borderValue: 边界值,默认为0。
图像经过腐蚀操作之后,可以抹除一些外部的细节,如图12.2所示是一个卡通小蜘蛛,如果用一个5×5的像素块作为核对小蜘蛛进行腐蚀操作,可以得到如图12.3所示的结果。小蜘蛛的腿被当成外部细节抹除了,同时小蜘蛛的眼睛变大了,因为核从内部也“削”了一圈。
在OpenCV做腐蚀或其他形态学操作时,通常使用numpy模块来创建核数组。
比如:
import numpy as np
k = np.ones((5, 5), np.uint8)
这两行代码什么意思可以去看我前面的文章:链接: 苦学Opencv的第三天:像素的操作
这个数组作为erode()方法的核参数。除了5×5的结构,还可以使用3×3、9×9、11×11等结构,行列数越大,计算出的效果就越粗糙,行列数越小,计算出的效果就越精细。
代码示例:
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.png', 0)
# 创建结构元素
kernel = np.ones((3,3), np.uint8)
# 腐蚀操作
eroded_img = cv2.erode(img, kernel)
# 显示结果
cv2.imshow('Eroded Image', eroded_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下:
🌟可以看出,仙人掌的刺并没有因此消失,但是刺明显变得模糊不清了。
2 膨胀
膨胀操作与腐蚀操作正好相反,它通过使用核来“扩展”图像的边界。
OpenCV将膨胀操作封装成dilate()
方法。
dst = cv2.dilate(src, kernel, anchor, iterations,borderType, borderValue)
参数说明:
src:原始图像。
kernel:膨胀使用的核。
anchor:可选参数,核的锚点位置。
iterations:可选参数,腐蚀操作的迭代次数,默认值为1。
borderType:可选参数,边界样式,建议默认。
borderValue:可选参数,边界值,建议默认。
返回值说明:
dst:经过膨胀之后的图像。
膨胀的效果也正好是与腐蚀相反。这里不多加介绍了,直接放个图像,大家就知道什么意思了。
代码示例:
# 膨胀操作
import cv2
import numpy as np
# 读取图像
img = cv2.imread('xianrenzhang.png')
cv2.imshow("img",img)
# 创建结构元素
kernel = np.ones((10,10), np.uint8)
# 腐蚀操作
dilated_img = cv2.dilate(img, kernel)
# 显示结果
cv2.imshow('Dilated Image', dilated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下:
🌟这里可以看出,过度膨胀后的图像就好像近视眼的世界,图像变得非常模糊。
3 开运算
开运算是先进行腐蚀操作,再进行膨胀操作,开运算可以用来抹除图像外部的细节(或者噪声)。
我们举个例子,这是一个二叉树:
我们先对齐进行腐蚀操作,那么连接的细线会因为腐蚀而消失
随后我们进行膨胀操作
🌟从结果中可以明显地看出:经过开运算之后,二叉树中的连接线消失了,只剩下光秃秃的节点。因为连接线被核当成“细节”抹除了,所以利用检测轮廓的方法可以统计二叉树节点数量,也就是说在某些情况下,开运算的结果还可以用来做数量统计。
4 闭运算
闭运算是先进行膨胀操作,再进行腐蚀操作,闭运算可以抹除图像内部的细节(或者噪声)。
闭运算正好与开运算相反。我们在这举个例子:假设有只身上有斑点的小蜘蛛
我们先对其膨胀
在进行腐蚀
🌟从结果中可以明显地看出:经过闭运算后,小蜘蛛身上的花纹都被抹除了,就连眼睛也被当成“细节”抹除了。闭运算除了会抹除图像内部的细节,还会让一些离得较近的区域合并成一块区域。
5 形态学运算
除了基本的腐蚀和膨胀操作,OpenCV还提供了梯度运算、顶帽运算和黑帽运算等高级形态学操作。OpenCV 提 供 了 一 个morphologyEx()
形态学方法,包含所有常用的运算,其语法如下:
dst = cv2.morphologyEx(src, op, kernel, anchor,iterations, borderType, borderValue)
参数说明:
src:原始图像。
op:操作类型,具体值如表所示。
kernel:操作过程中使用的核。
anchor:可选参数,核的锚点位置。
iterations:可选参数,迭代次数,默认值为1。
borderType:可选参数,边界样式,建议默认。
borderValue:可选参数,边界值,建议默认。
返回值说明:
dst:操作之后得到的图像。
参数值 | 含义 |
---|---|
CV2.MORPH_ERODE | 腐蚀操作 |
CV2.MORPHDILATE | 膨胀操作 |
CV2.MORPH_OPEN | 开运算,先腐蚀后膨胀 |
CV2.MORPHCLOSE | 闭运算,先胀后腐蚀 |
CV2.MORPH_GRADIENT | 梯度运算,膨胀图减腐蚀图 |
CV2.MORPHTOPHAT | 顶幅运算,原始图减开运算图 |
CV2.MORPHBLACKHAT | 黑幅运算,闭运算图减原始图 |
morphologyEx()方法实现的腐蚀、膨胀、开运算和闭运算效果与前文中介绍的效果完全一致,这里不再赘述,下面我们学习3个特点鲜明的操作:梯度运算、顶帽运算和黑帽运算。
5.1 梯度运算
这里的梯度是指图像梯度,可以简单地理解为像素的变化程度。如果几个连续的像素,其像素值跨度越大,则梯度值越大。
梯度运算是通过膨胀图像减去原始图像来突出显示图像的边缘。
通俗的讲,梯度运算的运算过程就是:让原图的膨胀图减去腐蚀图,因为膨胀图比原图大,腐蚀图比原图小,利用腐蚀图将膨胀图掏空,就得到了原图的轮廓图。当然,这只能等到一个大概的轮廓图,是不精准的。
具体的代码只是在前面的代码中修改函数为morphology()
,在这里不再赘述。
5.2 顶帽运算
顶帽运算是原始图像减去开运算后的图像,用于提取图像的外部细节。
5.3 黑帽运算
黑帽运算是闭运算后的图像减去原始图像,用于提取图像的内部细节。
代码示例:
# 梯度运算
gradient_img = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# 顶帽运算
tophat_img = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# 黑帽运算
blackhat_img = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
# 显示结果
cv2.imshow('Gradient Image', gradient_img)
cv2.imshow('Top Hat Image', tophat_img)
cv2.imshow('Black Hat Image', blackhat_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
小结
通过今天的学习,我们掌握了图像形态学的基本操作,这些操作对于图像分析和特征提取非常有用。明天继续学习图形检测!!!
大家在实践中遇到任何问题,欢迎在评论区讨论交流。明天见!