膨胀与腐蚀
膨胀
与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是1。会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。
作用:
- 对象的大小增加一个像素(3×3)
- 平滑对象边缘
- 减少或填充对象之间的边缘
cv2.dilate
使用特定的结构元素膨胀图像
dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) -> dst
- src:表示输入的图片
- kernel:表示膨胀所用的结构元素的大小
- iteration:表示迭代的次数
示例
对图像二值化并膨胀
def dilate(image):
"""膨胀"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU) # 二值化图像
cv.imshow("binary", binary)
# 构造5×5的结构元素,可选十字形、菱形、方形和X型等
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.dilate(binary, kernel=kernel) # 膨胀
cv.imshow("dilate", dst)
结果
注意: 二值化图像的膨胀和腐蚀要注意是白色还是黑色作为前景
示例
对彩图进行膨胀
def dilate_color(image):
"""彩图膨胀"""
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.dilate(image, kernel=kernel) # 膨胀
cv.imshow("dilate", dst)
结果:
腐蚀
卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素就保持原来的像素值,否则就变为零。 根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。
作用:
- 对象的大小减少一个像素(3×3)
- 平滑对象边缘
- 弱化或者分割对象之间的半岛型连接
cv2.erode
使用特定的结构元素腐蚀图像
erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) -> dst
- src:表示输入的图片
- kernel:表示腐蚀所用的结构元素的大小
- iteration:表示迭代的次数
示例
对图像二值化并腐蚀
def erode(image):
"""腐蚀"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU) # 二值化图像
cv.imshow("binary", binary)
# 构造5×5的结构元素,可选十字形、菱形、方形和X型等
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.erode(binary, kernel=kernel) # 腐蚀
cv.imshow("erode", dst)
结果
示例
对彩图进行腐蚀
def erode_color(image):
"""彩图腐蚀"""
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.erode(image, kernel=kernel) # 腐蚀
cv.imshow("erode", dst)
结果
参考链接:
形态学操作
cv2.morphologyEx
执行形态学操作
- 开运算:先进行腐蚀再进行膨胀就叫做开运算,它被用来去除噪声。
- 闭运算:先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。
- 顶帽:原图像与开操作之间的差值图像
- 黑帽:闭操作与原图像之间的差值图像
- 形态学梯度:其实就是一幅图像膨胀与腐蚀的差别。 结果看上去就像前景物体的轮廓
- 基本梯度:膨胀后图像减去腐蚀后图像得到的差值图像。
- 内部梯度:用原图减去腐蚀图像得到的差值图像。
- 外部梯度:膨胀后图像减去原图像得到的差值图像
morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) -> dst
- src:输入图像
- op:操作类型
- MORTH_OPEN:函数做开运算
- MORTH_CLOSE:函数做闭运算
- MORTH_GRADIENT:函数做形态学梯度运算
- MORTH_TOPHAT:函数做顶帽运算
- MORTH_BLACKHAT:函数做黑帽运算
- MORTH_DILATE :函数做膨胀运算
- MORTH_ERODE:函数做腐蚀运算
- kernel :内核类型,用getStructuringElement函数得到。
- 例如:采用开操作,kernel为(1, 15),提取垂直线,kernel为(15, 1),提取水平线
开操作
先进行腐蚀再进行膨胀就叫做开运算,它被用来去除噪声。
示例
开操作
def open_image(image):
"""开操作"""
# print(image.shape)
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) # 二值化图像
cv.imshow("binary", binary)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel=kernel) # 执行形态学操作(此时为开操作)
cv.imshow("open_image", dst)
结果
闭操作
先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。
示例
闭操作
def close_image(image):
"""闭操作"""
# print(image.shape)
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU) # 二值化图像
cv.imshow("binary", binary)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel=kernel) # 执行形态学操作(此时为闭操作)
cv.imshow("close_image", dst)
结果:
顶帽
原图像与开操作之间的差值图像
d
s
t
=
t
o
p
h
a
t
(
s
r
c
,
r
l
r
m
e
n
t
)
=
s
r
c
−
o
p
e
n
(
s
r
c
,
r
l
r
m
e
n
t
)
dst = tophat(src,rlrment) = src - open(src,rlrment)
dst=tophat(src,rlrment)=src−open(src,rlrment)
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
示例
def tophat_image(image):
"""顶帽操作"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel=kernel) # 执行形态学操作(此时为顶帽操作)
cv.imshow("tophat_image", dst)
结果:
示例
直接二值化图像
发现右下角细节缺失
发现原图右下角的字体与背景的亮度都有些高,所以会出现这种情况,现在想让字体与背景分离出来,我们可以用顶帽操作对前景进行明亮化。
因此先进行顶帽再二值化
def comprehensive_example(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (30, 30)) # 构造30×30的方形结构元素
dst = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel=kernel) # 执行形态学操作(此时为顶帽操作)
cv.imshow("tophat_image", dst)
ret, binary = cv.threshold(dst, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) # 二值化图像
cv.imshow("binary", binary)
结果:
黑帽
闭操作与原图像之间的差值图像
d
s
t
=
b
l
a
c
k
h
a
t
(
s
r
c
,
r
l
r
m
e
n
t
)
=
c
l
o
s
e
(
s
r
c
,
r
l
r
m
e
n
t
)
−
s
r
c
dst = blackhat(src,rlrment) = close(src,rlrment) - src
dst=blackhat(src,rlrment)=close(src,rlrment)−src
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
所以,黑帽运算用来分离比邻近点暗一些的斑块。可以得到轮廓效果图。
示例
def blackhat_image(image):
"""黑帽操作"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.morphologyEx(gray, cv.MORPH_BLACKHAT, kernel=kernel) # 执行形态学操作(此时为黑帽操作)
cv.imshow("blackhat_image", dst)
结果:
形态学梯度
本质上就是对图像的边缘提取,也可以说是膨胀的结果减去腐蚀的结果
示例
def gardient_image(image):
"""形态学梯度操作"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) # 构造5×5的方形结构元素
dst = cv.morphologyEx(gray, cv.MORPH_GRADIENT, kernel=kernel) # 执行形态学操作(此时为形态学梯度操作)
cv.imshow("blackhat_image", dst)
结果:
参考链接: