当前位置: 首页 > news >正文

图像预处理-图像噪点消除

一.基本介绍

噪声:指图像中的一些干扰因素,也可以理解为有那么一些点的像素值与周围的像素值格格不入。常见的噪声类型包括高斯噪声和椒盐噪声。

滤波器:也可以叫做卷积核

- 低通滤波器是模糊,高通滤波器是锐化

- 低通滤波器就是允许低频信号通过,在图像中边缘噪点都相当于高频部分,所以低通滤波器用于去除噪点、平滑和模糊图像。高通滤波器则反之,用来增强图像边缘,进行锐化处理。

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

这是高斯噪声


这是椒盐噪声,有很多黑白的或者孤立的小点


1.1 均值滤波

cv.blur(img, ksize)

参数:

- ksize:代表卷积核的大小

取的是卷积核区域内元素的均值

        对于边界的像素点,则会进行边界填充,以确保卷积核的中心能够对准边界的像素点进行滤波操作。在OpenCV中,默认的是使用BORDER_REFLECT_101的方式进行填充,下面的滤波方法中除了中值滤波使用的是BORDER_REPLICATE进行填充之外,其他默认也是使用这个方式进行填充

import cv2 as cvimg = cv.imread('../images/lvbo2.png')# 均值滤波,用3*3的卷积核
blur = cv.blur(img, (3, 3))cv.imshow('img', img)
cv.imshow('blur', blur)
cv.waitKey(0)
cv.destroyAllWindows()

1.2 方框滤波

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

参数:

- ksize:代表卷积核的大小

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

指在每个像素点所使用的位数(bit depth),也就是用来表示图像中每一个像素点的颜色信息所需的二进制位数。图像深度决定了图像能够表达的颜色数量或灰度级。

- normalize:当normalizeTrue的时候,方框滤波就是均值滤波,权重就等于1/9;normalizeFalse的时候,每个像素权重都是1,相当于求区域内的像素和,超出部分取模运算。

import cv2 as cvimg = cv.imread('../images/lvbo2.png')# 方框滤波,用3*3的卷积核,类似均值滤波
box = cv.boxFilter(img, -1,(3, 3),normalize=True)# 真正的方框滤波
box1 = cv.boxFilter(img, -1,(3, 3), normalize=False)cv.imshow('img', img)
cv.imshow('box', box)
cv.imshow('box1', box1)
cv.waitKey(0)
cv.destroyAllWindows()

跟均值滤波很像

        可以看到这里的方框滤波显示图片是很接近白色的,因为其将像素点周围的像素权重都设为1,然后相加得到该像素的值,所以很多都超过了255而进行了取模操作。

1.2 高斯滤波

cv.GaussianBlur(img, ksize, sigmaX)

参数:

- sigmaX

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

通过使用高斯函数(正态分布)作为卷积核来对图像进行模糊处理。

import cv2 as cvimg = cv.imread('../images/lvbo2.png')# 高斯,用3*3的卷积核
Gauss = cv.GaussianBlur(img, (3, 3), 1)cv.imshow('img', img)
cv.imshow('Gauss', Gauss)cv.waitKey(0)
cv.destroyAllWindows()

1.3 中值滤波

cv.medianBlur(img, ksize)

        中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值。就是用区域内的中值来代替本像素值,所以那种孤立的斑点,如0或255很容易消除掉,适用于去除椒盐噪声斑点噪声

import cv2 as cv# 导入椒盐噪声图片
img = cv.imread('../images/lvbo3.png')# 中值滤波,注意这里的3
median = cv.medianBlur(img, 3)cv.imshow('img', img)
cv.imshow('median', median)cv.waitKey(0)
cv.destroyAllWindows()

        其实你会注意到,中值滤波的ksize为啥是个整数呢,前面的都是(x,x)。因为中值滤波是非线性的,且没有核值不依赖卷积核权重。

1.4 双边滤波

cv.bilateralFilter(img,ksize,d,sigmaColor,sigmaSpace)

参数:

- d:过滤时周围每个像素领域的直径,这里已经设置了核大小。d=9===>9x9

- sigmaColor:在color space值域空间)中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。较大的sigmaColor意味着更大的颜色差异将被允许参与到加权平均中.

- sigmaSpace:在coordinate space坐标空间)中过滤sigma。这个参数是坐标空间中的标准差,决定了像素位置对滤波结果的影响程度。

双边滤波的基本思路是同时考虑将要被滤波的像素点的空域(空间)信息(周围像素点的位置的权重)和值域信息(周围像素点的像素值的权重)。因为在边缘处,临近的像素点差异会比较大,如果只是使用空域信息来进行滤波的话,得到的结果必然是边缘被模糊了,这样我们就丢掉了边缘信息。这也是一种非线性滤波

import cv2 as cvimg = cv.imread('../images/lvbo2.png')# 双边滤波
sb = cv.bilateralFilter(img, 9, 100, 100)cv.imshow('img', img)
cv.imshow('sb', sb)cv.waitKey(0)
cv.destroyAllWindows()

注意:

