1 腐蚀操作本文为《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)
2 膨胀操作从效果上来看,膨胀操作是腐蚀操作的逆运算,在卷积核中若同时出现值为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)))
3 开运算与闭运算
开运算:先腐蚀,再膨胀。
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)))))
从上图可以看出,执行过开运算或闭运算后,图像并不会被还原。
4 梯度运算
梯度 = 膨胀后图像 - 腐蚀后图像
通过求梯度可以得到图像的轮廓信息,核越小轮廓越细。
运算时同样使用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)))