简介
高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声,高斯噪声是一个加性噪声(加性噪声一般指热噪声、散弹噪声等,它们与信号的关系是相加,不管有没有信号,噪声都存在)。
产生原因:
1)图像传感器在拍摄时市场不够明亮、亮度不够均匀;
2)电路各元器件自身噪声和相互影响;
3)图像传感器长期工作,温度过高。
这里说一下高斯白噪声:
白噪声是一种功率谱密度为常数的随机信号或随机过程。换句话说,此信号在各个频段上的功率是一样的,由于白光是由各种频率(颜色)的单色光混合而成,因此此信号的这种具有平坦功率谱的性质被称作是“白色”,此信号也因此被称作白噪声。相对的,其他不具有这一性质的噪声信号被称为有色噪声(功率谱随频率变化)。
当随机的从高斯分布中获取采样值时,采样点所组成的随机过程就是“高斯白噪声”;同理,当随机的从均匀分布中获取采样值时,采样点所组成的随机过程就是“均匀白噪声”。
“非白的高斯”噪声——高斯色噪声。这种噪声其分布是高斯的,但是他的频谱不是一个常数,或者说,对高斯信号采样的时候不是随机采样的,而是按照某种规律来采样的。
这么说来我们添加的高斯噪声应该大部分都为高斯白噪声。
对于灰度图像的添加高斯噪声有很多,也比较简单,没有什么疑问。而对于彩色图像,由于有三个通道,如何将高斯噪声添加进去也有了不同的方法。目前我见到两种方法:
(1)将彩色图像分为RGB三个通道,对每个通道都添加高斯噪声,这样添加的高斯噪声会在图像上形成彩色的噪点。
(2)将彩色图像从RGB颜色模式转换为YCC颜色模式,对其中的亮度通道添加高斯噪声,而后将YCC颜色模式再转回RGB模式,这样添加的高斯噪声在图像上只会表现出亮度不同的噪点,不对颜色造成影响。
效果如下图:
原始图像:
RGB三通道加高斯噪声图像:
YCC模式下Y道加高斯噪声图像:
OpenCV 代码
#include <opencv2/opencv.hpp>
#include <iostream>
#include <time.h>
using namespace cv;
using namespace std;
///
//1. 将彩色图像分为RGB三个通道,对每个通道都添加高斯噪声,这样添加的高斯噪声会在图像上形成彩色的噪点。
// 方法来源:
///
void GaussianNoiseFullChannel(const Mat &src, Mat &dst, double u, double v);
///
//2. 将彩色图像转为YCC颜色模式,分离通道,对Y通道添加高斯噪声,合并通道(噪声图像无颜色变化,有亮度变化)
// 方法来源: https://blog.youkuaiyun.com/cutelily2014/article/details/50253583
///
void GaussianNoiseSingleChannel(const Mat &src, Mat &dst, double u, double v);
int main()
{
Mat srcImg = imread("C:\\Users\\Wei\\Desktop\\w.jpg",IMREAD_COLOR);//原图
Mat dstImg1;
Mat dstImg2;
double u = 0.0;
double v = 15.0;
GaussianNoiseFullChannel(srcImg, dstImg1,u,v);
GaussianNoiseSingleChannel(srcImg, dstImg2, u, v);
imshow("img", srcImg);//显示噪声图像;
imshow("Full Channel", dstImg1);//显示噪声图像;
imshow("Single Channel", dstImg2);//显示噪声图像;
imwrite("C:\\Users\\Wei\\Desktop\\dstImg1.jpg", dstImg1);
imwrite("C:\\Users\\Wei\\Desktop\\dstImg2.jpg", dstImg2);
waitKey(0);
destroyAllWindows();
return 0;
}
void GaussianNoiseSingleChannel(const Mat &src, Mat &dst,double u, double v)
{
if (src.empty() || src.channels() != 3)
{
cout << "Image is empty or not 3 channels" << endl;
return;
}
Mat noiseImg(src.size(), CV_64FC1); //存放噪声图像
RNG rng((unsigned)time(NULL)); //生成随机数 (均值,高斯)
rng.fill(noiseImg, RNG::NORMAL, u, v); //随机高斯填充矩阵
Mat yccImg; //用来进行对原图像的转换
cvtColor(src, yccImg, COLOR_BGR2YCrCb); //色彩空间转换;
Mat sigImg[3]; //用来存储单通道图像
split(yccImg, sigImg); //将图像分解到单通道,一幅灰度图像
sigImg[0].convertTo(sigImg[0], CV_64FC1); //将uchar转为double
sigImg[0] = sigImg[0] + noiseImg; //添加高斯噪声()
sigImg[0].convertTo(sigImg[0], CV_8UC1); //Y通道加高斯噪声后图像,自动截断小于零和大于255的值
Mat gaussianImg(src.size(), CV_8UC3); //添加高斯噪声的图像;
merge(sigImg, 3, gaussianImg); //和并三个通道
cvtColor(gaussianImg, dst, COLOR_YCrCb2BGR); //色彩空间转换
//imshow("noise", sigImg[0]); //显示噪声图像
}
void GaussianNoiseFullChannel(const Mat &src, Mat &dst,double u,double v)
{
if (src.empty() || src.channels() != 3)
{
cout << "Image is empty or not 3 channels" << endl;
return;
}
Mat noiseImg(src.size(), CV_64FC3); //存放噪声图像
RNG rng((unsigned)time(NULL)); //生成随机数 (均值,高斯)
rng.fill(noiseImg, RNG::NORMAL, u, v); //随机高斯填充矩阵
Mat gaussianImg;
src.convertTo(gaussianImg, CV_64FC3); //将uchar转换为double格式
gaussianImg = gaussianImg + noiseImg; //添加噪声
gaussianImg.convertTo(dst, CV_8UC3); //将double转为uchar 自动截断小于零和大于255的值
}