前言

在用相机拍摄工业零件照片时,明明光线很足,画面里却总有零星的 “小雪花”—— 这就是图像噪声。噪声就像照片上的 “小瑕疵”,不仅影响画面观感,还会干扰后续的缺陷检测、特征提取。在很多工程中,都会进行噪声处理。


一、先什么是图像噪声

简单说,图像噪声就是图像中 “不该有的像素点”—— 它们不是真实场景的一部分,而是拍摄或传输过程中产生的干扰信号。就像我们听收音机时的杂音,噪声会让图像的细节变得模糊。

常见的噪声来源有 3 种:

  1. 硬件问题:相机传感器温度过高(比如工业相机长时间工作)、传感器质量不佳,都会产生噪声;
  2. 环境干扰:光线过暗或过亮(比如夜晚拍摄时的 “grainy 颗粒感”)、电磁干扰(比如靠近电机等设备时);
  3. 传输误差:图像数据在传输过程中丢失或被干扰,比如网络传输时的数据包丢失,会导致画面出现 “黑点” 或 “白点”。

在这里插入图片描述

二、常见的图像噪声类型

机器视觉里遇到最多的噪声,常见的主要是 “高斯噪声” 和 “椒盐噪声”,两者的样子和处理方式差别很大:

1. 高斯噪声

  • 特点:噪声像素的灰度值围绕真实值呈 “高斯分布”(简单理解为 “中间多、两边少”),看起来就像给图像蒙了一层淡淡的薄雾,没有明显的 “亮点” 或 “黑点”,而是整体画质变粗糙。
    在这里插入图片描述
  • 常见场景:相机传感器发热(比如夏天长时间拍摄)、低光照环境下自动提高感光度(ISO)。

在这里插入图片描述

2. 椒盐噪声

  • 特点:噪声像素只有两种 —— 要么是极亮的 “白点”,要么是极暗的 “黑点”(像撒了胡椒),随机分布在图像中,不会成片出现。
  • 常见场景:图像传输错误(比如网线接触不良)、传感器损坏(比如相机像素点故障)。
    在这里插入图片描述

三、抑制噪声

噪声会影响后续处理,比如原本要检测零件的小划痕,却被噪声误判,所以必须处理,流程很简单:

1. 噪声检测

  • 椒盐噪声:直接肉眼观察 —— 如果图像中有零星的、与周围像素反差极大的白点 / 黑点,基本就是椒盐噪声;

  • 高斯噪声:看图像细节是否 “发虚”—— 比如原本清晰的零件边缘变得模糊,放大后能看到像素灰度值 “忽高忽低”,大概率是高斯噪声。

2. 噪声抑制

处理噪声的核心是 “滤波”(具体计算过程可查看机器视觉零基础入门:(五)卷积与卷积核)—— 就像用滤网过滤杂质,通过一定规则替换噪声像素,保留真实图像信息。

(1)均值滤波:适合高斯噪声

  • 原理:用一个 “小窗口”(比如 3×3 的正方形)框住当前像素,计算窗口内所有像素的灰度平均值,用这个平均值替换当前像素。相当于 “用周围像素的平均亮度,平滑掉单个像素的波动”。

  • 优点:计算简单,能有效消除高斯噪声的 “薄雾感”;

  • 缺点:会让图像整体变模糊,不适合需要保留边缘细节的场景(比如检测零件的棱角)。

在这里插入图片描述

(2)中值滤波:适合椒盐噪声

  • 原理:同样用 “小窗口” 框住当前像素,把窗口内所有像素的灰度值按大小排序,取中间值替换当前像素。比如窗口内像素是 [5, 200, 10](200 是椒盐噪声的白点),排序后是 [5, 10, 200],取中间值 10 替换 200,直接 “去掉极端值”。

  • 优点:能精准去除椒盐噪声的白点 / 黑点,还不会让图像变模糊;

  • 缺点:对高斯噪声效果差。
    在这里插入图片描述

四、添加噪声

在平时的图像处理中,有时候也需要我们人为的去添加噪声。即噪声的“好与坏”,全看应用场景。

1.高斯噪声

高斯噪声的特点是“均匀分布、类似薄雾”,这种特性和我们真实拍摄时的很多干扰高度一致——比如低光照下的相机噪点、传感器发热产生的干扰。正因为它贴近真实场景,所以成了机器视觉中数据增强的“常客”。

比如训练AI模型时的“抗干扰训练”模型:在“干净数据”上训练得再好,遇到真实场景中的噪点就容易“翻车”。假设训练一个“零件表面划痕检测模型”,如果训练数据全是高清无噪的图片,实际工厂拍摄时因为光线变化产生的高斯噪点,就可能让模型把噪点误判为划痕。

这时候通过添加高斯噪声:给训练数据故意添加高斯噪声,让模型提前“适应”真实场景的干扰,相当于给模型做“抗干扰训练”,提升鲁棒性。

2.椒盐噪声

