//给图像添加高斯噪声
#include <iostream>
#include <string>
#include <cmath>
#include <limits>
#include <cstdlib>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc.hpp>
using namespace cv;
using namespace std;
double generateGaussianNoise(double m, double sigma);
Mat addGaussianNoise(Mat& srcImage);
int denoise(Mat& srcImage)
{
Mat dstImage;
cout << "1.方框滤波" << endl;
cout << "2.均值滤波" << endl;
cout << "3.高斯滤波" << endl;
cout << "4.中值滤波" << endl;
cout << "5.双边滤波" << endl;
cout << "0.返回" << endl;
int num_2;
int ksize;
while (1)
{
cin >> num_2;
switch (num_2)
{
case 1:
{
cout << "1.方框滤波" << endl;
cout << "请输入平滑处理内核的大小(通常为正奇数1、3、5...): ";
cin >> ksize;
boxFilter(srcImage, dstImage, -1, Size(ksize, ksize));
imshow("添加高斯白噪声的图像", srcImage);
imshow("去噪后的图像", dstImage);
waitKey(0);
break;
}
case 2:
{
cout << "2.均值滤波" << endl;
cout << "请输入平滑处理内核的大小(通常为正奇数1、3、5...): ";
cin >> ksize;
blur(srcImage, dstImage, Size(ksize, ksize));
imshow("添加高斯白噪声的图像", srcImage);
imshow("去噪后的图像", dstImage);
waitKey(0);
break;
}
case 3:
{
cout << "3.高斯滤波" << endl;
cout << "请输入平滑处理内核的大小(通常为正奇数1、3、5...): ";
cin >> ksize;
GaussianBlur(srcImage, dstImage, Size(ksize, ksize), 0, 0);
imshow("添加高斯白噪声的图像", srcImage);
imshow("去噪后的图像", dstImage);
waitKey(0);
break;
}
case 4:
{
cout << "4.中值滤波" << endl;
cout << "请输入平滑处理内核的大小(通常为正奇数1、3、5...): ";
cin >> ksize;
medianBlur(srcImage, dstImage, ksize);
imshow("添加高斯白噪声的图像", srcImage);
imshow("去噪后的图像", dstImage);
waitKey(0);
break;
}
case 5:
{
cout << "5.双边滤波" << endl;
cout << "请输入滤波像素邻域直径(通常为正奇数1、3、5...): ";
cin >> ksize;
bilateralFilter(srcImage, dstImage, ksize, ksize * 2, ksize / 2);
imshow("添加高斯白噪声的图像", srcImage);
imshow("去噪后的图像", dstImage);
waitKey(0);
break;
}
case 0:
{
cout << "1.加噪" << endl;
cout << "2.去噪" << endl;
cout << "0.退出" << endl;
return 0;
break;
}
default:
cout << "输入错误,重新输入" << endl;
break;
}
}
waitKey(0);
return 0;
}
int main()
{
string filename_src = "sudoku.png";
string filename_srcnoise = "sudoku_noise.png";
Mat srcImage = imread(filename_src);
if (!srcImage.data)
{
cout << "读入图片错误!" << endl;
system("pause");
return -1;
}
cout << "1.加噪" << endl;
cout << "2.去噪" << endl;
cout << "0.退出" << endl;
int num;
while (1)
{
cin >> num;
switch (num)
{
case 1:
{
imshow("原图像", srcImage);
Mat dstImage = addGaussianNoise(srcImage);
imshow("添加高斯噪声后的图像", dstImage);
if (!imwrite(filename_srcnoise, dstImage))
{
cout << "写入图片错误!" << endl;
system("pause");
}
waitKey(0);
break;
}
case 2:
{
Mat srcnoiseImage = imread(filename_srcnoise);
if (!srcnoiseImage.data)
{
cout << "读入图片错误!" << endl;
system("pause");
return -1;
}
denoise(srcnoiseImage);
waitKey(0);
break;
}
case 0:
{
return 0;
break;
}
default:
cout << "输入错误,重新输入" << endl;
break;
}
}
waitKey(0);
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 & srcImage)
{
Mat dstImage = srcImage.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(2, 0.8) * 32;
if (val < 0)
val = 0;
if (val > 255)
val = 255;
dstImage.ptr<uchar>(i)[j] = (uchar)val;
}
}
return dstImage;
}