opencv 噪点的消除

1 概念

首先介绍一些概念:

噪声:指图像中的一些干扰因素,通常是由图像采集设备、传输信道等因素造成的,表现为图像中随机的亮度,也可以理解为有那么一些点的像素值与周围的像素值格格不入。常见的噪声类型包括高斯噪声和椒盐噪声。高斯噪声是一种分布符合正态分布的噪声,会使图像变得模糊或有噪点。椒盐噪声则是一些黑白色的像素值分布在原图像中。
在这里插入图片描述
滤波器:也可以叫做卷积核,与自适应二值化中的核一样,本身是一个小的区域,有着特定的核值,并且工作原理也是在原图上进行滑动并计算中心像素点的像素值滤波器可分为线性滤波和非线性滤波,线性滤波对邻域中的像素进行线性运算,如在核的范围内进行加权求和,常见的线性滤波器有均值滤波、高斯滤波等。非线性滤波则是利用原始图像与模板之间的一种逻辑关系得到结果,常见的非线性滤波器中有中值滤波器、双边滤波器等。

滤波与模糊联系与区别:

  • 它们都属于卷积,不同滤波方法之间只是卷积核不同(对线性滤波而言)
  • 低通滤波器是模糊,高通滤波器是锐化
  • 低通滤波器就是允许低频信号通过,在图像中边缘和噪点都相当于高频部分,所以低通滤波器用于去除噪点、平滑和模糊图像。高通滤波器则反之,用来增强图像边缘,进行锐化处理。

注意:椒盐噪声可以理解为斑点,随机出现在图像中的黑点或白点;高斯噪声可以理解为拍摄图片时由于光照等原因造成的噪声。

本实验中共提供了五种滤波的方式,分别为(1.均值滤波,2.方框滤波,3.高斯滤波,4.中值滤波,5.双边滤波)下面进行一一介绍。

2.均值滤波(cv2.blur)

均值滤波是一种最简单的滤波处理,它取的是卷积核区域内元素的均值,如3×3的卷积核:

k e r n e l = 1 9 [ 1 1 1 1 1 1 1 1 1 ] k e r n e l={\frac{1}{9}}{\Bigg[}\begin{array}{l l l}{1}&{1}&{1}\\{1}&{1}&{1}\\{1}&{1}&{1}\end{array}{\Bigg]} kernel=91[111111111]
在滤波算法组件中,当参数filtering_method选为均值滤波,参数component_param为ksize,代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:
在这里插入图片描述
对于边界的像素点,则会进行边界填充,以确保卷积核的中心能够对准边界的像素点进行滤波操作。在OpenCV中,默认的是使用BORDER_REFLECT_101的方式进行填充,下面的滤波方法中除了中值滤波使用的是BORDER_REPLICATE进行填充之外,其他默认也是使用这个方式进行填充,因此下面就不再赘述。通过卷积核在原图上从左上角滑动计算到右下角,从而得到新的4*4的图像的像素值。
在这里插入图片描述
代码格式如下:

cv2.blur(img,kernel)

参数说明:

  • img:要进行滤波处理的原图
    -kernel:卷积核(用元组表示)

下面是均值滤波处理椒盐噪点的代码:

'''均值滤波'''
    img=cv2.imread(r"../15day4.10/src/lvbo3.png")
    img2=cv2.blur(img,(3,3))
    cv2.imshow("img",img)
    cv2.imshow("Img2",img2)
    cv2.waitKey(0)

在这里插入图片描述

如图所示:

  • 图像中的噪点变模糊了
  • 但是模糊的噪点变大了

2. 方框滤波(cv2.boxFilter())

方框滤波跟均值滤波很像,如3×3的滤波核如下:
k e r n e l = a [ 1 1 1 1 1 1 1 1 1 ] k e r n e l={a}{\Bigg[}\begin{array}{l l l}{1}&{1}&{1}\\{1}&{1}&{1}\\{1}&{1}&{1}\end{array}{\Bigg]} kernel=a[111111111]
在滤波算法组件中,当参数filtering_method选为方框滤波时,参数component_param为ksize,ddepth,normalize。下面讲解这3个参数的含义:
在这里插入图片描述
ksize:代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

ddepth:输出图像的深度,-1代表使用原图像的深度。

normalize:当normalize为True的时候,方框滤波就是均值滤波,上式中的a就等于1/9;normalize为False的时候,a=1,相当于求区域内的像素和

其滤波的过程与均值滤波一模一样,都采用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,直至到达图像右下角,唯一的区别就是核值可能会不同。
在这里插入图片描述
代码格式如下:

cv2.boxFilter(img,ksize,ddepth,normalize)

参数说明:

  • ksize:代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

  • ddepth:输出图像的深度,-1代表使用原图像的深度。

  • normalize:当normalize为True的时候,方框滤波就是均值滤波,上式中的a就等于1/9;normalize为False的时候,a=1,相当于求区域内的像素和

