文章目录
- 1.首先了解腐蚀和膨胀原理
- 2.开运算
- (1)为什么开运算可以去白噪点呢?
- (2).函数讲解
- (3)代码实战
- 3.闭运算
- (1)函数讲解
- (2)代码实战
1.首先了解腐蚀和膨胀原理
https://mydreamambitious.blog.csdn.net/article/details/125265431
2.开运算
开运算=腐蚀+膨胀(顺序不可颠倒)
(1)为什么开运算可以去白噪点呢?
根据腐蚀的原理,使用一个给定大小的卷积核(结构单元)对图像进行卷积,操作是用卷积核(结构元素)B与其覆盖的二值图像A做“与”操作,如果结果为1,那么为1,否则为0;但是对于噪点的话,很多情况下在于卷积核进行与操作之后结果都为0,所以对于二值图像那么就是黑色,也就是白色的噪点变成黑色(相当于白色噪点被去掉)。腐蚀之后图像中的主要部分也会变小(“瘦”),所以需要使用膨胀进行还原;膨胀的过程是使用卷积核与二值图像进行或操作,只要其中有一个为1,则结果为1,否则结果为0.从而达到了去白噪点。
比如下面一张图中,可以看到其中有很多的白色噪点,所以这个时候可以使用开运算操作。
(2).函数讲解
morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None):
Src:输入的原始图像
;
Op:进行操作(开运算或者闭运算)
;
Kernel:卷积核的大小
;
Dst:输出的图像
;
Anchor:默认值为(-1,-1),卷积的中心
。
Iterations:迭代的次数
。
borderType:用于推断图像外部像素的某种边界模式。注意它有默认值 BORDER_DEFAULT
。
borderValue:边界值(如果是常量边界)。默认morphologyDefaultBorderValue具有特殊含义。对于侵蚀,它被转换为+\inf;对于膨胀,它被转换为-\inf,这意味着只有在图像内部的像素上才能有效地计算最小值(最大值)
。
(3)代码实战
import os
import cv2
import random
import numpy as np#产生白色噪点
def ProduceWhiteNoise(img_path='images/Exen.png'):image=cv2.imread(img_path)h,w,c=np.shape(image)noise=np.zeros(shape=image.shape,dtype=np.uint8)# print(np.shape(image))#固定产生白噪点的个数count=0prob=0.95for i in range(h):for j in range(w):sand=random.random()if count<=50000 and sand>prob:noise[i][j]=255count+=1else:noise[i][j]=image[i][j]cv2.imshow('image',noise)cv2.waitKey(0)cv2.imwrite('images/Exen_copy.png',noise)#进行开运算的方式一,直接调用开运算函数
def MorphologyExAnd(img_path='images/Exen_copy.png'):#读取图片img_src=cv2.imread(img_path)img=cv2.resize(src=img_src,dsize=(500,500))#获取卷积核,这里使用矩阵的方式kernel=cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=(7,7))#进行开运算img=cv2.morphologyEx(src=img,op=cv2.MORPH_OPEN,kernel=kernel,iterations=1)#显示图片cv2.imshow('img_src',img_src)cv2.imshow('img',img)#等待接收鼠标或者键值cv2.waitKey(0)cv2.destroyAllWindows()#进行开运算方式2=腐蚀+膨胀
def Erode_Dilate(img_path='images/Exen_copy.png'):#读取图像img_src=cv2.imread(img_path)img=cv2.resize(src=img_src,dsize=(500,500))#获取卷积核kernel=cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=(7,7))#首先进行腐蚀操作img_erode=cv2.erode(src=img,kernel=kernel,iterations=2)#再进行膨胀操作img_dilate=cv2.dilate(src=img_erode,kernel=kernel,iterations=2)#显示图像cv2.imshow('img_src',img_src)cv2.imshow('img_dilate',img_dilate)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':print('Pycharm')# ProduceWhiteNoise()# MorphologyExAnd()Erode_Dilate()
直接调用开运算操作的结果
使用:腐蚀+膨胀方式
可以看到两者的效果都是很不错的。
3.闭运算
闭运算=膨胀+腐蚀
(和开运算相反)
达到的效果:
比如下面一张图中,可以看到其中有很多的黑色噪点,所以这个时候可以使用开运算操作。
(1)函数讲解
和开运算一样的函数,只不过op的方式改为:cv2.MORPH_CLOSE
(2)代码实战
import os
import cv2
import random
import numpy as np#产生黑色噪点
def ProduceBlackNoise(img_path='images/Exen.png'):image=cv2.imread(img_path)h,w,c=np.shape(image)noise=np.zeros(shape=image.shape,dtype=np.uint8)# print(np.shape(image))#固定产生白噪点的个数count=0prob=0.95for i in range(h):for j in range(w):sand=random.random()if count<=50000 and sand>prob:noise[i][j]=0count+=1else:noise[i][j]=image[i][j]cv2.imshow('image',noise)cv2.waitKey(0)cv2.imwrite('images/Exen_black.png',noise)#进行开运算的方式一,直接调用开运算函数
def MorphologyExAnd(img_path='images/Exen_black.png'):#读取图片img_src=cv2.imread(img_path)img=cv2.resize(src=img_src,dsize=(500,500))#获取卷积核,这里使用矩阵的方式kernel=cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=(3,3))#进行闭运算img=cv2.morphologyEx(src=img,op=cv2.MORPH_CLOSE,kernel=kernel,iterations=1)#显示图片cv2.imshow('img_src',img_src)cv2.imshow('img',img)#等待接收鼠标或者键值cv2.waitKey(0)cv2.destroyAllWindows()#进行开运算方式2=腐蚀+膨胀
def Erode_Dilate(img_path='images/Exen_black.png'):#读取图像img_src=cv2.imread(img_path)img=cv2.resize(src=img_src,dsize=(500,500))#获取卷积核kernel=cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=(3,3))#首先进行膨胀操作img_dilate = cv2.dilate(src=img, kernel=kernel, iterations=1)#再进行腐蚀操作img_erode = cv2.erode(src=img_dilate, kernel=kernel, iterations=1)#显示图像cv2.imshow('img_src',img_src)cv2.imshow('img_dilate',img_erode)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':print('Pycharm')# ProduceBlackNoise()# MorphologyExAnd()Erode_Dilate()
直接使用闭运算函数的结果:
使用:膨胀+腐蚀方式
总结:
开运算是解决黑色图像部分中的白色噪点;
闭运算解决的是白色图像部分中的黑色噪点。