1. 程式人生 > >利用CImage類對影象進行高斯噪聲生成

利用CImage類對影象進行高斯噪聲生成

    課上作業要求利用C裡面的自帶類庫對影象做一個高斯噪聲的生成,記錄一下大概的原理和步驟。

    首先是對高斯函式的理解

   

    這個函式是一個高斯概率密度的分佈表示式,表示為X~N(μ,σ²),其中μ表示均值,σ²表示方差,當μ=0,σ²=1時為標準正態分佈。

    而高斯噪聲是要求生成的噪聲的概率密度函式符合高斯分佈。我覺得可以理解為所有的噪聲取樣服從高斯分佈的一種噪聲。有關高斯噪聲和高斯白噪聲的理解參考

    高斯噪聲的生成就是在影象所有畫素上新增一個噪聲訊號:

        n(x,y)=o(x,y)+g(x,y)

    其關鍵是如何生成這個g(x,y)。當然x和y只是表示影象畫素的座標,對原畫素值加上一個高斯取樣值就可以生成一個高斯噪聲。計算機中生成高斯取樣的方法有很多,這裡我使用的是比較常用的Box-Muller

方法。該方法原理涉及到統計學的各種問題(反正我看一遍沒太看懂),但實現過程非常簡單。

    使用方法是首先生成兩個數a,b為在[0,1]的均勻分佈隨機取樣;

    根據box-muller方法,對a,b做如下運算可以得到服從高斯分佈的兩個隨機數

    使用任何一個都可以,我覺得這是二維的高斯取樣,然後咱們在這裡只需要選擇任何一維都可以。

    最終生成的噪聲點為

    n(x,y)=o(x,y)+(μ+N*σ);

接下來是利用CImage對影象進行處理階段了

下面我放上我的程式碼和效果圖

巨集定義和main函式部分

#include <atlimage.h>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define MU 0			//均值
#define SIGMA 2			//方差
#define k 16
#define PI 3.1415926

using namespace std;
int addNoise(const CImage& input, CImage& noise);
double guass();
int makeNoise(CImage input);
int addNoise(const CImage& input, CImage& noise);
int main() {
	CString ImagePath = "E:\\1myRobotFile\\公式演算法專案\\CameraCalibration\\input.jpg";
	CImage image, noise;
	//讀入圖片
	image.Load(ImagePath);
	makeNoise(image);

	cout << "successd" << endl;
	system("pause");

}
接下來是高斯噪聲生成函式
double guass()
{
	//生成0-1的隨機數
	double x1, x2;
	//生成0-1兩個隨機數
	x1 = rand() / ((double)RAND_MAX);
	x2 = rand() / ((double)RAND_MAX);
	if (x1 < 1e-100)
		x1 = 1e-100;
	x1 = (-2) * log(x1);
	x2 = x2 * PI * 2;
	double g = MU + (sqrt(x1) * cos(x2)) * SIGMA;

	//double g = MU + (sqrt(x1) * sin(x2)) * SIGMA;

	return g;
}

最後是輸出高斯噪聲模版和高斯噪聲疊加影象

int makeNoise(CImage input)
{
	if (input == 0)
	{
		cout << "圖片輸入錯誤!" << endl;
		return 0;
	}

	//噪聲圖片的建立
	CImage gaussNoise, In;
	CString ImagePath = "E:\\1myRobotFile\\公式演算法專案\\CameraCalibration\\input.jpg";
	In.Load(ImagePath);
	gaussNoise = input;
	//gaussNoise.Create(input.GetWidth(), input.GetHeight(), 8);
	//高斯噪音生成
	int r, g, b;
	for (int i = 0; i<gaussNoise.GetWidth(); i++)
	{
		for (int j = 0; j<gaussNoise.GetHeight(); j++)
		{
			r = guass();
			g = guass();
			b = guass();
			gaussNoise.SetPixelRGB(i, j, r, g, b);

		}
	}
	CString SImagePath = "E:\\1myRobotFile\\公式演算法專案\\CameraCalibration\\noise.jpg";
	gaussNoise.Save(SImagePath);
	addNoise(In, gaussNoise);
}
//噪聲和原圖的相加
int addNoise(const CImage& input, CImage& noise)
{
	CImage addnoise;
	COLORREF pixel1;
	COLORREF pixel2;
	int r, g, b;
	if (input == 0 || noise == 0)
	{
		cout << "圖片輸入錯誤!" << endl;
		return 0;
	}
	addnoise = input;
	int w = addnoise.GetWidth();
	int h = addnoise.GetHeight();
	for (int i = 0; i < w; i++)
	{
		for (int j = 0; j<h; j++)
		{
			pixel1 = input.GetPixel(i, j);
			pixel2 = noise.GetPixel(i, j);
			/*r = GetRValue(pixel1);
			g = GetGValue(pixel1);
			b = GetBValue(pixel1);
			cout << r << "," << g << "," << b << endl;*/
			//r = GetRValue(pixel1) + GetRValue(pixel2) - 128;
			//g = GetGValue(pixel1) + GetGValue(pixel2) - 128;
			//b = GetBValue(pixel1) + GetBValue(pixel2) - 128;
			r = GetRValue(pixel1) + GetRValue(pixel2) *k;
			g = GetGValue(pixel1) + GetGValue(pixel2) *k;
			b = GetBValue(pixel1) + GetBValue(pixel2) *k;

			//cout << r << "," << g << "," << b << endl; 
			if (r>255)
			{
				r = 255;
			}
			if (g>255)
			{
				g = 255;
			}
			if (b>255)
			{
				b = 255;
			}
			if (r<0)
			{
				r = 0;

			}
			if (g<0)
			{
				g = 0;
			}
			if (b<0)
			{
				b = 0;
			}
			addnoise.SetPixelRGB(i, j, r, g, b);
		}
	}
	CString SImagePath = "E:\\1myRobotFile\\公式演算法專案\\CameraCalibration\\output.jpg";
	addnoise.Save(SImagePath);

}

效果圖如下

原圖


噪聲影象(μ=0,σ=2)

帶有高斯噪聲的影象