OpenCV之图像模糊操作

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

1.均值滤波

图像的滤波操作本质上是对图像进行卷积,具体步骤是定义卷积核,卷积核中每个位置有相应的权重参数,在卷积核区域内的图像像素点与对应位置的权重参数相乘后经过某种方法得出一个新的值代替原区域中的中心像素点(不同的滤波操作有不同的选取方法),达到图像模糊化的效果,权重参数的设置直接影响模糊的效果,滤波操作不仅能使图像模糊,也可对图像进行降噪。
滤波的过程:

均值滤波是指卷积核内的权重参数全部为1,经卷积操作后相乘再相加再除以卷积核的大小得到新的值代替中心像素点的方法,是线性滤波操作之一,OpenCV提供的相关的API是blur,具体如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path)
#加噪声
h,w,c = image.shape
for i in range(20000):
    x = np.random.randint(0,h)
    y = np.random.randint(0,w)
    image[x,y,:] = 255
result = cv.blur(image,(7,7))
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

均值滤波的API为blur(),其参数非常简单,src为输入的图像,ksize为卷积核的大小,卷积核的两个维度必为奇数,因为只有奇数有中心点。
原图:
image.png
加上噪声后:
image.png
降噪:
image.png
均值滤波存在一定的缺点,它不能很好地保留图像的细节,去除噪声的同时也损害了图像的细节,使得图像过于模糊,而且其本身的降噪效果也不太好,特别是对椒盐噪声。

2.中值滤波

中值滤波是非线性的滤波操作,对于去除椒盐噪声有比较好的效果。中值滤波是将邻域内的所有像素值进行排列,取出其中间值代替原邻域内的中心像素值,具体如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path)
h,w,c = image.shape
for i in range(20000):
    x = np.random.randint(0,h)
    y = np.random.randint(0,w)
    image[x,y,:] = 255
result = cv.medianBlur(image,7)
cv.imshow("result",result)
cv.imshow("image",image)
cv.waitKey(0)
cv.destroyAllWindows()

API为medianBlur(),参数src为输入的图像,ksize为核的大小,同样需要是大于1的奇数,处理结果输出如下:
image.png
可以看到处理结果比均值滤波的效果好。

3.高斯滤波

高斯滤波与均值滤波一样是线性滤波,只不过卷积核内的权重参数符合高斯分布(此时的高斯分布是二维的高斯分布),在卷积核内部对应位置的像素值和权重参数相乘并累加,再除以权重参数的总和得到新值作为中心像素点的像素值。高斯滤波适合用来降低服从高斯分布的噪声,在通常情况下我们会假定图像的噪声是高斯白噪声,因此使用高斯滤波进行平滑操作是比较常见的,具体如下:
二维高斯分布公式:
image.png

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path)
h,w,c = image.shape
noise = np.random.randn(h,w)*10
noise = np.uint8(noise)
image[:,:,0] += noise
image[:,:,1] += noise
image[:,:,2] += noise
cv.normalize(image,image,0,255,cv.NORM_MINMAX)
result = cv.GaussianBlur(image,(0,0),5)#sigmaX,ksize参数必须有,ksize=(0,0)时由sigmaX参数反算ksize,且两者不能同时为零
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

OpenCV提供的对应的API是GaussianBlur(),最主要的两个参数是ksize和sigmaX,两者只要其中一个为真值,另外一个不起作用,故两者不能同时为零,具体输出如下:
加入高斯噪声的图片:
image.png
经处理后:
image.png

4.双边滤波

在使用高斯滤波时,会发现图像更加模糊,这是因为高斯滤波对于边缘的信息保留的效果不是很好,在高斯滤波中,越靠近卷积核中心的权重越大,考虑了空间上的临近性但没有关注到像素值的相似性的保留。而双边滤波结合了两者,基于两个函数生成卷积核,一是计算空间距离,而是计算灰度距离,公式如下:
空间距离:
image.png
( x i x_i , y i y_i )为邻域内某一点的位置,( x c x_c , y c y_c )为中心点的位置
灰度距离:
image.png
g r a y ( x i , y i ) gray(x_i,y_i) 为邻域某点的灰度值, g r a y ( x c , y c ) gray(x_c,y_c) 为中心点的灰度值。
其实两个公式的本质也是高斯函数,
最终的权重参数的分布由两个函数的值相乘决定。
具体如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path)
h,w,c = image.shape
noise = np.random.randn(h,w)*10
noise = np.uint8(noise)
image[:,:,0] += noise
image[:,:,1] += noise
image[:,:,2] += noise
cv.normalize(image,image,0,255,cv.NORM_MINMAX)
result = cv.bilateralFilter(image,0,100,10)
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

OpenCV提供的API是bilateralFilter(),其中最重要的参数是sigmaColor和sigmaSpace。

sigmaColor是指灰度距离高斯函数的sigma,其值越大,高斯图像越“矮胖”,图像边缘越模糊,极限情况下其值为常数,使得双边滤波其无限接近于高斯滤波;其值越小,高斯图像越“瘦高”,图像边缘的保留的越完整。
sigmaSpace是指空间距离高斯函数的sigma,类似与高斯滤波的sigmaX,其值越大图像越模糊,极限情况下,每个权重参数会趋于一个固定的相同值,与均值滤波类似,但权重参数不为一;其值越小,中心位置的权重参数越大,周围权重参数越小,对图像的过滤作用越小,越接近于原图。
至于参数d,是指邻域半径的大小,通常定为0,再由sigmaSpace反算出d。
处理后的效果:
image.png
明显对于边缘信息保留效果优于高斯滤波。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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