第三章-OpenCV基础-7-形态学

前置

形态学主要是从图像中提取分量信息,该分量信息通常是图像理解时所使用的最本质的形状特征,对于表达和描绘图像的形状有重要意义。

大体就是通过一系列操作让图像信息中的关键信息更加凸出。同时,形态学的操作都是基于灰度图进行。

相关操作最主要的2种操作为腐蚀/膨胀,后面又延伸了综合操作-开运算/闭运算/形态学梯度/礼帽/黑帽等等。

腐蚀

腐蚀是最基本的形态学操作之一,能够去除图像的边界点,使图像沿着边界向内收缩,对于小于指定结构元的部分会去除。

所以,通过腐蚀可以达到去除一些外部噪音、元素分割等功能。

腐蚀原理说明 :

结构元 : 就是拥有一个中心位置并且有一定范围的结构,说白了就是一个二维数组。

扫描图像中的每一个像素点,结构元和扫描点重合,用结构元元素与覆盖的二值图做"与"运算,都为1则图像的像素值不变,否则改为0。

图示如下:

a图为原图,b图为结构元,当扫描到第2行,由于第一行存在2/3/4列的数据为0,所以经过腐蚀后,第2行的2/3/4列的1都变成了0,同理第4行。

扫描到第三行的2/3/4列时,由于都是1,第3行的2/3/4列分别不变,最终结果如d图所示。

函数语法说明: dst = cv2.erode( src,kernel,anchor,iterations,borderType,borderValue)

  • kernel : 腐蚀时使用的结构体,可以自己生成,也可以通过cv2.getStructuringElement()生成,就是个二维数组空间
  • anchor : 锚点位置,默认为(-1,-1),在核的中心位置
  • iterations : 腐蚀操作迭代次数,默认为1,只进行1次腐蚀操作
  • borderType : 边界处理方式,一般采用默认BORDER_CONSTANT
  • borderValue : 边界填充值,一般采用默认值

所以经常简化为 dst = cv2.erode( src ,kernel )

程序实例如下:

import cv2 as cv
import numpy as np

origin = cv.imread("erode.bmp")
# 使用了一个3*3的结构元,结构元面积越大,腐蚀的越厉害,结果图就越小
kernel_3 = np.ones((3, 3), np.uint8)

# 不大明显,但有些触角已经变短了
erode_3 = cv.erode(origin, kernel_3)
# 反复刷了三次,图像进一步腐蚀减小,边角已经腐蚀掉了
erode_3_3 = cv.erode(origin, kernel_3, iterations=3)

cv.imshow("origin", origin)
cv.imshow("erode_3", erode_3)
cv.imshow("erode_3_3", erode_3_3)

cv.waitKey()
cv.destroyAllWindows()

运行结果如下:

 膨胀

膨胀操作同样是形态学的一种基本操作,膨胀和腐蚀的作用是相反的,膨胀操作能对边界进行扩张。膨胀操作可以将较近的2个对象连通在一起,也有利于填补

图片分割后图像内的空白处。

膨胀原理说明:

使用结构元扫描图像中的每一个像素点,结构元和扫描点重合,用结构元元素与覆盖的二值图做"与"运算,都为0则图像的像素值为0,否则改为1,这样图片边缘位置就会紧跟结构元进行扩张。

函数语法说明: dst = cv2.dilate( src ,kernel,anchor,iterations,borderType,borderValue)

函数参数与腐蚀参数完全一致,不做过多解释。方法可以简化为 dst = cv2.dilate( src,kernel )

程序实例如下:

import cv2 as cv
import numpy as np

origin = cv.imread("dilation.png")
# 使用了一个3*3的结构元,结构元面积越大,膨胀的越厉害,结果图就越大
kernel = np.ones((3, 3), np.uint8)
erode_3 = cv.dilate(origin, kernel)
# 连续膨胀3次
erode_3_3 = cv.dilate(origin, kernel, iterations=9)
cv.imshow("origin", origin)
cv.imshow("dilation_3", erode_3)
cv.imshow("dilation_3_3", erode_3_3)

