【OpenCV入门教程】图像加噪

来源:互联网 发布:ardupilot源码下载 编辑:程序博客网 时间:2024/05/21 10:41

图像噪声使图像在获取或是传输过程中收到随机信号干扰,妨碍人们对图像理解及分析处理的信号。很多时候将图像噪声看做多维随机过程,因而描述噪声的方法完全可以借用随机过程的描述,也就是使用随机过程的描述,也就是用它的高绿分布函数和概率密度分布函数。图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量,图像在传输过程中产生图像噪声的主要因素是所用的传输信道收到了噪声的污染。
下面简单介绍两种图像噪声,即椒盐噪声和高斯噪声。
1.椒盐噪声
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
图像模拟添加椒盐噪声是通过随机获取像素点并设置为高亮度点和低灰度点来实现的
图像添加椒盐噪声的程序如下:

//利用程序给原图像增加椒盐噪声  //图象模拟添加椒盐噪声是通过随机获取像素点斌那个设置为高亮度点来实现的  #include <cstdlib>  #include <iostream>  #include <opencv2\core\core.hpp>  #include <opencv2\highgui\highgui.hpp>  #include <opencv2\imgproc\imgproc.hpp>  using namespace cv;  using namespace std;  Mat addSaltNoise(const Mat srcImage, int n);  int main()  {      Mat srcImage = imread("2345.jpg");      if (!srcImage.data)      {          cout << "读入图像有误!" << endl;          system("pause");          return -1;      }      imshow("原图像", srcImage);      Mat dstImage = addSaltNoise(srcImage, 3000);      imshow("添加椒盐噪声的图像", dstImage);      //存储图像      imwrite("salt_pepper_Image.jpg", dstImage);      waitKey();      return 0;  }  Mat addSaltNoise(const Mat srcImage, int n)  {      Mat dstImage = srcImage.clone();      for (int k = 0; k < n; k++)      {          //随机取值行列          int i = rand() % dstImage.rows;          int j = rand() % dstImage.cols;          //图像通道判定          if (dstImage.channels() == 1)          {              dstImage.at<uchar>(i, j) = 255;       //盐噪声          }          else          {              dstImage.at<Vec3b>(i, j)[0] = 255;              dstImage.at<Vec3b>(i, j)[1] = 255;              dstImage.at<Vec3b>(i, j)[2] = 255;          }      }      for (int k = 0; k < n; k++)      {          //随机取值行列          int i = rand() % dstImage.rows;          int j = rand() % dstImage.cols;          //图像通道判定          if (dstImage.channels() == 1)          {              dstImage.at<uchar>(i, j) = 0;     //椒噪声          }          else          {              dstImage.at<Vec3b>(i, j)[0] = 0;              dstImage.at<Vec3b>(i, j)[1] = 0;              dstImage.at<Vec3b>(i, j)[2] = 0;          }      }      return dstImage;  }  

执行程序后,输出的效果如下:
这里写图片描述
这里写图片描述
2.高斯噪声
高斯噪声是指高绿密度函数服从高斯分布的一类噪声。特别的,如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度有事均匀分布的,则称这个噪声为高斯白噪声。高斯白噪声二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性。高斯噪声包括热噪声和三里噪声。高斯噪声万有由它的事变平均值和两瞬时的协方差函数来确定,若噪声是平稳的,则平均值与时间无关,而协方差函数则变成仅和所考虑的两瞬时之差有关的相关函数,在意义上它等同于功率谱密度。高斯早生可以用大量独立的脉冲产生,从而在任何有限时间间隔内,这些脉冲中的每一个买充值与所有脉冲值得总和相比都可忽略不计。
根据Box-Muller变换原理,建设随机变量U1、U2来自独立的处于(0,1)之间的均匀分布,则经过下面两个式子产生的随机变量Z0,Z1服从标准高斯分布。

Z0=Rcosϕ=2lnU1cos(2πU2)

Z1=Rsinϕ=2lnU1sin(2πU2)

上式中Z0,Z1满足正态分布,其中均值为0,方差为1,变量U1和U2可以修改为下式:

U1=eZ21+Z222

U2=12πtan1Z1Z2

给图像添加高斯噪声的程序如下:

//给图像添加高斯噪声  #include <cmath>  #include <limits>  #include <cstdlib>  #include <iostream>  #include <opencv2\core\core.hpp>  #include <opencv2\highgui\highgui.hpp>  using namespace cv;  using namespace std;  double generateGaussianNoise(double m, double sigma);  Mat addGaussianNoise(Mat &srcImag);  int main()  {      Mat srcImage = imread("2345.jpg");      if (!srcImage.data)      {          cout << "读入图片错误!" << endl;          system("pause");          return -1;      }      imshow("原图像", srcImage);      Mat dstImage = addGaussianNoise(srcImage);      imshow("添加高斯噪声后的图像", dstImage);      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(2, 0.8) * 32;              if (val < 0)                  val = 0;              if (val>255)                  val = 255;              dstImage.ptr<uchar>(i)[j] = (uchar)val;          }      }      return dstImage;  }  

程序执行后的效果图如下:
这里写图片描述这里写图片描述