《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波 | 您所在的位置:网站首页 › 图像降噪的作用有哪些 › 《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波 |
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的、不同方法的处理,以达到对图像进行去噪、锐化等一系列的操作。同时,希望观看本专栏的小伙伴可以理解到OpenCv进行图像处理的强大哦,如有转载,请注明出处(原文链接和作者署名),感谢各位小伙伴啦! 前文参考: 《OpenCv视觉之眼》Python图像处理一 :Opencv-python的简介及Python环境搭建 《OpenCv视觉之眼》Python图像处理二 :Opencv图像读取、显示、保存基本函数原型及使用 《OpenCv视觉之眼》Python图像处理三 :Opencv图像属性、ROI区域获取及通道处理 《OpenCv视觉之眼》Python图像处理四 :Opencv图像灰度处理的四种方法及原理 上次博客讲到图像灰度处理的四种方法原理,以及通过原理编写图像灰度处理函数,然后结合OpenCv图像灰度处理函数库进行对比,理解不同处理方法之间的不同处理原理,并总结出了Gamma校正灰度化是对图像对人眼视觉最好的一种图像灰度化方法,相信阅读过的小伙伴应该是可以理解的。 本次博客,我们将讲解OpenCV如何对图像进行去噪,一般情况下,通过OpenCV对图像进行处理,我们首先应该考虑的就是去除图像中的噪声点,例如椒盐噪声等,避免在后续的图像处理中影响相应进程,OpenCV对于图像去噪(又称图像平滑)提供了四种方法,分别是均值滤波、方框滤波、中值滤波和高斯滤波,并且提供了这几种方法的库函数,本次博客,林君学长主要给大家讲解这几种方法去噪的原理,并通过原理编写自己的去噪函数,当然,也会带大家了解如何使用库函数,因为在对图像处理的现实中,我们肯定会使用库函数进行图像处理,OpenCV官方对他们的库函数进行过优化,执行速度非常快;而我们自己通过原理编写代码只是为了研究库函数处理的原理,较于使用多次for循环,因此执行速度是比较慢的,现在,开始学习吧! 在进行下面几种滤波的学习时,应该提前考虑如下几点: 图像去噪处理一般来说是在图像灰度处理之后,图像灰度化之后,会存在噪声点,这些噪声是我们不需要的噪声,因此我们需要对图像进行模糊,去除这些噪声点;当然,只是一般来说,如果对于彩色图像,同样也是可以进行去噪的,即在读取彩色图像后便可以进行滤波降噪处理,这个后面我们会讲到,但滤波处理也只能降低噪声的数量,并不能完全消除,即使调整核函数尺寸也不行,去得太多,将会影响图中我们需要的部分,这也是缺点之一,但后续的其他处理可以解决这个问题,滤波处理我们暂时不用考虑 既然是去除图像中的噪声,我们首先便需要增加选取一张具有噪声的图像,然后进行各种滤波处理,这是一个方法,同时我们还可以自己给图像增加噪声,形成噪声图像,Python代码如下所示: #给图像加噪声 import cv2 import numpy as np import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文 #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) #随机取行 y = np.random.randint(0, w) #随机取列 img[x,y,:] = 255 #行和列设置为白色噪声点 #BGR转换为RGB显示格式,方便通过matplotlib进行图像显示 img= cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #显示图像 plt.imshow(img) plt.axis('off')#关闭坐标轴 设置为on则表示开启坐标轴 plt.savefig('my1.jpg') #保存图像 plt.show()#显示图像1)、均值滤波原理 均值滤波是指任意一点的像素值,都是周围NM个像素值的均值。例如下图中,红色点的像素值为蓝色背景区域像素值之和除25: 1)、通过以上原理,我们不难发现,如果是通过原图与核进行卷积,卷积之后的图的尺寸是会变小的,最后结果给我们的视觉体验就是在图周围有一圈黑边,这一圈黑边是没有进行到卷积的地方,因此,我们需要将原图进行扩充,使得第一次卷积的地方就是原图的[0,0]点,在卷积后,扩充的地方是没有进行卷积的,所以我们从扩充的图中裁剪出原图就可以了,接下来,通过原理实现该代码吧! 2)、自定义均值滤波函数 import cv2 import numpy as np def meanFiltering1(img,size): #img输入,size均值滤波器的尺寸,>=3,且必须为奇数 num = int((size - 1) / 2) # 输入图像需要填充的尺寸 img = cv2.copyMakeBorder(img, num, num, num, num, cv2.BORDER_REPLICATE)#对传入的图像进行扩充,尺寸为num h1, w1 = img.shape[0:2] # 高斯滤波 img1 = np.zeros((h1, w1, 3), dtype="uint8") #定义空白图像,用于输出中值滤波后的结果 for i in range(num, h1-num): #对扩充图像中的原图进行遍历 for j in range(num, w1-num): sum=0 sum1=0 sum2=0 for k in range(i-num,i+num+1): #求中心像素周围size*size区域内的像素的平均值 for l in range(j-num,j+num+1): sum=sum+img[k,l][0] #B通道 sum1=sum1+img[k,l][1] #G通道 sum2=sum2+img[k,l][2] #R通道 sum=sum/(size**2) #除以核尺寸的平方 sum1 = sum1/(size**2) sum2 = sum2/(size**2) img1[i, j]=[sum,sum1,sum2] #复制给空白图像 img1=img1[(0+num):(h1-num),(0+num):(h1-num)] #从滤波图像中裁剪出原图像 return img13)、读取图像加噪声,然后进行均值滤波处理并显示 #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用均值滤波函数 result=meanFiltering1(img,5) #传入读取的图像和核尺寸 cv2.imshow("Noise",img) cv2.imshow("meanFiltering",result) cv2.waitKey(0)
1)、在OpenCV对图像去噪处理中,也提供了均值滤波处理的库函数,处理原理是一样的,主要是运算速度快,OpenCV官方对for循环进行了优化,大大提升了代码运算速度,主要还是开源的,函数原型如下: 2)、函数原型:cv2.blur(img,(szie,size)) img:img表示需要进行中值滤波处理的图像(size,size):表示核大小,是以(宽度,高度)表示的元祖形式。常见的形式包括:核大小(3,3)和(5,5) 3)、中值滤波库函数使用 import cv2 import numpy as np #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用均值滤波函数 result=cv2.blur(img,(5,5)) #传入读取的图像和核尺寸 cv2.imshow("Noise",img) cv2.imshow("meanFiltering-OpenCV",result) cv2.waitKey(0)
1)、方框滤波原理 方框滤波原理和均值滤波原理基本一致,区别是需不需要均一化处理;需要均一化处理,则原理和均值滤波相同;如果不需要均一化处理,很容易发生溢出,溢出时均为白色,设置对应像素值为255,而对于均一化或者非均一化处理主要通过传递参数normalize来进行区别,当normalize=Ture时,表示需要均一化处理,而当normalize=Flase时,则表示不需要均一化处理(非均一化处理),则将溢出部分的像素值设置为0 2)、将以上原理转化为我们可以理解的数学公式则如下: 1)、编写方框滤波函数功能 import cv2 import numpy as np #方框滤波 # 自定义方框滤波函数 def boxFiltering1(img, size,normalize): #img输入,size均值滤波器的尺寸,>=3,且必须为奇数 num = int((size - 1) / 2) # 输入图像需要填充的尺寸 img = cv2.copyMakeBorder(img, num, num, num, num, cv2.BORDER_REPLICATE)#对传入的图像进行扩充,尺寸为num h1, w1 = img.shape[0:2] # 高斯滤波 img1 = np.zeros((h1, w1, 3), dtype="uint8") #定义空白图像,用于输出中值滤波后的结果 for i in range(num, h1-num): #对扩充图像中的原图进行遍历 for j in range(num, w1-num): sum=0 sum1=0 sum2=0 for k in range(i-num,i+num+1): #求中心像素周围size*size区域内的像素的平均值 for l in range(j-num,j+num+1): sum=sum+img[k,l][0] #B通道 sum1=sum1+img[k,l][1] #G通道 sum2=sum2+img[k,l][2] #R通道 if normalize==True:#均一化处理,和均值滤波一样,除以25 sum = sum / (size ** 2) sum1 = sum1 / (size ** 2) sum2 = sum2 / (size ** 2) else: #非均一化处理,溢出部分设置为255 if sum2>255: sum2=255 else: sum=sum2 if sum1 > 255: sum1 = 255 else: sum1 = sum1 if sum>255: sum=255 else: sum=sum img1[i, j]=[sum,sum1,sum2] #复制给空白图像 img1=img1[(0+num):(h1-num),(0+num):(h1-num)] #从滤波图像中裁剪出原图像 return img12)、读取图像,添加噪声、进行方框滤波过滤并显示 #读取图像 img=cv2.imread("g.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用均值滤波函数 result=boxFiltering1(img, 5,normalize=True) #传入读取的图像和核尺寸 result1=boxFiltering1(img, 5,normalize=False) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("JunYIHua",result) cv2.imshow("NoJunYIHua",result1) cv2.waitKey(0)
1)、在OpenCV函数库中,也为我们提供了方框滤波的库函数,函数原型如下所示: 函数原型rusult=cv2.boxFilter(img, deep, (szie,size), normalize) img:原始图像deep:原始图像深度(szie,size):核尺寸normalize:归一化参数,normalize=1进行归一化,normalize=0,非归一化 2)、方框滤波库函数使用 #方框滤波OpenCV库 import cv2 import numpy as np #读取图像 img=cv2.imread("g.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用均值滤波函数 result=cv2.boxFilter(img, -1, (5,5), normalize=1) #传入读取的图像和核尺寸 result1=cv2.boxFilter(img, -1, (5,5), normalize=0) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("JunYIHua-opencv",result) cv2.imshow("NoJunYIHua-opencv",result1) cv2.waitKey(0)
上面我们介绍的均值滤波和方框滤波都属于邻域平均法,而在使用邻域平均法去噪的同时也使得边界变得模糊;而中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。 1、中值滤波原理1)、中值滤波原理 选一个含有奇数点的窗口W,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。 例如选择滤波的窗口如下图,是一个一维的窗口,待处理像素的灰度取这个模板中灰度的中值,滤波过程如下: 1)、自定义中值滤波函数medianFiltering1(img, size) #中值滤波 # 自定义中值滤波函数 import cv2 import numpy as np def medianFiltering1(img, size): # img输入,size均值滤波器的尺寸,>=3,且必须为奇数 num = int((size - 1) / 2) # 输入图像需要填充的尺寸 img = cv2.copyMakeBorder(img, num, num, num, num, cv2.BORDER_REPLICATE) h, w = img.shape[0:2] # 获取输入图像的长宽和高 img1 = np.zeros((h, w, 3), dtype="uint8") # 定义空白图像,用于输出中值滤波后的结果 for i in range(num, h - num):#遍历出原图像 for j in range(num, w - num): sum=[] sum1=[] for k in range(i - num, i + num + 1): # 求中心像素周围size*size区域内的像素的平均值 for l in range(j - num, j + num + 1): sum =sum+[int(img[k, l][0])+int(img[k, l][1])+int(img[k, l][2])] #每个像素的3通道像素值相加,然后求中间数 sum1=sum1+[(img[k, l][0],img[k, l][1],img[k, l][2])]#将对于的三通道像素值存在数组sum1中 id=np.argsort(sum) #将像素值周围的点的数组进行排序,然后返回排序之前的像素值对应在数组中的序号 id=id[int((size**2)/2)+1] #取返回序号的中间序号 b,g,r=sum1[id]#通过中间序号找到在像素值数组中的3通道信号,然后分别复制给b,g,r img1[i, j]=[b,g,r] img1 = img1[(0 + num):(h - num), (0 + num):(h - num)] return img1以上中值滤波函数中,第一个参数为需要进行中值滤波处理的图像,第二个参数则为核的尺寸 2)、读取图像添加噪声,然后进行中值滤波处理,并进行图像显示 #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用均值滤波函数 result=medianFiltering1(img, 5) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("medianFiltering",result) cv2.waitKey(0)
当然,对椒盐噪声这么重要的中值滤波,OpenCV库函数肯定包含中值滤波函数,看一下中值滤波函数原型吧! 1)、函数原型result=cv2.medianBlur(img, size) img:需要进行中值滤波处理的图像size:核大小,核必须是大于1的奇数,如3、5、7等2)、中值滤波函数使用方法 #OpenCV中值滤波库函数使用 import cv2 import numpy as np #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用OpenCV库函数中的均值滤波函数 result=cv2.medianBlur(img, 5) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("medianFiltering-opencv",result) cv2.waitKey(0)
为了克服简单局部平均法的弊端(图像模糊),目前已提出许多保持边缘、细节的局部平滑算法。它们的出发点都集中在如何选择邻域的大小、形状和方向、参数加平均及邻域各店的权重系数等。 1、高斯滤波原理1)、高斯滤波原理 图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值,下图的所示的 3 * 3 和 5 * 5 领域的高斯模板: 1)、定义高斯核函数,计算高斯核 import cv2 import numpy as np import math #计算高斯卷积核 def gausskernel(size): sigma = 1.0 #设置σ=1.0 gausskernel = np.zeros((size, size), np.float32) #通过传递的参数尺寸设置高斯核模板 for i in range(size): #对高斯核进行遍历 for j in range(size): norm = math.pow(i - 1, 2) + pow(j - 1, 2) #求解x平方加y平方的值 gausskernel[i, j] = math.exp(-norm / (2 * math.pow(sigma, 2))) # 求高斯卷积 sum = np.sum(gausskernel) # 求和 kernel=gausskernel/sum # 归一化 return kernel2)、自定义高斯滤波函数 #自定义高斯滤波函数 def Gaussian(img,size): num = int((size - 1) / 2) # 输入图像需要填充的尺寸 img = cv2.copyMakeBorder(img, num, num, num, num, cv2.BORDER_REPLICATE)#对原图像进行扩充,处理黑边 h, w = img.shape[0:2] # 获取输入图像的长宽和高 # 高斯滤波 img1 = np.zeros((h, w, 3), dtype="uint8") kernel =gausskernel(size) # 计算高斯卷积核 for i in range(num, h - num): for j in range(num, w - num): sum = 0 q=0 p=0 for k in range(i-num, i+num+1): for l in range(j-num, j+num+1): sum = sum + img[k,l] * kernel[q,p] # 高斯滤波 p=p+1 #进行高斯核的列计数 q=q+1 #进行高斯核的行计数 p=0#内层循环执行完毕,将列计数为0,下次循环便可以再次从0开始 img1[i, j] = sum img1 = img1[(0 + num):(h-num), (0+num):(h-num)]#裁剪原图 return img1上面传递的参数一个为需要处理的图像和高斯核的尺寸 3)、读取图像添加噪声,调用自定义高斯滤波函数进行降噪处理并显示图像 #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用OpenCV库函数中的均值滤波函数 result=Gaussian(img, 5) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("Gaussian",result) cv2.waitKey(0)
图像大多数噪声均属于高斯噪声,因此高斯滤波器应用也较广泛。高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像去噪。 可以简单地理解为,高斯滤波去噪就是对整幅图像像素值进行加权平均,针对每一个像素点的值,都由其本身值和邻域内的其他像素值经过加权平均后得到。 3、OpenCV高斯滤波库函数使用既然高斯滤波比较广泛应用,因此OpenCV库函数中必有高斯滤波函数,一起了解高斯滤波库函数的使用方法吧! 1)、函数原型:result=cv2.GaussianBlur(img, (size,size), sigmaX,sigmaY) img:需要处理图像(size,size):高斯核尺寸sigmaX:X方向上的高斯核标准偏差sigmaY:Y方向上的高斯核标准偏差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigma都为零,则分别从ksize.width和ksize.height计算得出;为了完全控制结果,建议指定所有ksize,sigmaX和sigmaY。注意,核大小(size,size)必须是奇数,X方向方差主要控制权重。 2)、OpenCV高斯滤波库函数使用方法 #OpenCV高斯滤波库函数使用 import cv2 import numpy as np #读取图像 img=cv2.imread("my.jpg") #获取图像属性 h, w = img.shape[0:2] #加噪声 for i in range(3000): #添加3000个噪声点 x = np.random.randint(0, h) y = np.random.randint(0, w) img[x,y,:] = 255 #调用OpenCV库函数中的高斯滤波函数 result=cv2.GaussianBlur(img,(5,5),1,1) #传入读取的图像和核尺寸 cv2.imshow("src",img) cv2.imshow("GaussianBlur-opencv",result) cv2.waitKey(0)
以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷! 每一个人都拥有生命,却并非每个人都能读懂生命;每一个人都拥有头脑,却并非每一个人都能善用头脑。只有热爱生命,善于动脑的人,才算得上真正拥有生命。优美段落摘抄与君分享。 陈一月的又一天编程岁月^ _ ^ |
CopyRight 2018-2019 实验室设备网 版权所有 |