高斯噪声的概率分布
代码中添加噪声用到了Box-Muller变换原理 具体原理就不列出来了
更详细求解公式的可以转https://blog.csdn.net/weixin_41793877/article/details/84700875
//给图像加入高斯噪声
#include <cmath>
#include <limits>
#include <cstdlib>
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
double generateGaussianNoise(double m, double sigma);
Mat addGaussianNoise(Mat &srcImag);
Mat CalcHist(Mat src);
string st = "E:\\冈萨雷斯OpenCV重写\\DIP3E_CH05_Original_Images\\DIP3E_CH05_Original_Images\\";
//添加高斯噪声
int main()
{
Mat srcImage = imread(st + "Fig0503 (original_pattern).tif",0);
Mat histsrc = CalcHist(srcImage);
imshow("Hist1", histsrc);
imshow("原图像", srcImage);
Mat dstImage = addGaussianNoise(srcImage);
Mat histdst = CalcHist(dstImage);
imshow("HistD", histdst);
imshow("加入高斯噪声后的图像", dstImage);
Mat testimg(512, 512, CV_8UC1, Scalar(0));
testimg = addGaussianNoise(testimg);
Mat histtest = CalcHist(testimg);
imshow("histtest", histtest);
imshow("高斯噪声图像", testimg);
waitKey();
return 0;
}
//生成高斯噪声
double generateGaussianNoise(double mu, double sigma)
{
//定义小值
const double epsilon = numeric_limits<double>::min();
static double z0, z1;
static bool flag = false;
flag = !flag;
//flag为假 构造高斯随机变量X
if (!flag)
return z1 * sigma + mu;
double u1, u2;
//构造随机变量(均匀分布)
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= epsilon);
//flag为真 构造高斯随机变量
z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);
z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);
return z0*sigma + mu;
}
//为图像加入高斯噪声
Mat addGaussianNoise(Mat &srcImag)
{
Mat dstImage = srcImag.clone();
int channels = dstImage.channels();
int rowsNumber = dstImage.rows;
int colsNumber = dstImage.cols*channels;
//推断图像的连续性
//意思 查看储存类型 是矩阵还是行向量 内存足够大的情况下 会以行向量的方式保存
if (dstImage.isContinuous())
{
colsNumber *= rowsNumber;
rowsNumber = 1;
}
for (int i = 0; i < rowsNumber; i++)
{
for (int j = 0; j < colsNumber; j++)
{
//加入高斯噪声
int val = dstImage.ptr<uchar>(i)[j] +
generateGaussianNoise(10,10);
if (val < 0)
val = 0;
if (val>255)
val = 255;
dstImage.ptr<uchar>(i)[j] = (uchar)val;
}
}
return dstImage;
}
//计算直方图
Mat CalcHist(Mat src)
{
const int channels[] = { 0 };
const int histsize[] = { 255 };
float range[] = { 0, 256 };
const float* ranges[] = { range };
Mat hist;
calcHist(&src,1 ,channels, Mat(), hist,1, histsize, ranges);
normalize(hist, hist, 0, 255, NORM_MINMAX);
Mat maphist1 = Mat::zeros(Size(256, 256), CV_8UC1);
for (int i = 1; i < 255; i++)
{
line(maphist1, Point(i - 1, 255 - hist.at<float>(i - 1)), Point(i, 255 - hist.at<float>(i)), Scalar(255));
}
return maphist1;
}