数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:腐蚀和膨胀、开运算和闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换等。
首先呢, 数学形态学并不是什么高大上的概念. 数学形态学两个最基本的操作是腐蚀 跟膨胀. 利用数学形态学, 我们可以实现如下操作:
例如我们确定好这个核的尺寸为3*3
. 在opencv中核又被称之为结构元素。
用结构元素与其覆盖的二值图像做与 and操作 如果都为1,结果图像的该像素为1。否则为0。
简单来讲, 如果一个点周边所有点与其本身, 只要这里面有一个0, 它就会被视作为0.
如何选取合适的核?
这个根据图像的图像质量, 分辨率, 应用场景不同, 因图而异。 你需要去尝试取不同的值。
那么我们执行腐蚀操作, 最直观的感觉就是二值化图像向内缩减了一圈.
如果你取的核越大, 腐蚀效果越强.除此之外,你可以迭代多次。
'''
数学形态学 腐蚀 erorsion
'''
import cv2
import numpy as np
# 读入灰度图
img = cv2.imread("dao-bin.png", flags=cv2.IMREAD_GRAYSCALE)
# 创建 核
kernel = np.ones((5,5), np.uint8)
# 腐蚀
erorsion_img = cv2.erode(img, kernel, iterations=1)
cv2.imwrite('dao_erorsion_k5.png', np.hstack((img, erorsion_img)))
具体运算过程
假如我们使用的是3*3
的核(有时也被称之为结构元素). 用核与其覆盖的二值图像做或 or操作
如果周边与其自身任意一个点为1,结果图像的该像素为1, 否则为0。
直观效果, 就是图像向外扩增一圈。
膨胀我们要使用dilate
函数.
'''
数学形态学 膨胀 dilate
'''
import cv2
import numpy as np
# 读入灰度图
img = cv2.imread("dao-bin.png", flags=cv2.IMREAD_GRAYSCALE)
# 创建 核
kernel = np.ones((5,5), np.uint8)
# 膨胀
dilate_img = cv2.dilate(img, kernel, iterations=1)
cv2.imwrite('dao_dilate_k5.png', np.hstack((img, dilate_img)))
开运算(opening) 等于对图像先进行腐蚀(erode) 然后进行膨胀(dilate).
开运算其主要作用与腐蚀相似,与腐蚀操作相比,具有可以基本保持目标原有大小不变的优点。
通常用于去除小粒噪声。
'''
数学形态学 开运算 opening
'''
import cv2
import numpy as np
# 迭代次数
iter_time = 4
# 读入灰度图
img = cv2.imread("dao-bin.png", flags=cv2.IMREAD_GRAYSCALE)
# 创建 核
kernel = np.ones((5,5), np.uint8)
# 开运算
opening_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=iter_time)
cv2.imwrite('dao_opening_k5_iter%d.png'%(iter_time), np.hstack((img, opening_img)))
闭运算(closing) 是先对图像进行膨胀, 然后进行腐蚀操作.
闭运算用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。
关于消除内部细小空洞的部分,我们可以看官网的示例:
'''
数学形态学 闭运算 closing
'''
import cv2
import numpy as np
# 迭代次数
iter_time = 1
# 读入灰度图
img = cv2.imread("dao-bin.png", flags=cv2.IMREAD_GRAYSCALE)
# 创建 核
kernel = np.ones((5,5), np.uint8)
# 闭运算
closing_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=iter_time)
cv2.imwrite('dao_closing_k5_iter%d.png'%(iter_time), np.hstack((img, closing_img)))
数学形态学梯度 = 图像膨胀 - 图像腐蚀 从而获取到图像的边缘.
''
数学形态学 获取形态学梯度 gradient
'''
import cv2
import numpy as np
# 读入灰度图
img = cv2.imread("dao-bin.png", flags=cv2.IMREAD_GRAYSCALE)
# 创建 核
kernel = np.ones((5,5), np.uint8)
# 获取形态学梯度
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv2.imwrite('dao_gradient_k5.png', np.hstack((img, gradient)))