形态学操作是基于形状的一系列图像处理操作。
形态学操作集合
膨胀(Dilate)
对图像中的高亮部分进行膨胀,是求局部最大值的操作,可以消除一些细小的暗点和暗线。
腐蚀(erode)
对原图中的高亮部分进行腐蚀,是求局部最小值的操作,可以消除一些细小的亮点和亮线。
形态学梯度(Morphological Gradient)
是膨胀图与腐蚀图之差, 可以用来保留物体的边缘轮廓。
开运算(Opening Operation)
先腐蚀后膨胀,在消除一些细小的亮点和亮线、平滑较大物体的边界的同时并不明显改变其面积。
闭运算(Closing Operation)
先膨胀后腐蚀,在消除一些细小的暗点和暗线的同时并不明显改变其面积。
顶帽运算(Top Hat)
原图与开运算的结果图之差,可以分离比邻近点亮一些的斑块。
黑帽运算(Black Hat)
闭运算的结果图与原图之差,可以分离比邻近点暗一些的斑块。
获取形态学运算的卷积核
一般使用 getStructuringElemen() 函数,返回指定形状和尺寸的形态学卷积核。
函数原型:
def getStructuringElement(shape, ksize, anchor=None)
参数:
-
shape:表示卷积核的形状,有如下三种:
矩形:MORPH_RECT = 0
交叉形::MORPH_CROSS = 1
椭圆形::MORPH_ELLIPSE = 2
-
ksize:表示卷积核的尺寸
-
anchor:表示卷积核锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形卷积核的形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。
使用矩形卷积核进行形态学处理:
使用交叉形卷积核进行形态学处理:
使用椭圆形卷积核进行形态学处理:
膨胀
函数原型:
def dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
参数:
-
src:输入图像,即源图像,通道数量任意
-
kernel:膨胀操作的核,可以使用getStructuringElement()函数获取
-
dst:输出的目标图像
-
anchor:锚的位置,其有默认值(-1,-1),表示锚位于中心
-
iterations:迭代使用erode()函数的次数,默认值为1
-
borderType:用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT
-
borderValue:当边界为常数时的边界值,有默认值morphologyDefaultBorderValue()
腐蚀
函数原型:
def erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
参数:
-
src:输入图像,即源图像,通道数量任意
-
kernel:膨胀操作的核,可以使用getStructuringElement()函数获取
-
dst:输出的目标图像
-
anchor:锚的位置,其有默认值(-1,-1),表示锚位于中心
-
iterations:迭代使用erode()函数的次数,默认值为1
-
borderType:用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT
-
borderValue:当边界为常数时的边界值
形态学处理
函数原型:
def morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
参数:
-
src:输入图像,即源图像,通道数量任意
-
op:表示形态学运算的类型,可以是如下之一的标识符:
MORPH_OPEN – 开运算(Opening operation)
MORPH_CLOSE – 闭运算(Closing operation)
MORPH_GRADIENT -形态学梯度(Morphological gradient)
MORPH_TOPHAT - “顶帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
-
kernel:膨胀操作的核,可以使用getStructuringElement()函数获取
-
dst:输出的目标图像
-
anchor:锚的位置,其有默认值(-1,-1),表示锚位于中心
-
iterations:迭代使用erode()函数的次数,默认值为1
-
borderType:用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT
-
borderValue:当边界为常数时的边界值
效果对比
使用 5 × 5 5 \times 5 5×5的卷积核进行形态学处理:
![](https://i-blog.csdnimg.cn/blog_migrate/36791ed4ccdc8a9bf8ae60fad15bc5a2.png)
使用 9 × 9 9 \times 9 9×9的卷积核进行形态学处理:
![](https://i-blog.csdnimg.cn/blog_migrate/c878ccb6b0baf471186091d749f17bcb.png)
import cv2
def process(x):
k = cv2.getTrackbarPos('ksize', 'process')
MorphShapes = cv2.getTrackbarPos('MorphShapes', 'process')
if k % 2 == 0:
return
kernel = cv2.getStructuringElement(MorphShapes,(k, k))
dilate = cv2.dilate(gray, kernel)
close = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
erode = cv2.erode(gray, kernel)
open_o = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
gradient = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
top_hat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel)
black_hat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('dilate', dilate)
cv2.imshow('close', close)
cv2.imshow('erode', erode)
cv2.imshow('open', open_o)
cv2.imshow('gradient', gradient)
cv2.imshow('top_hat', top_hat)
cv2.imshow('black_hat', black_hat)
MorphShapes = 0
ksize = 3
cv2.namedWindow('process')
img = cv2.imread("./91_frame.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('process', img)
cv2.createTrackbar('ksize', 'process', ksize, 25, process)
cv2.createTrackbar('MorphShapes', 'process', MorphShapes, 2, process)
process(0)
if cv2.waitKey(0) == 27:
cv2.destroyAllWindows()
经过形态学处理之后的边缘检测效果对比:
原图 / 膨胀后边缘检测
边缘检测 / 闭运算后边缘检测