OpenCV(python)一键入门--十九篇(图像形态学函数使用)
1:图像膨胀与腐蚀
import cv2 as cv
import numpy as np
#膨胀和腐蚀
src = cv.imread("D:/coin.jpg")
cv.imshow("input", src)
# 使用3x3 np.ones的结构元素进行膨胀与腐蚀操作
se = np.ones((3, 3), dtype=np.uint8)
dilate = cv.dilate(src, se, None, (-1, -1), 1)
erode = cv.erode(src, se, None, (-1, -1), 1)
cv.imshow("dilate", dilate)
cv.imshow("erode", erode)
cv.waitKey(0)
cv.destroyAllWindows()
1):cv.dilate 膨胀
函数原型:dst=cv.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
image | 输入图像;通道数任意,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F其中之一。 |
dst | 输出与 src 大小和类型相同的图像。 |
kernel | 用于膨胀的结构元素 |
anchor | 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
iterations | 应用扩张的次数。 |
borderType | 像素外插方法 |
borderValue | 边界不变的情况下的边界值 |
其中,像素外插方法,在官网有如下介绍,在这里不再赘述:
膨胀效果:
2):cv.erode 腐蚀
函数原型:dst=cv.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
和膨胀的函数解释类似
src | 输入图像;通道数可以任意,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F之一。 |
dst | 输出与 src 大小和类型相同的图像。 |
kernel | 用于侵蚀的结构元素 |
anchor | 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
iterations | 应用侵蚀的次数。 |
borderType | 像素外插方法,具体请参见上图 |
borderValue | 边界不变的情况下的边界值 |
效果如下:
3):结构元素
第一个demo,我们使用了np.ones直接生成一个3*3,全为1的“结构元素”。其实应对不同的应用场景,选择一个好的结构元素很重要。
import cv2 as cv
import numpy as np
#二值化图像
src = cv.imread("D:/coin.jpg")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("input", binary)
# 使用3x3 “矩形”结构元素
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
dilate = cv.dilate(binary, se, None, (-1, -1), 1)
erode = cv.erode(binary, se, None, (-1, -1), 1)
cv.imshow("dilate", dilate)
cv.imshow("erode", erode)
cv.waitKey(0)
cv.destroyAllWindows()
对于cv.getStructuringElement,函数原型如下:
函数原型:retval=cv.getStructuringElement(shape, ksize[, anchor])
shape | 结构元素形状类型,常见的有矩形,圆形,十字交叉。 |
ksize | 结构元素的大小。 |
anchor | 元素内的锚点位置。默认值( − 1 , − 1 )表示锚在中心。 只有十字形元素的形状取决于锚点位置。其他情况下,anchor 只调节形态操作的结果移动了多少。 |
通常其参数需要视情况调整
常见的结构元素介绍如下:
矩形结构元素: cv.MORPH_RECT | |
十字形结构元素:cv.MORPH_CROSS | |
椭圆结构元素: cv.MORPH_ELLIPSE | 内接矩形为 Rect(0, 0, esize.width, 0.esize.height) 的实心椭圆 |
效果如下:
2:cv.morphologyEx 形态学操作
(在这篇博客中,二值图像分析的案例使用了morphologyEx该函数:OpenCV(python)一键入门--十四篇(二值图像分析入门))
函数原型:dst=cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
src | 源图像。通道的数量可以是任意的。深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。 |
dst | 与源图像大小和类型相同的目标图像。 |
op | 形态学操作的类型 |
kernel | 结构元素。可以用getStructuringElement创建结构元素。 |
anchor | 用内核锚定位置。负值意味着锚点位于内核中心。 |
iterations | 应用腐蚀和膨胀的次数。 |
borderType | 像素外插方法,具体请参照上图 |
borderValue | 边界不变的情况下的边界值。默认值具有特殊含义。 |
形态学操作类型:
MORPH_ERODE | 腐蚀 | 当调用morphologyEx使用MORPH_ERODE类型时,与调用腐蚀函数erode效果相同 |
MORPH_DILATE | 膨胀 | 当调用morphologyEx使用MORPH_DILATE类型时,与调用膨胀函数dilate效果相同 |
MORPH_OPEN | 开运算 | 对图像先进行腐蚀再膨胀,等同于dilate(erode(src,kernal)),开运算对图像的边界进行平滑、去掉凸起等 |
MORPH_CLOSE | 闭运算 | 对图像先进行膨胀在腐蚀,等同于erode(dilate(src,kernal)),闭运算用于填充图像内部的小空洞、填充图像的凹陷等 |
MORPH_GRADIENT | 梯度图 | 用膨胀图减腐蚀图,等同于dilate(src,kernal)−erode(src,kernal),可以用于获得图像中物体的轮廓 |
MORPH_TOPHAT | 顶帽,又称礼帽 | 用原图像减去开运算后的图像,等同于src−open(src,kernal),可以用于获得原图像中比周围亮的区域 |
MORPH_BLACKHAT | 黑帽 | 闭运算图像减去原图像,等同于close(src,kernal)−src,可以用于获取原图像中比周围暗的区域 |
MORPH_HITMISS | 击中击不中变换 | 用于匹配处理图像中是否存在核对应的图像,匹配时,需要确保核矩阵非0部分和为0部分都能匹配,注意该变换只能处理灰度图像。 |
2.1)开操作、闭操作:
import cv2 as cv
import numpy as np
src = cv.imread("D:/morph01.png")
cv.imshow("input", src)
# 高斯模糊去噪
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
dst = cv.GaussianBlur(gray, (9, 9), 2, 2)
binary = cv.adaptiveThreshold(dst, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 45, 15)
# 开操作
se = cv.getStructuringElement(cv.MORPH_RECT, (5, 5), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, se)
#闭操作
#se = cv.getStructuringElement(cv.MORPH_RECT, (5, 5), (-1, -1))
#binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, se)
cv.imshow("binary", binary)
cv.waitKey(0)
cv.destroyAllWindows()
(自适应阈值adaptiveThreshold的介绍在这篇博客中: OpenCV(python)一键入门--十三篇(二值化去噪与图像连通域))
效果如下:
(开操作)
(闭操作)
附素材:
2.2)顶帽
对图像进行开运算,得到的是除去白色噪声的图像,再用原图减去开运算后的图像,得到的是图像的白色噪声。
import cv2 as cv
import numpy as np
src = cv.imread("D:/cells.jpg")
cv.imshow("input", src)
# 高斯模糊去噪
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# 顶帽操作
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_TOPHAT, se)
cv.imshow("binary", binary)
cv.waitKey(0)
cv.destroyAllWindows()
效果如下:
附素材:
2.3)黑帽
对图像进行闭运算,得到的是除去黑色噪声的图像,再用原图减去闭运算后的图像,得到的是图像的黑色噪声。
import cv2 as cv
import numpy as np
src = cv.imread("D:/morph01.png")
cv.imshow("input", src)
# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# 黑帽操作
se = cv.getStructuringElement(cv.MORPH_RECT, (9, 9), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, se)
cv.imshow("black hat", binary)
cv.waitKey(0)
cv.destroyAllWindows()
效果如下:
2.4)图像梯度
import cv2 as cv
src = cv.imread("ma.jpg")
cv.imshow("input", src)
# 形态学梯度 - 基本梯度
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
basic = cv.morphologyEx(src, cv.MORPH_GRADIENT, se)
cv.imshow("basic gradient", basic)
# 外梯度
dilate = cv.morphologyEx(src, cv.MORPH_DILATE, se)
exteral = cv.subtract(dilate, src)
cv.imshow("external gradient", exteral)
# 内梯度
erode = cv.morphologyEx(src, cv.MORPH_ERODE, se)
interal = cv.subtract(src, erode)
cv.imshow("interal gradient", interal)
cv.waitKey(0)
cv.destroyAllWindows()
· 基本梯度
基本梯度是用 膨胀后的图像 减去 腐蚀后的图像 得到差值图像,称为梯度图像
· 内部梯度
是用 原图像 减去 腐蚀之后的图像 得到差值图像,称为图像的内部梯度
· 外部梯度
膨胀后的图像 减去 原来的图像 得到的差值图像,称为图像的外部梯度。
效果如图:
2.*)击中击不中
import cv2 as cv
import numpy as np
src = cv.imread("D:/cross.png")
cv.imshow("input", src)
# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
# 击中击不中
se = cv.getStructuringElement(cv.MORPH_CROSS, (11, 11), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_HITMISS, se)
cv.imshow("demo", binary)
cv.waitKey(0)
cv.destroyAllWindows()
效果如下:
附素材
- 点赞
- 收藏
- 关注作者
评论(0)