课上作业要求利用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对图像进行处理阶段了
关于如何使用Cimage类的介绍,这里我参考了self_mind 的关于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)
带有高斯噪声的图像