关于2个sigma参数:

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

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

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

关于参数d

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

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

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

二.图像梯度处理

2.1 图像梯度

        把图片想象成连续函数,因为边缘部分的像素值是与旁边像素有明显区别,所以对图片局部求极值,就可以得到整幅图片的边缘信息了。不过图片是二维的离散函数,导数就变成了差分,这个差分就称为图像的梯度

2.2 垂直边缘提取

        这个核是用来提取图片中的垂直边缘(右侧边缘,若提取左边缘卷积核中正负号换一下就好)的,中间像素就是这个卷积核卷积的结果

        当前列左右两侧的元素进行差分,由于边缘(当前列)的值明显小于(或大于)周边像素,所以边缘(当前列)的差分结果会明显不同,这样就提取出了垂直边缘。简单理解,就是在‘1’位置右边的像素值相对于‘-1’位置左边的像素值的差距会显示在中间的像素中,所以中间的列就是旁边两列的垂直差分

来介绍一下二维卷积函数:

cv2.filter2D(src, ddepth, kernel)

- src: 输入图像,一般为numpy数组。

- ddepth: 输出图像的深度,可以是负值(表示与原图相同)、正值或其他特定值(常用-1 表示输出与输入具有相同的深度)。

- kernel: 卷积核,一个二维数组(通常为奇数大小的方形矩阵),用于计算每个像素周围邻域的加权和。

import cv2 as cv
import numpy as np# 模拟一张图像,灰度图
img=np.array([[100,102,109,110,98,20,19,18,21,22],[109,101,98,108,102,20,21,19,20,21],[109,102,105,108,98,20,22,19,19,18],[109,98,102,108,102,20,23,19,20,22],[109,102,105,108,98,20,22,19,20,18],[100,102,108,110,98,20,19,18,21,22],[109,101,98,108,102,20,22,19,20,21],[109,102,108,108,98,20,22,19,19,18],],dtype=np.float32)
# 定义卷积核,
kernel=np.array([[-1,0,1],[-2,0,2],[-1,0,1]],dtype=np.float32)
# 二维卷积操作
img2=cv.filter2D(img,-1,kernel)
# 打印卷积后的图
print(img2)

[[   0.   -4.   30.  -14. -356. -320.   -6.    2.   12.    0.]
 [   0.  -17.   28.  -10. -354. -317.   -5.   -3.    7.    0.]
 [   0.  -26.   29.  -10. -352. -312.   -4.  -10.    3.    0.]
 [   0.  -22.   32.  -14. -352. -310.   -4.  -11.    4.    0.]
 [   0.   -7.   30.  -24. -354. -310.   -5.   -5.    5.    0.]
 [   0.    1.   29.  -23. -356. -314.   -6.    0.    9.    0.]
 [   0.  -15.   28.  -12. -354. -315.   -5.   -5.    7.    0.]
 [   0.  -24.   26.  -12. -352. -312.   -4.  -10.    2.    0.]]

        这里的值就是用上面的卷积核计算的,其中边缘由于使用边界反射101进行填充,左右两边的差分为0,也就是无梯度变化。然后中间两列有着超出255的最大数值,这就会作为边缘被提取出来。

        差分后值的符号正负代表梯度的方向,差分值实际应该取绝对值,毕竟我们只是想看数值大小来提取边缘。值超过了255都算(+-)255,即使是负号。

如果使用的是一张真正的图片进行特征提取,建议转化为灰度图(单通道)方便计算。

相关文章:

  • 星智CASE|拆解行业工具类智能体搭建方法论!
  • 12.FFN基于位置的前馈网络
  • 中华传承-医山命相卜-易经
  • Linux MySQL版本升级(rpm安装方式)
  • 嵌入式开发--STM32G4系列硬件CRC支持MODBUS和CRC32
  • mybatisFlex各种链式sql写法
  • 深度比较Gemini 2.5两款最新模型差异
  • Python基础知识语法归纳总结(数据类型-1)
  • python_level1.2
  • Android模块编译无法找到依赖(shared_libs)
  • 【Vue3代理机制详解:从原理到实践】
  • LeadeRobot具身智能应用标杆:无人机X柔韧具身智能,空中精准作业游刃有余
  • 6. 实战(二):用Spring AI+OpenAI构建企业级智能客服
  • STM32学习2
  • 自学新标日第十九课复习版本
  • 驱动移植【简略版】
  • Vue3中provide和inject的用法示例
  • 第 4 期:DDPM中的损失函数——为什么只预测噪声?
  • 守护进程及gdb调试(新手简略版)
  • 数控铣床自动上下料机械手控制装置设计
  • 清华成立教育学院:加快高层次人才培养、加强教育学科建设
  • 阿塞拜疆总统阿利耶夫将访华
  • 上海古籍书店重新开卷,在这里淘旧书获新知
  • 一中国公民在日本滑雪场意外死亡,我领馆发布提醒
  • 大理州工业投资(集团)有限公司党委副书记、副总经理赵云接受审查调查
  • 2025年福建省文旅经济发展大会召开