代码如下:

 '''方框滤波'''
    img=cv2.imread(r"../15day4.10/src/lvbo3.png")
    img2=cv2.boxFilter(img,ksize=(3,3),ddepth=-1,normalize=True) #normalize=True表示均值滤波3*3的核每个的权重为1/9
    img2=cv2.boxFilter(img,ksize=(3,3),ddepth=-1,normalize=False) #normalize=False表示均值滤波3*3的核每个的权重为1,再将每个值加起来
    cv2.imshow("img",img)
    cv2.imshow("Img2",img2)
    cv2.waitKey(0)

normalize=True的图像
在这里插入图片描述
normalize=False的图像
在这里插入图片描述

3. 高斯滤波(cv2.GaussianBlur())

前面两种滤波方式,卷积核内的每个值都一样,也就是说图像区域中每个像素的权重也就一样。 高斯滤波的卷积核权重并不相同:中间像素点权重最高,越远离中心的像素权重越小。 还记得我们在自适应二值化里是怎么生成高斯核的吗?这里跟自适应二值化里生成高斯核的步骤是一样的,都是以核的中心位置为坐标原点,然后计算周围点的坐标,然后带入下面的高斯公式中。
g ( x , y ) = 1 2 π σ 2 e − ( x 2 + y 2 ) 2 σ 2 g(x,y)=\frac{1}{2\pi\sigma^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}} g(x,y)=2πσ21e2σ2(x2+y2)
其中的值也是与自适应二值化里的一样,当时会取固定的系数,当kernel大于7并且没有设置时,会使用固定的公式进行计算 σ \sigma σ的值:
σ = 0.3 ∗ ( ( k s i z e − 1 ) ∗ 0.5 − 1 ) + 0.8 \sigma=0.3*\left((k s i z e-1)*0.5-1\right)+0.8 σ=0.3((ksize1)0.51)+0.8
我们还是以3*3的卷积核为例,其核值如下所示:
  k e r n e l = [ 0.0625      0.125      0.0625 0.125      0.25      0.125 0.0625      0.125      0.0625 ] = [ 1 16     1 8     1 16 1 8     1 4     1 8 1 16     1 8     1 16 ] \ k e r n e l=\left[\begin{array}{c}{{0.0625~~~~0.125~~~~0.0625}}\\{{0.125~~~~0.25~~~~0.125}}\\{{0.0625~~~~0.125~~~~0.0625}} \end{array}\right]=\left[\begin{array}{c c c}{\frac{1}{16}~~~\frac{1}{8}~~~\frac{1}{16}}\\{\frac{1}{8}~~~\frac{1}{4}~~~\frac{1}{8}}\\{\frac{1}{16}~~~\frac{1}{8}~~~\frac{1}{16}}\end{array}\right]  kernel= 0.0625    0.125    0.06250.125    0.25    0.1250.0625    0.125    0.0625 = 161   81   16181   41   81161   81   161
得到了卷积核的核值之后,其滤波过程与上面两种滤波方式的滤波过程一样,都是用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,直至到达图像右下角,唯一的区别就是核值不同。

在滤波算法组件中,当参数filtering_method选为高斯滤波,参数component_param为ksize,sigmaX。下面讲解这2个参数的含义:
在这里插入图片描述
在这里插入图片描述

代码格式如下:

cv2.GaussianBlur(img,ksize,sigmaX)

参数说明:

  • ksize:代表卷积核的大小(用元组表示)

  • sigmaX:就是高斯函数里的值,σx值越大,模糊效果越明显。高斯滤波相比均值滤波效率要慢,但可以有效消除高斯噪声,能保留更多的图像细节,所以经常被称为最有用的滤波器。均值滤波与高斯滤波的对比结果如下(均值滤波丢失的细节更多)

下面是高斯滤波处理高斯噪点的代码:

 '''高斯滤波'''
    img=cv2.imread(r"../15day4.10/src/lvbo2.png") #高斯噪点的原图
    img2=cv2.GaussianBlur(img,ksize=(3,3),sigmaX=10)
    cv2.imshow("img",img)
    cv2.imshow("Img2",img2)
    cv2.waitKey(0)

在这里插入图片描述

4. 中值滤波(cv2.medianBlur())

中值又叫中位数,是所有数排序后取中间的值。中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值,其过程如下所示:
在这里插入图片描述
中值滤波就是用区域内的中值来代替本像素值,所以那种孤立的斑点,如0或255很容易消除掉,适用于去除椒盐噪声和斑点噪声。中值是一种非线性操作,效率相比前面几种线性滤波要慢。

比如下面这张斑点噪声图,用中值滤波显然更好:
在这里插入图片描述
代码格式如下:

cv2.medianBlur(img,ksize)

