在对二值图像进行处理的过程中,我们总会使用形态学变换,来去除一些不必要的结果和特征,来帮助我们进行后续的分析。
接下来介绍以下形态学的几种方式,了解了这几种方式,以及这些方式的特点后,才能够更加熟练的使用。
形态学变换的方法有以下几种:
腐蚀:erode
膨胀:dilate
开运算:Opening
闭运算:Closing
形态梯度:Morphological Gradient
顶帽:Top Hat
黑帽:Black Hat
先来介绍以下erode
def erode
(src,kernel,dst=None,anchor=None,iterations=None,borderType=None,borderValue=None)
kernel:内核。若为null,默认使用3*3的内核。我们一般使用getStructuringElement配合这个参数使用。在getStructuringElement里面指定形状和尺寸:
形状包含如下三种:
矩形:MORPH_RECT
交叉形:MORPH_CORSS
椭圆形:MORPH_ELLIPSE
anchor:Point类型的,锚点的位置,默认Point(-1,-1),表示锚点位于中心。
iterations:int类型的,迭代使用erode()的次数,默认为1
borderType:int类型的,推断图像外部像素的某种边界模式。默认BORDER_DEFAULT
borderValue:const Scalar类型的,当边界为常数时的边界,有默认值
morphologyDefaultBorderValue()
等下我们要将腐蚀和膨胀来做下对比,所以在这里将膨胀(dilate)的参数也讲下:
def dilate
(src,kernel,dst=None,anchor=None,iterations=None,borderType=None,borderValue=None)
一看参数,诶,巧了!一模一样。那我这里就不啰嗦了,就在上面,直接看。
明天就七夕了,我这里就用一个跟节日靠近的图像来做实例吧!
腐蚀后的图像与原图像的对比:
膨胀后的图像与原图像的对比:
我们看完这个图,会觉得,欸?是不是搞错了啊!!! 腐蚀后的结果比原来的图像更胖了!
膨胀后的结果比原来的图像更瘦了! (+_+)? 如果看不出图像差异的,我推荐你就别看牛郎和织的女了,改看旁边喜鹊吧,翅膀还是很明显的。
其实并没有搞错,你要知道,所谓的膨胀腐蚀对于作用的对象并不是我们所看到的轮廓,而是外面的白色,黑色在二值图像里面代表的是0 白色是1 所以我们进行图像操作操作的是有数值的白色,而不是无值的黑色。 (这就是为啥说,眼见不一定为实)。
到这里就又有一个疑问了,为啥要先介绍膨胀和腐蚀,而没有先介绍后面的那几种操作呢?
原因是,后面的那几种操作其实就是上面的图像的运算而形成的。
这几种操作用到的都是同一个函数:morphologyEx
def morphologyEx
(src,op,kernel,dst=None,anchor=None,iterations=None,borderType=None,borderValue=None)
op:就是我们这里指的这几种形态学运算的类型
开运算 (MORPH_OPEN):先腐蚀再膨胀
闭运算(MORPH_CLOSE) :先膨胀再腐蚀
形态梯度(MORPH_GRADIENT): 膨胀图与腐蚀图之差(保留物体边缘轮廓)
顶帽(MORPH_TOPHAT) : 原图像与开运算之差
黑帽 (MORPH_BLACKHAT): 闭图像与原图像之差
这里唯一需要多介绍的就这一个函数,其他的都和膨胀腐蚀的参数一样。还不太明白的可以去上面找一找。
虽然这个实验我也想用上面的那个图,不过发现效果不够明显,这下我换成文字吧,比较含蓄的提现即将到来的节日:
这组图片中,第一个是原图,然后是开运算的图,闭运算的图
第二行第一个是形态梯度的图,第二个是顶帽的图,第三个是黑帽的图
我们会发现:
当使用开运算的时候,看“情”字比较明显,中间的封闭的地方比原图像模糊了
因为开运算能够**删除不能包含结构元素的对象区域,平滑图像的轮廓,使拐点的地方更加连贯,断开一些狭窄的链接,去掉细小的突出部分。
当使用闭运算的时候,看每个字代笔(连笔)的地方,变得不是那么的连续
因为闭运算能够排除小型黑洞,平滑图像轮廓,与开运算不同的是闭运算会将狭窄的缺口链接起来,填充比结构元素小的洞
形态学梯度就很明显了,保留物体边缘轮廓
顶帽和黑帽在这里的效果不是很明显,这里我就不从图片上分析了,直接从公式入手
顶帽: 原图像与开运算之差
开运算的目的是放大裂缝(此时的文字可以理解为裂缝)或局部降低亮度的区域,顶帽(原图像减去开运算)的图能够突出比原图像周围区域更亮的区域。按照位置对应,会发现“情”字的“月”的那部分有一些高亮的区域。
黑帽:闭运算与原图像之差
黑帽运算突出比原图像周围更暗的区域。黑帽用来显示比原图像多闭合的高亮区域。
这个地方比较绕,我这里做一个简单的介绍:当针对二值图像来说,白色是有值的,黑色是无值的,开运算就是将有值的部分打开,从而将无值的部分显得更加连贯,闭运算就相反,是将有值的地方进行连接,从而无值的部分就会显得稀少了。根据我总结的这句话可以再返回去看下上面的开运算和闭运算的图,不知道是否能帮助你们了解下形态学的相关信息。
接下来上代码:
import cv2
img = cv2.imread("C:/Users/DELL/Desktop/img4.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gauss = cv2.GaussianBlur(gray, (3, 3), 1)
element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
erode = cv2.erode(gauss, element)
dilate = cv2.dilate(gauss, element)
open = cv2.morphologyEx(gauss, cv2.MORPH_OPEN, element)
close = cv2.morphologyEx(gauss, cv2.MORPH_CLOSE, element)
morphological_gradient = cv2.morphologyEx(gauss, cv2.MORPH_GRADIENT, element)
top_hat = cv2.morphologyEx(gauss, cv2.MORPH_TOPHAT, element)
black_hat = cv2.morphologyEx(gauss, cv2.MORPH_BLACKHAT, element)
cv2.imshow("src", gauss)
cv2.imshow("dilate", dilate)
cv2.imshow("erode", erode)
cv2.imshow("open", open)
cv2.imshow("close", close)
cv2.imshow("morphological_gradient", morphological_gradient)
cv2.imshow("top_hat", top_hat)
cv2.imshow("black_hat", black_hat)
cv2.waitKey(0)