通过Box-Muller变换可以产生Gaussian噪音
Box-Muller变换:假设随机变量x1, x2来自独立的处于[0,1]之间的均匀分布,则经过下面两个式子产生的随机变量z1, z2服从标准高斯分布:
实现代码(引自维基百科)
#define TWO_PI 6.2831853071795864769252866 double generateGaussianNoise() { static bool hasSpare = false; static double rand1, rand2; if(hasSpare) { hasSpare = false; return sqrt(rand1) * sin(rand2); } hasSpare = true; rand1 = rand() / ((double) RAND_MAX); if(rand1 < 1e-100) rand1 = 1e-100; rand1 = -2 * log(rand1); rand2 = (rand() / ((double) RAND_MAX)) * TWO_PI; return sqrt(rand1) * cos(rand2); }
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace cv; using namespace std; #define TWO_PI 6.2831853071795864769252866 double generateGaussianNoise() { static bool hasSpare = false; static double rand1, rand2; if(hasSpare) { hasSpare = false; return sqrt(rand1) * sin(rand2); } hasSpare = true; rand1 = rand() / ((double) RAND_MAX); if(rand1 < 1e-100) rand1 = 1e-100; rand1 = -2 * log(rand1); rand2 = (rand() / ((double) RAND_MAX)) * TWO_PI; return sqrt(rand1) * cos(rand2); } void AddGaussianNoise(Mat& I) { // accept only char type matrices CV_Assert(I.depth() != sizeof(uchar)); int channels = I.channels(); int nRows = I.rows; int nCols = I.cols * channels; if(I.isContinuous()){ nCols *= nRows; nRows = 1; } int i,j; uchar* p; for(i = 0; i < nRows; ++i){ p = I.ptr<uchar>(i); for(j = 0; j < nCols; ++j){ double val = p[j] + generateGaussianNoise() * 128; if(val < 0) val = 0; if(val > 255) val = 255; p[j] = (uchar)val; } } } int main( int argc, char** argv ) { if( argc != 2) { cout <<" Usage: display_image ImageToLoadAndDisplay" << endl; return -1; } Mat image; image = imread(argv[1], 1); // Read the file if(! image.data ) // Check for invalid input { cout << "Could not open or find the image" << std::endl ; return -1; } namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display. imshow( "Display window", image ); // Show our image inside it. // Add Gaussian noise here AddGaussianNoise(image); namedWindow( "Noisy image", WINDOW_AUTOSIZE ); // Create a window for display. imshow( "Noisy image", image ); // Show our image inside it. waitKey(0); // Wait for a keystroke in the window return 0; }
参考:
1. http://mathworld.wolfram.com/Box-MullerTransformation.html
2. http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
3. Sanka et al. Image processing, analysis and machine vision. 3rd edition.