本文为《OpenCV计算机视觉实战》课程的笔记。
在卷积核中,若同时出现像素值255和0的像素点,则0替换255。
关键方法:cv2.erode(img,kernel,iterations = 1)
前提:输入图像是二值的
1、读入图像
img = cv2.resize(cv2.imread('./img/nihao.png'),(300,300))
cv_show('nihao',img)
2、创建核(卷积窗口)
kernel = np.ones((3,3),np.uint8)
# 设置腐蚀参数
# iterations:迭代次数
erosion = cv2.erode(img,kernel,iterations = 1)
cv_show('erosion',erosion)
对圆腐蚀三次的效果如下:
pie = cv2.resize(cv2.imread('./img/pie.png'),(300,300))
# 展示对圆腐蚀三次的效果
kernel = np.ones((20,10), np.uint8)
erosion_1 = cv2.erode(pie, kernel, iterations = 1)
erosion_2 = cv2.erode(pie, kernel, iterations = 2)
erosion_3 = cv2.erode(pie, kernel, iterations = 3)
res = np.hstack((pie,erosion_1, erosion_2, erosion_3))
cv_show('erosion',res)
从效果上来看,膨胀操作是腐蚀操作的逆运算,在卷积核中若同时出现值为0和255的的像素点,则用255替换0。通过“腐蚀+膨胀”可以清除图像中的毛刺(不相关的点)。
关键方法:cv2.dilate(nihao_erosion, kernel, iterations = 1)
1、腐蚀去除毛刺
nihao = cv2.resize(cv2.imread('./img/nihao.png'),(300, 300))
kernel = np.ones((3,3),np.uint8)
nihao_erosion = cv2.erode(nihao, kernel, iterations = 1)
2、膨胀还原笔画
nihao_dilate = cv2.dilate(nihao_erosion, kernel, iterations = 1)
cv_show('dilate',np.hstack((nihao, nihao_erosion, nihao_dilate)))
开运算:先腐蚀,再膨胀。
cv2.morphologyEx(nihao, cv2.MORPH_OPEN, kernel)
闭运算:先膨胀,再腐蚀。
cv2.morphologyEx(nihao, cv2.MORPH_CLOSE, kernel)
nihao = cv2.resize(cv2.imread('./img/nihao.png'),(300, 300))
kernel = np.ones((3,3),np.uint8)
# 开:先腐蚀,再膨胀
opening = cv2.morphologyEx(nihao, cv2.MORPH_OPEN, kernel)
# 闭:先膨胀,再腐蚀
close = cv2.morphologyEx(nihao, cv2.MORPH_CLOSE, kernel)
cv_show('open&close',np.hstack((nihao, opening, close)))
可以看到,开运算可以去除毛刺,而闭运算不仅不能去除毛刺,还可能使毛刺被加强。
当核尺寸为5×5时,由于核尺寸太大,导致原图信息全部丢失。
再来看看对圆形做开闭运算的结果:
pie = cv2.resize(cv2.imread('./img/pie.png'),(300, 300))
kernel = np.ones((30,30),np.uint8)
opening = cv2.morphologyEx(pie, cv2.MORPH_OPEN, kernel)
close = cv2.morphologyEx(pie, cv2.MORPH_CLOSE, kernel)
cv_show('open&close', np.vstack((np.hstack((pie, opening, opening-pie)),np.hstack((pie, close, close-pie)))))
从上图可以看出,执行过开运算或闭运算后,图像并不会被还原。
梯度 = 膨胀后图像 - 腐蚀后图像
通过求梯度可以得到图像的轮廓信息,核越小轮廓越细。
运算时同样使用cv2.morphologyEx()
方法,第二个参数选cv2.MORPH_GRADIENT
首先来看看对原求梯度的结果:
# 梯度=膨胀 - 腐蚀
pie = cv2.resize(cv2.imread('./img/pie.png'),(300, 300))
kernel = np.ones((3,3),np.uint8)
# 执行5次膨胀-->执行5此腐蚀
dilate = cv2.dilate(pie, kernel, iterations = 5)
erosion = cv2.erode(pie, kernel, iterations = 5)
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv_show('res',np.hstack((pie, dilate, erosion,gradient)))
再来看看对手写字“你好”做梯度运算的结果:
nihao = cv2.resize(cv2.imread('./img/nihao.png'),(300,300))
kernel = np.ones((2,2), np.uint8)
gradient = cv2.morphologyEx(nihao, cv2.MORPH_GRADIENT, kernel)
cv_show('gradient', gradient)
对于手写字“你好”的图像,由于开运算去除了原图的毛刺,因此通过礼帽可以得到毛刺信息;而闭运算加强了笔画的拐点,故通过黑帽可以捕捉到一些笔画的交叉点。
nihao = cv2.resize(cv2.imread('./img/nihao.png'), (300, 300))
kernel = np.ones((3,3),np.uint8)
# 礼帽
tophat = cv2.morphologyEx(nihao, cv2.MORPH_TOPHAT, kernel)
# 黑帽
blackhat = cv2.morphologyEx(nihao, cv2.MORPH_BLACKHAT, kernel)
cv_show('res',np.hstack((nihao, tophat, blackhat)))