代码如下:

 img=cv2.imread(r"../15day4.10/src/lvbo3.png") #读取的是椒盐噪点的图
    img2=cv2.medianBlur(img,ksize=3)
    cv2.imshow("img",img)
    cv2.imshow("Img2",img2)
    cv2.waitKey(0)

在这里插入图片描述
如图所示中值滤波处理椒盐噪点时几乎没有噪点,这是因为这些噪点分布不均匀,而在一个卷积核中噪点,要么是最小值或者最大值,根本取不到噪点的值作为中位数

注意:

  • 中值滤波适用于处理椒盐噪点,高斯噪点因为噪点分布比较均匀中值滤波处理效果也不是很好
  • 中值滤波因为需要排序,所以执行效率比较低

5. 双边滤波(cv2.bilateralFilter())

模糊操作基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。
在这里插入图片描述
双边滤波的原理
代码格式如下:

cv2.bilateralFilter(img,d,sigmacolor,sigmaspace)

参数说明:

  • d:过滤时周围每个像素领域的直径
  • sigmaColor:在color space中过滤sigma。参数越大,临近像素将会在越远的地方mix。
  • sigmaSpace:在coordinate space中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。

关于2个sigma参数:

简单起见,可以令2个sigma的值相等;

如果他们很小(小于10),那么滤波器几乎没有什么效果;

如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化。

关于参数d:

过大的滤波器(d>5)执行效率低。

对于实时应用,建议取d=5;

对于需要过滤严重噪声的离线应用,可取d=9;

代码如下:

  '''双边滤波'''
    img=cv2.imread(r"../15day4.10/src/lvbo2.png") #高斯噪点的原图
    img2=cv2.bilateralFilter(img,5,150,150)
    cv2.imshow("img",img)
    cv2.imshow("Img2",img2)
    cv2.waitKey(0)

在这里插入图片描述

6. 小结

在不知道用什么滤波器好的时候,优先高斯滤波,然后均值滤波。

斑点和椒盐噪声优先使用中值滤波。

要去除噪点的同时尽可能保留更多的边缘信息,使用双边滤波。

线性滤波方式:均值滤波、方框滤波、高斯滤波(速度相对快)。

非线性滤波方式:中值滤波、双边滤波(速度相对慢)。

### 使用OpenCV在C++中去除图像 为了有效去除图像中的,在计算机视觉领域通常采用多种方法和技术。对于周期性声,可以在傅里叶变换后的频域内进行处理[^4];而对于随机分布的椒盐声或其他类型的加性白声,则可以考虑空间域内的滤波技术。 #### 基于形态学操作的简单降方案 一种常见的做法是在应用`findContours`之前对二值化后的图像执行形态学开闭运算以消除音[^3]: ```cpp cv::Mat src; // 输入图像 cv::Mat gray; cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY); // 应用高斯模糊减少高频细节带来的干扰 cv::GaussianBlur(gray, gray, cv::Size(5, 5), 0); // 自动阈值分割得到二值图 cv::threshold(gray, gray, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); // 定义结构元素用于形态学转换 cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2 * 2 + 1, 2 * 2 + 1), cv::Point(2, 2)); // 形态学开运算先腐蚀再膨胀,用来移除小对象 cv::morphologyEx(gray, gray, cv::MORPH_OPEN, element); ``` 此代码片段展示了通过形态学开运算来清理二值化的图像数据,从而达到初步降的效果。这种方法特别适合处理具有较大连通区域的目标物体,并能有效地过滤掉较小尺寸的孤立像素或斑。 #### 利用双边滤波器实现更精细的去效果 当面对彩色图片或是希望保留边缘特征的同时平滑表面纹理时,推荐使用双边滤波算法。该方法能够在保持边界清晰度的前提下削弱局部变化剧烈的颜色差异所造成的伪影现象。 ```cpp int d = 9; // 邻域直径 double sigmaColor = 75; double sigmaSpace = 75; cv::bilateralFilter(src, src, d, sigmaColor, sigmaSpace); ``` 上述设置参数可以根据实际应用场景灵活调整,其中邻域直径决定了每次计算涉及范围大小,而两个标准差则分别控制着颜色相似性和空间距离的影响程度。 #### FastNLMeansDenoisingColored函数的应用实例 针对更加复杂的多通道影像资料(如RGB色彩模式),OpenCV提供了专门优化过的快速非局部均值去工具——FastNLMeansDenoisingColored()。它能够高效地抑制各种形式的随机声而不破坏原始信号特性。 ```cpp float h = 10.f; // H通道强度调节因子 float hForColorComponents = 10.f; std::vector<cv::Mat> img_planes; cv::split(src, img_planes); for(size_t i=0;i<img_planes.size();i++) { cv::fastNlMeansDenoising(img_planes[i],img_planes[i],h); } cv::merge(img_planes,src); ``` 这段程序实现了分层处理各单色平面后再重新组合成完整彩照的过程,使得最终输出既干净又不失真。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值