1. 侵蚀
侵蚀的基本思想就像土壤侵蚀一样,它侵蚀了前景物体的边界(始终尽量保持前景为白色)。那么它有什么作用呢?内核在图像中滑动(如在 2D 卷积中)。仅当内核下的所有像素都为 1 时,原始图像中的像素(1 或 0)才会被视为 1,否则它会被侵蚀(使其为零)。所以发生的事情是,根据内核的大小,边界附近的所有像素都将被丢弃。因此,前景对象的厚度或大小会减少,或者只是图像中的白色区域会减少。它对于去除小的白噪声、分离两个连接的对象等很有用。
python中用法:
dst = cv.erode( src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )
参数 | 描述 |
---|---|
src | 输入图片矩阵 |
dst | 输出图片矩阵 |
kernel | 用于侵蚀的结构元素;如果 element=Mat(),则使用 3 x 3 矩形结构元素。可以使用 getStructuringElement 创建内核。 |
anchor | 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
iterations | 应用侵蚀的次数 |
borderType | 像素外插方法,参见 BorderTypes。不支持 BORDER_WRAP。 |
borderValue | 边界不变的情况下的边界值 |
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8) # 自定义内核
erosion = cv.erode(img,kernel,iterations = 1)
plt.subplot(1, 2, 1), plt.imshow(img, 'gray'), plt.title("Original")
plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(erosion, 'gray'), plt.title("Erosion")
plt.xticks([]), plt.yticks([])
plt.show()
2.扩张
它与侵蚀正好相反。这里,如果内核下至少一个像素为“1”,则像素元素为“1”。所以它增加了图像中的白色区域或前景对象的大小增加。通常,在去除噪声等情况下,腐蚀之后是膨胀。因为,侵蚀去除了白噪声,但它也缩小了我们的对象。所以我们扩张它。由于噪音消失了,它们不会回来,但我们的对象区域会增加。它也可用于连接对象的损坏部分。
python中用法:
dst = cv.dilate( src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )
参数 | 描述 |
---|---|
src | 输入图片矩阵 |
dst | 输出图片矩阵 |
kernel | 用于侵蚀的结构元素;如果 element=Mat(),则使用 3 x 3 矩形结构元素。可以使用 getStructuringElement 创建内核。 |
anchor | 元素内锚点的位置;默认值 (-1, -1) 表示锚点位于元素中心。 |
iterations | 应用膨胀的次数 |
borderType | 像素外插方法,参见 BorderTypes。不支持 BORDER_WRAP。 |
borderValue | 边界不变的情况下的边界值 |
3. 形态变换
morphologyEx()执行高级形态变换。函数 cv::morphologyEx 可以使用腐蚀和膨胀作为基本操作来执行高级形态变换。任何操作都可以就地完成。在多通道图像的情况下,每个通道都是独立处理的。
python中用法:
dst = cv.morphologyEx( src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]] )
参数 | 描述 |
---|---|
src | 输入图片矩阵 |
dst | 输出图片矩阵 |
op | 形态操作的类型,参见 MorphTypes |
kernel | 结构元素。它可以使用 getStructuringElement 创建。 |
anchor | 用内核锚定位置。负值表示anchor位于内核中心。 |
iterations | 应用腐蚀和膨胀的次数。 |
borderType | 像素外插方法,参见 BorderTypes。不支持 BORDER_WRAP。 |
borderValue | 边界不变的情况下的边界值 |
MorphTypes
类型 | 描述 |
---|---|
MORPH_ERODE Python: cv.MORPH_ERODE | 参考erode |
MORPH_DILATE Python: cv.MORPH_DILATE | 参考dilate |
MORPH_OPENPython: cv.MORPH_OPEN | 开运算 d s t = o p e n ( s r c , e l e m e n t ) = d i l a t e ( e r o d e ( s r c , e l e m e n t ) ) dst=open(src,element)=dilate(erode(src,element)) dst=open(src,element)=dilate(erode(src,element)) |
MORPH_CLOSE Python: cv.MORPH_CLOSE | 闭运算 d s t = c l o s e ( s r c , e l e m e n t ) = e r o d e ( d i l a t e ( s r c , e l e m e n t ) ) dst=close(src,element)=erode(dilate(src,element)) dst=close(src,element)=erode(dilate(src,element)) |
MORPH_GRADIENT Python: cv.MORPH_GRADIENT | 形态梯度 d s t = m o r p h g r a d ( s r c , e l e m e n t ) = d i l a t e ( s r c , e l e m e n t ) − e r o d e ( s r c , e l e m e n t ) dst=morph_grad(src,element)=dilate(src,element)−erode(src,element) dst=morphgrad(src,element)=dilate(src,element)−erode(src,element) |
MORPH_TOPHAT Python: cv.MORPH_TOPHAT | 顶帽 d s t = t o p h a t ( s r c , e l e m e n t ) = s r c − o p e n ( s r c , e l e m e n t ) dst=tophat(src,element)=src−open(src,element) dst=tophat(src,element)=src−open(src,element) |
MORPH_BLACKHAT Python: cv.MORPH_BLACKHAT | 黑帽 d s t = b l a c k h a t ( s r c , e l e m e n t ) = c l o s e ( s r c , e l e m e n t ) − s r c dst=blackhat(src,element)=close(src,element)−src dst=blackhat(src,element)=close(src,element)−src |
MORPH_HITMISS Python: cv.MORPH_HITMISS | “命中或未命中” .- 仅支持 CV_8UC1 二进制图像。可以在文档中找到教程 |
3.1 开运算
开运算只是侵蚀后膨胀的另一个名称。正如我们上面所解释的,它在消除噪声方面很有用。这里我们使用函数cv.morphologyEx()
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
3.2 闭运算
闭运算与开运算、膨胀和侵蚀相反。它可用于关闭前景对象内的小孔或对象上的小黑点。
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
3.3 形态梯度
这是图像膨胀和腐蚀之间的区别。结果看起来像是图像的轮廓
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
3.4 顶帽
它是输入图像和输入图像开运算之间的差异。下面的例子是针对一个9x9的内核做的。
kernel = np.ones((9, 9), np.uint8)
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)
3.5 黑帽
它是输入图像和输入图像的闭运算之间的差异。
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
结构元素
在前面的例子中,我们在Numpy的帮助下手动创建了一个结构化元素。它是长方形的。但在某些情况下,你可能需要椭圆/圆形的内核。所以为了这个目的,OpenCV有一个函数,cv.getStructuringElement()。你只需传递内核的形状和大小,就可以得到所需的内核
# Rectangular Kernel,矩形内核
>>> cv.getStructuringElement(cv.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,椭圆内核
>>> cv.getStructuringElement(cv.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,十字内核
>>> cv.getStructuringElement(cv.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)