5 高斯噪声(Gaussian Noise)
高斯噪声(Gaussian Noise)是一种符合正态(高斯)分布的随机噪声,广泛存在于传感器采集、信号传输等场景中。以下是关于高斯噪声的详细说明、添加方法及滤波方案。
特点:符合正态分布,模拟传感器噪声。
噪声值服从正态分布
其中:
μ(均值):通常为 0(对称分布);σ
σ(标准差):控制噪声强度(值越大,噪声越明显)
视觉表现:图像上出现细密的颗粒状噪声,类似“电视雪花”效果。
5.1 加入噪声
void addGaussianNoise(cv::Mat &image, double mean=0, double stddev=15) {
cv::Mat noise = cv::Mat::zeros(image.size(), image.type());
cv::randn(noise, mean, stddev); // 生成高斯噪声
image += noise;
cv::normalize(image, image, 0, 255, cv::NORM_MINMAX, image.type()); // 防止溢出
}
5.2 高斯滤波
原理:使用高斯核加权平均,与噪声分布特性匹配。
优点:计算高效,适合实时处理。
OpenCV 函数:cv::GaussianBlur()
函数原型:
void cv::GaussianBlur(
InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
);
参数:
ksize Size 高斯核大小(宽度和高度,必须为正奇数如3x3、5x5)。
sigmaX double X方向标准差。若为0,则自动从ksize计算:sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8
sigmaY double Y方向标准差(默认=0,表示与sigmaX相同)。
borderType int 边界填充方式(默认BORDER_DEFAULT)。
参考应用:
cv::Mat denoised;
cv::GaussianBlur(noisy_img, denoised, cv::Size(5, 5), 1.5); // 内核大小5x5,标准差1.5
5.4 双边滤波(Bilateral Filter)
原理:同时考虑空间距离和像素值差异,保留边缘。
bilateralFilter 为双边滤波,d 为计算的半径,在 d 以内的像素点会被纳入计算,如果 d=-1,则根据 sigmas 参数取值进行处理。Sigmac 决定多少差值之内的像素点会被计算。Sigmas 和 d 的值有关,如果 d 大于0,该值无效,如果小于 0,则根据 sigmas 来计算 d 的值。
优点:边缘保持效果好。
OpenCV 函数:cv::bilateralFilter()
cv::Mat denoised;
cv::bilateralFilter(noisy_img, denoised, 9, 75, 75); // 直径9,颜色/空间标准差75
5.5 总结
6 椒盐噪声(Salt-and-Pepper Noise)
椒盐噪声是一种常见的图像噪声,表现为随机出现的 纯白(盐噪声) 和 纯黑(椒噪声) 像素点,通常由传感器故障、信号传输错误或存储介质损坏引起。以下是其特性、添加方法及去噪方案。
6.1 定义
噪声像素值为 0(黑) 或 255(白),随机分布在图像中
视觉表现:图像上散落黑白点,类似胡椒和盐粒。
6.2 添加椒盐噪声
#include "random"
void addSaltPepperNoise(cv::Mat &image, double prob = 0.05) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, 1.0);
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
double r = dis(gen);
if (r < prob / 2) {
image.at<cv::Vec3b>(i, j) = cv::Vec3b(0, 0, 0); // 椒噪声(黑)
} else if (r < prob) {
image.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255); // 盐噪声(白)
}
}
}
}
6.3 中值滤波(Median Filter)
原理:用邻域像素的中值替代中心像素,有效消除孤立噪点。
优点:计算快,适合实时处理。
OpenCV 函数:cv::medianBlur()
cv::Mat denoised;
cv::medianBlur(noisy_img, denoised, 5); // 内核大小5x5(必须为奇数)
medianBlur 为中值滤波,ksize 为中值滤波的窗口大小。
6.5 总结
7 参考案例
7.1 模糊案例
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main (int argc,char **argv)
{
Mat src = imread("cyq.jpg",1);
if(src.empty())
{
cout << "Could not load image.."<<endl;
return -1;
}
Mat image1,image2,image3;
blur(src,image1,Size(3,3),Point(-1,-1));
blur(src,image2,Size(29,1),Point(-1,-1));
blur(src,image3,Size(1,20),Point(-1,-1));
imshow("input",src);
imshow("output1",image1);
imshow("output2",image2);
imshow("output3",image3);
waitKey(0);
return 0;
}
这部分代码很简单,使用 mat 将图像信息装起来,然后调用 OpenCV 提供的 blur 接口进行模糊,通过调整 Size 参数来看看均值滤波的效果。第一次调用 Size(3,3),表示卷积算子的大小为 3*3,这个值是可以随意改变的,但必须是正数,后面的 Point 表示采用卷积算子的中心点为计算结果。后面将 size 中的参数改变,例如 Size(29,1)是 x 方向的模糊,因为我们平时看到的移动都是相对于地面的,所以转换出来的图像像是瞬间移动了;Size(1,20)是在 y 方向的模糊,看起来像是向上跳跃的感觉。
7.1 中值滤波
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main (int argc,char **argv)
{
Mat src = imread("nn.png",1);
if(src.empty())
{
cout << "Could not load image.."<<endl;
return -1;
}
Mat dst;
medianBlur(src,dst,3);
imshow("input",src);
imshow("output",dst);
waitKey(0);
return 0;
}