椒盐噪声的特点是“随机分布的白点/黑点”,这种噪声很像图像传输或存储时的“错误像素”——比如网线接触不良导致的像素丢失、存储介质损坏产生的坏点。正因为它的“突发性”和“极端性”,所以就成了很多测试算法抗干扰能力的“标准考题”。

五、代码实战

1.抑制噪声

(1)高斯噪声抑制

可以直接调用opencv的抑制接口,opencv里有对高斯噪声专门抑制的接口

cv2.GaussianBlur(src, ksize, sigmaX, sigmaY=0, borderType=cv2.BORDER_DEFAULT)
  • src:输入图像(灰度 / 彩色均可)
  • ksize:高斯核尺寸,必须是奇数(如(3,3)、(5,5)),尺寸越大去噪越强但模糊越严重
  • sigmaX:X 方向高斯核标准差,sigmaY默认与sigmaX相同;若设为 0,OpenCV 会根据ksize自动计算

(2)椒盐噪声抑制

椒盐噪声是孤立的极值点,纯白或者纯黑,中值计算会直接剔除这些极值,完美保留图像边缘和细节,可以理解是椒盐噪声的 “专属解法”,而高斯滤波对椒盐噪声几乎无效。

cv2.medianBlur(src, ksize)

2.添加噪声

(1)添加高斯噪声

import numpy as np
import cv2
import random

# 生成高斯噪声的函数
def GaussianNoise(src, means, sigma, percetage):
    NoiseImg = src.copy()
    NoiseNum = int(percetage * src.shape[0] * src.shape[1])
    for i in range(NoiseNum):
        # 每次取一个随机点(避免边缘越界,故-1)
        randX = random.randint(0, src.shape[0] - 1)
        randY = random.randint(0, src.shape[1] - 1)
        # 在原有像素灰度值上叠加高斯随机数
        NoiseImg[randX, randY] = NoiseImg[randX, randY] + random.gauss(means, sigma)
        # 限制像素值在0-255范围内
        if NoiseImg[randX, randY] < 0:
            NoiseImg[randX, randY] = 0
        elif NoiseImg[randX, randY] > 255:
            NoiseImg[randX, randY] = 255
    return NoiseImg

# 直接读取灰度图
img_gray = cv2.imread('lenna.png', 0)
# 生成带高斯噪声的图像
img_noise = GaussianNoise(img_gray, 2, 4, 0.8)

combined_img = np.hstack((img_gray, img_noise))

# 设置字体(默认字体)
font = cv2.FONT_HERSHEY_SIMPLEX
# 为原图添加注释
cv2.putText(combined_img, 'Original Image', (20, 30), font, 1, (255, 255, 255), 2)
# 为噪声图添加注释
cv2.putText(combined_img, 'Gaussian Noise Image', (img_gray.shape[1] + 20, 30),
            font, 1, (255, 255, 255), 2)

# 3. 显示拼接后的图像
cv2.imshow('Image Comparison (图像对比)', combined_img)

# 等待按键输入,任意键关闭窗口
cv2.waitKey(0)
# 释放所有窗口资源
cv2.destroyAllWindows()

(2) 添加椒盐噪声


import numpy as np
import cv2
from numpy import shape
import random

# 生成椒盐噪声的函数
def fun1(src, percetage):
    NoiseImg = src.copy()  # 复制原图,避免直接修改原数组
    NoiseNum = int(percetage * src.shape[0] * src.shape[1])
    for i in range(NoiseNum):
        # 每次取一个随机点
        # randX=行坐标,randY=列坐标(避免越界,-1)
        randX = random.randint(0, src.shape[0]-1)
        randY = random.randint(0, src.shape[1]-1)
        # 50%概率白点(255),50%概率黑点(0)
        if random.random() <= 0.5:
            NoiseImg[randX, randY] = 0
        else:
            NoiseImg[randX, randY] = 255
    return NoiseImg

# 读取图像并生成椒盐噪声
img_gray = cv2.imread('lenna.png', 0)  # 直接读取灰度图,简化代码
img_noise = fun1(img_gray, 0.2)        # 生成20%比例的椒盐噪声图

# 1. 水平拼接两张灰度图
combined_img = np.hstack((img_gray, img_noise))

# 2. 添加文字注释
font = cv2.FONT_HERSHEY_SIMPLEX  # 设置字体
# 原图注释
cv2.putText(combined_img, 'Original Image',
            (20, 30), font, 1, (255, 255, 255), 2)
# 椒盐噪声图注释
cv2.putText(combined_img, 'Salt & Pepper Noise',
            (img_gray.shape[1] + 20, 30), font, 1, (255, 255, 255), 2)

# 3. 显示拼接后的图像窗口
cv2.imshow('Original vs Salt & Pepper Noise (原图 vs 椒盐噪声)', combined_img)

# 4. 等待按键并释放资源
cv2.waitKey(0)          # 按任意键关闭窗口
cv2.destroyAllWindows() # 释放所有窗口资源

六、总结

在很多工程中基本都离不开噪声的处理,一定要搞清楚原理加以运用。同样还有很多的噪声和滤波类型,根据实际情况决定具体的使用。
(总目录跳转链接)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