【OpenCV】彩色RGB图像添加高斯噪声(Gaussian Noise)

简介

高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声,高斯噪声是一个加性噪声(加性噪声一般指热噪声、散弹噪声等,它们与信号的关系是相加,不管有没有信号,噪声都存在)。

产生原因:
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.csdn.net/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的值

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章