上个教程中我们遗留了一些问题,那就是经过图像开运算或者是闭运算之后亮度会发生变化,这就会对后期的图像处理造成一定的困扰,所以本次教程我们介绍OpenCV的顶帽与黑帽运算,来解决这些问题。
顶帽
顶帽运算又常常被译为”礼帽“运算。为原图像与上文刚刚介绍的“开运算“的结果图之差,数学表达式如下:
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
现在我们来进行一些实战操作,我们先来看一幅图片:
这是之后我们将要讲述的一个是实战案例-卡片上的数字识别,首先我们需要做的就是对图像先进行灰度化,然后再进行阈值化,这样才方便后期提取轮廓,我们先来用OTSU算法进行阈值化:
import cv2 import numpy as np img = cv2.imread('credit_card_.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) threshold = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV| cv2.THRESH_OTSU)[1] cv2.imshow("img",img) cv2.imshow("thres",threshold) cv2.waitKey(0) cv2.destroyAllWindows()
事实情况很糟糕,这样的阈值化根本无法让我们进行下一步的操作,我们看原图发现右下角的字体与背景的亮度都有些高,所以会出现这种情况,现在想让字体与背景分离出来,我们可以用顶帽操作对前景进行明亮化:
import cv2 import numpy as np img = cv2.imread('credit_card_.png') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(21,21)) tophat = cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,kernel) threshold = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV| cv2.THRESH_OTSU)[1] cv2.imshow("img",img) cv2.imshow("thres",threshold) cv2.waitKey(0) cv2.destroyAllWindows()
我们再来看这样的效果是不是好的多了?中间的数字字体被完整的分离了出来,事实上,在很多地方我们经常会用到顶帽操作。
黑帽
黑帽运算为”闭运算“的结果图与原图像之差。数学表达式为:
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。所以,黑帽运算用来分离比邻近点暗一些的斑块。非常完美的轮廓效果图,同样我们来看实例代码:
import cv2 import numpy as np img = cv2.imread('close.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) tophat = cv2.morphologyEx(gray,cv2.MORPH_BLACKHAT,kernel) cv2.imshow("img",img) cv2.imshow("thres",tophat) cv2.waitKey(0) cv2.destroyAllWindows()
形态学梯度
现在我们来看OpenCV形态学处理中的最后一个操作——形态学梯度,它本质上就是对图像的边缘提取,也可以说是膨胀的结果减去腐蚀的结果,我们来看实际效果:
import cv2 import numpy as np img = cv2.imread('close.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) tophat = cv2.morphologyEx(gray,cv2.MORPH_GRADIENT,kernel) cv2.imshow("img",img) cv2.imshow("thres",tophat) cv2.waitKey(0) cv2.destroyAllWindows()
这就对图像的边缘进行了检测。
本次教程的结束同时也意味着OpenCV中形态学处理部分的结束,实际上我们发现,它们都可以用一个函数API来进行调用:
cv2. morphologyEx()
关于它我们在前面已经有所介绍,现在总结一下,它总共可以进行这些操作:
(1)MORPH_OPEN:开运算
(2)MORPH_CLOSE:闭运算
(3)MORPH_GRADIENT:形态学梯度
(4)MORPH_TOPHAT:顶帽
(5)MORPH_BLACKHAT:黑帽
(6)MORPH_ERODE:腐蚀
(7)MORPH_DILATE:膨胀
图像形态学的处理是非常重要的,大家一定要熟练掌握。