【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的值

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