OpenCV—python 形态学处理(腐蚀、膨胀、开闭运算、边缘检测)
内容来自博客~
形态学处理的核心就是定义结构元素,在OpenCV-Python中,可以使用其自带的getStructuringElement
函数,也可以直接使用NumPy的ndarray来定义一个结构元素。
可以定义椭圆、矩形、十字形等形态学结构:
椭圆:
cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
矩形:
cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
十字形:
import numpy as np
import cv2
# 创建十字形结构
element= cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
# 注意后引号之前有一个空格
print("element ",element)
NpKernel = np.uint8(np.zeros((5,5)))
for i in range(5):
NpKernel[2,i]= 1
NpKernel[i,2]= 1
print("NpKernel ",NpKernel)
上述结果输出(相同):
array([[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0]], dtype=uint8)
腐蚀:腐蚀会把物体的边界腐蚀掉,卷积核沿着图像滑动,如果卷积核对应的原图的所有像素值为1,那么中心元素就保持原来的值,否则变为零。主要应用在去除白噪声,也可以断开连在一起的物体。
膨胀:卷积核所对应的原图像的像素值只要有一个是1,中心像素值就是1。一般在除噪时,先腐蚀再膨胀,因为腐蚀在去除白噪声的时候也会使图像缩小,所以我们之后要进行膨胀。当然也可以用来将两者物体分开。
"""
"""""
腐蚀
cv2.erode(src, # 输入头像
kernel, # 卷积核
dst=None,
anchor=None,
iterations=None, # 迭代次数,默认1
borderType=None,
borderValue=None)
膨胀
cv2.dilate(src, # 输入头像
kernel, # 卷积核
dst=None,
anchor=None,
iterations=None, # 迭代次数,默认1
borderType=None,
borderValue=None)
"""""
import cv2
import numpy as np
original_img=cv2.imread('C:\\Users\\xxx\\Desktop\\bottle.jpg')
# 图形太大,执行缩小操作
res=cv2.resize(original_img,None,fx=0.6,fy=0.6,
interpolation=cv2.INTER_CUBIC)
# 获取红色通道
B,G,R=cv2.split(res)
img=R
# img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
RedThresh=cv2.threshold(img,160,255,cv2.THRESH_BINARY)
# OpenCV定义的结构矩形元素
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
# 腐蚀图像
eroded=cv2.erode(RedThresh,kernel)
# 膨胀图像
dilated=cv2.dilate(RedThresh,kernel)
# 原图像
cv2.imshow("original_img",res)
# 红色通道图
cv2.imshow("R_channel_img",img)
# 红色阈值图像
cv2.imshow("RedThresh",RedThresh)
# 显示腐蚀后的图像
cv2.imshow("Eroded Image",eroded)
# 显示膨胀后的图像
cv2.imshow("Dilated Image",dilated)
# Numpy定义的结构元素
NpKernel=np.uint8(np.ones((3,3)))
# 腐蚀图像
Nperoded=cv2.erode(RedThresh,NpKernel)
# 显示腐蚀后的图像
cv2.imshow("Eroded by Numpy kernel",Nperoded)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.error: OpenCV(4.5.3) error: (-5:Bad argument) in function ‘erode’
Overload resolution failed:
- src is not a numerical tuple
- Expected Ptrcv::UMat for argument ‘src’
补加一行解决方法仍无法解决。
开运算和闭运算就是将腐蚀和膨胀按照一定的次序进行处理。
但这两者并不是可逆的,即先开后闭并不能得到原先的图像。
先闭后开——为了获取图像中的主要对象,对一副二值图连续使用闭运算和开运算;先开后闭——或者消除图像中的噪声,也可以对图像先用开运算后用闭运算,不过这样也会消除一些破碎的对象。
- 开运算:先腐蚀后膨胀,用于移除由图像噪音形成的斑点。
- 闭运算:先膨胀后腐蚀,用来连接被误分为许多小块的对象;
"""
cv2.morphologyEx(src, # 输入图片
op, # 需要处理类型的函数:(cv2.MORPH_OPEN,cv2.MORPH_CLOSE,cv2.MORPH_GRADIENT)
kernel, # 卷积核大小
dst=None,
anchor=None,
iterations=None, #迭代次数,默认1次
borderType=None,
borderValue=None)
"""
"""
cv2.morphologyEx(src, # 输入图片
op, # 需要处理类型的函数:
(cv2.MORPH_OPEN,cv2.MORPH_CLOSE,cv2.MORPH_GRADIENT
kernel, # 卷积核大小
dst=None,
anchor=None,
iterations=None, #迭代次数,默认1次
borderType=None,
borderValue=None)
"""
import cv2
import numpy as np
original_img=cv2.imread('C:\\Users\\xxx\\Desktop\\blue.jpg',0)
#图形太大了缩小一点
gray_res=cv2.resize(original_img,None,fx=0.8,fy=0.8,interpolation=cv2.INTER_CUBIC)
# B,G,img=cv2.split(res)
# _,RedThresh =
# cv2.threshold(img,160,255,cv2.THRESH_BINARY)
# 设定红色通道阈值160(阈值影响开闭运算效果)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
# 定义矩形结构元素
closed1= cv2.morphologyEx(gray_res , cv2.MORPH_CLOSE,kernel,iterations=1)
# 闭运算1
closed2=cv2.morphologyEx(gray_res,cv2.MORPH_CLOSE,kernel,iterations=3)
# 闭运算2
opened1=cv2.morphologyEx(gray_res,cv2.MORPH_OPEN,kernel,iterations=1)
# 开运算1
opened2=cv2.morphologyEx(gray_res,cv2.MORPH_OPEN,kernel,iterations=3)
# 开运算2
gradient=cv2.morphologyEx(gray_res,cv2.MORPH_GRADIENT,kernel)
# 梯度
# 显示如下腐蚀后的图像
cv2.imshow("gary_res",gray_res)
cv2.imshow("Close1",closed1)
cv2.imshow("Close2",closed2)
cv2.imshow("Open1",opened1)
cv2.imshow("Open2",opened2)
cv2.imshow("gradient",gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
初次编写于2021年8月18日;
一改于2021年8月26日。