OPenCV之形态学操作

举报
Y_K_C 发表于 2021/12/22 16:36:46 2021/12/22
【摘要】 声明:本文是OpenCV入门级别的技术分享,主要围绕图像预处理来进行学习,所用语言均为Python。

一、图像形态学

图像形态学是用来去除一些噪声和小的无意义的目标物,主要有腐蚀运算、膨胀运算、开运算和闭运算,而开运算和闭运算是由腐蚀运算和膨胀运算结合而来的,下面介绍一下两种运算的原理。

1.二值化形态学

腐蚀:
简单来讲,二值化形态学中的腐蚀操作是用来消除二值化后的图像的一些无意义的小目标,公式为:
image.png
这个公式表示用结构B来腐蚀图像A,具体过程为通过定义一个结构B(类似于卷积核),结构B中每个位置分配值(0或1),并且在B中规定一个原点;之后结构B在A上移动,每一次移动时只有当结构B为1的地方A也为1时,结构B原点所覆盖的A的位置赋值为1,否则赋值为0:
image.png
膨胀:
膨胀操作与腐蚀相反,用来填补邻域内的某些空洞和消除邻域内的小颗粒噪声,公式为:
image.png
这个公式表示使用结构B膨胀A,具体通过定义一个结构B,每个位置分配0或1,并且规定一个原点,结构B在A上移动,只要当B中为1的位置中其中有一个位置在A中对应的值为1,即可将B原点对应的A的位置赋值为1,否则赋值为0:
image.png

2.灰度形态学

腐蚀:
灰度形态学的腐蚀操作类似与卷积操作,定义一个结构B,每个位置赋给一定的值,并且规定一个原点,结构B在图像A上移动,在B覆盖A的邻域内,将A位置上的值减去B对应位置上的值,得到一个与B形状相同的矩阵,将矩阵中最小的值赋给B原点对应A的位置:
image.png
image.png
灰度形态学的腐蚀是将像素值变小,抑制高频段的噪声。
膨胀:
膨胀与腐蚀是相反的操作,在膨胀的原理中,前面的操作与腐蚀相同,只不过在计算时是将B中的值与A对应位置的值相加,得到相同形状的矩阵,选取矩阵中最大的值赋给B原点对应A的位置:
image.png
image.png
相反,灰度形态学的膨胀是将像素值变大,抑制的是低频段的噪声。

开运算和闭运算是膨胀和腐蚀按照一定的顺序进行排列的操作。开运算是先腐蚀再膨胀,去除图像中没有意义的边;闭运算是先膨胀再腐蚀,填补图像中的空洞,这里就不再赘述。

二、代码实现

通过上面的介绍,说明无论说明什么操作都需要定义一个结构B,这里可以运用numpy定义,或者使用OpenCV的API——getStructuringElement(),返回一个矩阵,参数解释:
shape:指的是结构的形状,矩形(cv2.MORPH_RECT),椭圆形(cv2.MORPH_ELLIPSE),交叉形(cv2.MORPH_CORSS)
ksize:结构的形状
anchor:指结构的锚点(即上文提到的原点)的位置,默认值为(-1,-1)指结构的中心点

1.腐蚀

腐蚀运算使用的是API——erode(),具体如下:

import cv2 as cv
path =  "C:\\Users\\27914\\Desktop\\images\\test12.jpeg"
image  = cv.imread(path)
cv.imshow("image",image)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(10,10))
result1 = cv.erode(image,kernel,iterations=2)
cv.imshow("erode",result1)
cv.waitKey(0)
cv.destroyAllWindows()

参数解释:
src:输入图像,通道数不限,但图像的ddepth必须是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F
kernel:腐蚀操作的结构
anchor:锚点(原点)的位置
iterations:迭代次数,即腐蚀重复的次数
borderType:图像边缘判断的方法
borderValue:边缘值
输出:
原图:
image.png
腐蚀:
image.png

2.膨胀

膨胀使用另外一个API——dilate(),参数与erode()一样,这里不重复介绍了,代码如下:

import cv2 as cv
path =  "C:\\Users\\27914\\Desktop\\images\\test12.jpeg"
image  = cv.imread(path)
cv.imshow("image",image)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(10,10))
result2 = cv.dilate(image,kernel,iterations=2)
cv.imshow("dilate",result2)
cv.waitKey(0)
cv.destroyAllWindows()

膨胀:
image.png

3.开、闭运算

开和闭运算都是用同一个API——morphologyEx(),只需要调整其中的op参数就可以实现开闭运算,代码如下:

import numpy as np
import cv2 as cv
path =  "C:\\Users\\27914\\Desktop\\images\\test12.jpeg"
image  = cv.imread(path)
cv.imshow("image",image)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(10,10))
open = cv.morphologyEx(image,cv.MORPH_OPEN,kernel)
close = cv.morphologyEx(image,cv.MORPH_CLOSE,kernel)
cv.imshow("open",open)
cv.imshow("close",close)
cv.waitKey(0)
cv.destroyAllWindows()

参数解释:
其参数与erode()差不多,多了一个op参数而已,op参数主要是调整运算方法的,可选择:
开运算:cv.MORPH_OPEN,闭运算:cv.MORPH_CLOSE,梯度运算:cv.MORPH_GRADIENT,礼帽(顶帽)运算:cv.MORPH_TOPHAT,黑帽运算:cv.MORPH_BLACKHAT。后面几种运算后面补充介绍一下。
开运算输出:
image.png
闭运算输出:
image.png

4梯度,顶帽,黑帽运算

这三种运算是将腐蚀操作结果,膨胀操作结果,开运算结果,闭运算结果,原图之间进行计算的得出一个新的结果。
梯度运算: 对图片分别进行腐蚀和膨胀操作,用膨胀结果减去腐蚀结果,得到的是轮廓信息。
顶帽运算: 对图像进行开运算,得到的是除去白色噪声的图像,再用原图减去开运算后的图像,得到的是图像的白色噪声。
黑帽运算: 对图像进行闭运算,得到的是除去黑色噪声的图像,再用原图减去闭运算后的图像,得到的是图像的黑色噪声。
代码如下:

import numpy as np
import cv2 as cv
path =  "C:\\Users\\27914\\Desktop\\images\\test12.jpeg"
image  = cv.imread(path)
cv.imshow("image",image)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(10,10))
grad = cv.morphologyEx(image,cv.MORPH_GRADIENT,kernel)#梯度
tophat = cv.morphologyEx(image,cv.MORPH_TOPHAT,kernel)#顶帽
blackhat = cv.morphologyEx(image,cv.MORPH_BLACKHAT,kernel)#黑帽
cv.waitKey(0)
cv.destroyAllWindows()

输出:
梯度:
image.png
顶帽:
image.png
黑帽:
image.png
这三种算法受限制与结构的定义,当结构定义较大时,噪声检测越多,但同时轮廓也被检测出来。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。