cv.waitKey()
cv.destroyAllWindows()

运行如下:

开运算

开运算是先进行腐蚀操作,后再进行膨胀操作。进行腐蚀操作可以把图像中目标外的噪声去掉,膨胀后再恢复目标的大小。

函数语法说明: dst = cv2.morphologyEx( src,cv2.MORPH_OPEN,kernel)

src,dst分别是原始图像和处理后的结果图像

cv2.MORPH_OPEN : 做开运算的标识

kernel : 运算使用的结构元

程序如下:

import cv2 as cv
import numpy as np

origin = cv.imread("open_pic.png", 0)
kernel = np.ones((5, 5), np.uint8)
open_pic = cv.morphologyEx(origin, cv.MORPH_OPEN, kernel) # 开运算
cv.imshow("origin", origin)
cv.imshow("open", open_pic)

cv.waitKey()
cv.destroyAllWindows()

运行如下:

闭运算

闭运算是先进行膨胀操作,后再进行腐蚀操作。主要针对情景为图像中关键信息内部有小洞,膨胀操作会填充小洞。

函数语法说明: dst = cv2.morphologyEx( src,cv2.MORPH_CLOSE,kernel)

闭运算和开运算使用一样的函数,仅通过标识不同来实现不同操作。

cv2.MORPH_OPEN : 做闭运算的标识

程序如下:

import cv2 as cv
import numpy as np

origin = cv.imread("close_pic.png", 0)
kernel = np.ones((5, 5), np.uint8)
open_pic = cv.morphologyEx(origin, cv.MORPH_CLOSE, kernel) # 闭运算
cv.imshow("origin", origin)
cv.imshow("open", open_pic)

cv.waitKey()
cv.destroyAllWindows()

运行结果如下:

形态学梯度

其实就是一副图像膨胀和腐蚀的差别,看起来就是前景物体的轮廓。

函数语法说明:dst = cv2.morphologyEx( src,cv2.MORPH_GRADIENT,kernel)

函数同开闭运算一样,只有样式不一样。

cv2.MORPH_GRADIENT : 形态学梯度的关键字

程序如下:

import cv2 as cv
import numpy as np

origin = cv.imread("abcdefg.png")
kernel = np.ones((5, 5), np.uint8)
open_pic = cv.morphologyEx(origin, cv.MORPH_GRADIENT, kernel)  # 形态学梯度
cv.imshow("origin", origin)
cv.imshow("gradient", open_pic)

cv.waitKey()
cv.destroyAllWindows()

效果图如下:

礼帽

开运算是先腐蚀再膨胀,会消除图像中的噪声,而礼帽是原始图片与进行开运算后的得到的图像的差,也就是消除掉的噪声。

函数语法说明: dst = cv2.morphologyEx( src,cv2.MORPH_TOPHAT,kernel)

import cv2 as cv
import numpy as np

origin = cv.imread("open_pic.png")
kernel = np.ones((5, 5), np.uint8)
open_pic = cv.morphologyEx(origin, cv.MORPH_TOPHAT, kernel)  # 礼帽
cv.imshow("origin", origin)
cv.imshow("tophat", open_pic)

cv.waitKey()
cv.destroyAllWindows()

运行如下:

黑帽

闭运算是先膨胀再腐蚀,具有填充内部小洞的功能,而黑帽是进行闭运算得到的图片与原始图像的差,所以显示的是之前补上的小洞图片。

函数语法说明: dst = cv2.morphologyEx( src,cv2.MORPH_BLACKHAT,kernel)

程序如下:

import cv2 as cv
import numpy as np

origin = cv.imread("close_pic.png")
kernel = np.ones((5, 5), np.uint8)
open_pic = cv.morphologyEx(origin, cv.MORPH_BLACKHAT, kernel)  # 黑帽
cv.imshow("origin", origin)
cv.imshow("blackhat", open_pic)

cv.waitKey()
cv.destroyAllWindows()

运行如下:

 

猜你喜欢

转载自blog.csdn.net/sunguanyong/article/details/129281995
今日推荐