本文首发于“小白学视觉”微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!


经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

图像在获取或者传输过程中会受到随机信号的干扰产生噪声,例如电阻引起的热噪声、光子噪声、暗电流噪声以及光响应非均匀性噪声等。图像噪声会妨碍人们对图像的理解以及后续的处理工作,因此去除噪声的影响在图像处理中具有十分重要的作用图像中常见的噪声主要有四种,分别是:高斯噪声、椒盐噪声、泊松噪声和乘性噪声。想要去除噪声首先需要了解噪声产生原因以及特性,因此本节中将重点介绍高斯噪声和椒盐噪声产生的原因以及如何在图像中添加这两种噪声,生成的含有噪声的图像可以应用于后续的滤波处理中。

椒盐噪声

椒盐噪声又被称作脉冲噪声,它会随机改变图像中的像素值,是由相机成像、图像传输、解码处理等过程产生的黑白相间的亮暗点噪声,其样子就像在图像上随机的撒上一些盐粒和黑椒粒,因此被称为椒盐噪声。目前为止OpenCV 4中没有提供专门用于为图像添加椒盐噪声的函数,需要使用者根据自己需求去编写生成椒盐噪声的程序,本小节将会带领读者一起实现在图像中添加椒盐噪声。

考虑到椒盐噪声会随机产生在图像中的任何一个位置,因此对于椒盐噪声的生成需要使用到OpenCV 4中能够产生随机数的函数rand(),为了能够生成不同数据类型的随机数,该函数拥有多种演变形式,在代码清单5-3中给出了这几种形式的函数原型。

代码清单5-3 随机数函数原型
1.  int cvflann::rand()
2.
3.  double cvflann::rand_double(double  high = 1.0,
4.                                    double  low = 0
5.                                    )
6.
7.  int cvflann::rand_int(int  high = RAND_MAX,
8.                            int  low = 0
9.                            )
  • high:输出随机数的最大值
  • low:输出随机数的最小值

这三个函数都可以用来生成随机数,区别在于第一个函数rand()不需要输入任何的参数,返回的随机数为int类型;第二个函数rand_double()需要输入随机数的上下边界,默认状态下生成的随机数在0到1之间,返回的随机数为double类型;第三个函数rand_int()也需要输入随机数的上下边界,不同的是该函数默认状态下的最大值为RAND_MAX,这是一个由系统定义的宏变量,在笔者的计算机中这个变量表示的是整数32767,该函数会返回的随机数为int类型。这三个函数的功能和使用方式上都比较简单,这里有个小技巧,rand()函数虽然没有给出随机数的取值范围,但是可以采用求取余数的方式来实现对随机数范围的设置,例如使用rand()函数随机生成一个0到100之间的整数,可以使用“int a = rand()%100”语句来实现,因为无论任何数除以100后的余数一定在0到100之间。

注意

该函数与之前所有的函数不相同之处在于该函数并不在cv的命名空间中,而是在cvflann类中,因此在使用的时候一定要在函数前添加前缀,如cvflann::rand()。有些读者在使用rand()函数时不添加cvflann命名空间的前缀也可以使用,是因为该函数不仅在OpenCV 4中有,在stdlib.h头文件中同样有这个函数,只有在函数前面添加了命名空间前缀时使用的才是OpenCV 4中的随机数生成函数。

了解随机函数之后,在图像中添加椒盐噪声大致分为以下4个步骤:

  • Step1:确定添加椒盐噪声的位置。根据椒盐噪声会随机出现在图像中任何一个位置的特性,我们可以通过随机数函数生成两个随机数,分别用于确定椒盐噪声产生的行和列。
  • Step2:确定噪声的种类。不仅椒盐噪声的位置是随机的,噪声点是黑色的还是白色的也是随机的,因此可以再次生成的随机数,通过判断随机数的奇偶性确定该像素是黑色噪声点还是白色噪声点。
  • Step3:修改图像像素灰度值。判断图像通道数,通道数不同的图像中像素表示白色的方式也不相同。也可以根据需求只改变多通道图像中某一个通道的数值。
  • Step4:得到含有椒盐噪声的图像。

依照上述思想,在代码清单5-4中给出在图像中添加椒盐噪声的示例程序,程序中判断了输入图像是灰度图还是彩色图,但是没有对彩色图像的单一颜色通道产生椒盐噪声。如果需要对某一通道产生椒盐噪声,只需要单独处理彩色图像每个通道即可。程序在图像中添加椒盐噪声的结果如图5-6、图5-7所示,由于椒盐噪声是随机添加的,因此每次运行结果会有所差异。

代码清单5-4 mySaltAndPepper.cpp图像中添加椒盐噪声
1.  #include <opencv2\opencv.hpp>
2.  #include <iostream>
3.
4.  using namespace cv;
5.  using namespace std;
6.
7.  //盐噪声函数
8.  void saltAndPepper(cv::Mat image, int n)
9.  {10.     for (int k = 0; k<n / 2; k++)
11.     {12.         //随机确定图像中位置
13.         int i, j;
14.         i = std::rand() % image.cols;  //取余数运算,保证在图像的列数内
15.         j = std::rand() % image.rows;  //取余数运算,保证在图像的行数内
16.         int write_black = std::rand() % 2;  //判定为白色噪声还是黑色噪声的变量
17.         if (write_black == 0)  //添加白色噪声
18.         {19.             if (image.type() == CV_8UC1)  //处理灰度图像
20.             {21.                 image.at<uchar>(j, i) = 255;  //白色噪声
22.             }
23.             else if (image.type() == CV_8UC3)  //处理彩色图像
24.             {25.                 image.at< Vec3b>(j, i)[0] = 255; //Vec3b为opencv定义的3个值的向量类型
26.                 image.at<Vec3b>(j, i)[1] = 255; //[]指定通道,B:0,G:1,R:2
27.                 image.at<Vec3b>(j, i)[2] = 255;
28.             }
29.         }
30.         else  //添加黑色噪声
31.         {32.             if (image.type() == CV_8UC1)
33.             {34.                 image.at<uchar>(j, i) = 0;
35.             }
36.             else if (image.type() == CV_8UC3)
37.             {38.                 image.at< Vec3b>(j, i)[0] = 0; //Vec3b为opencv定义的3个值的向量类型
39.                 image.at<Vec3b>(j, i)[1] = 0; //[]指定通道,B:0,G:1,R:2
40.                 image.at<Vec3b>(j, i)[2] = 0;
41.             }
42.         }
43.
44.     }
45. }
46.
47. int main()
48. {49.     Mat lena = imread("lena.png");
50.     Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);
51.     if (lena.empty()||equalLena.empty())
52.     {53.         cout << "请确认图像文件名称是否正确" << endl;
54.         return -1;
55.     }
56.     imshow("lena原图", lena);
57.     imshow("equalLena原图", equalLena);
58.     saltAndPepper(lena, 10000);  //彩色图像添加椒盐噪声
59.     saltAndPepper(equalLena, 10000);  //灰度图像添加椒盐噪声
60.     imshow("lena添加噪声", lena);
61.     imshow("equalLena添加噪声", equalLena);
62.     waitKey(0);
63.     return 0;
64. }

图5-6 mySaltAndPepper.cpp程序中灰度图添加椒盐噪声结果 图5-7 mySaltAndPepper.cpp程序中彩色图添加椒盐噪声结果

高斯噪声

高斯噪声是指噪声分布的概率密度函数服从高斯分布(正态分布)的一类噪声,其产生的主要原因是由于相机在拍摄时视场较暗且亮度不均匀造成的,同时相机长时间工作使得温度过高也会引起高斯噪声,另外电路元器件自身噪声和互相影响也是造成高斯噪声的重要原因之一。高斯噪声的概率密度函数如式(5.2)所示,其中zzz表示图像像素的灰度值,μ\muμ表示像素值的平均值或者期望值,σ\sigmaσ表示像素值的标准差,标准差的平方σ2\sigma ^2σ2称为方差。区别于椒盐噪声随机出现在图像中的任意位置,高斯噪声出现在图像中的所有位置。
p(z)=12πσe−(z−μ)22σ2(5.2)p({\rm{z}}) = \frac{1}{{\sqrt {2\pi } \sigma }}{e^{\frac{{ - {{(z - \mu )}^2}}}{{2{\sigma ^2}}}}} \tag{5.2}p(z)=2π​σ1​e2σ2−(z−μ)2​(5.2)
OpenCV 4中同样没有专门为图像添加高斯噪声的函数,对照在图像中添加椒盐噪声的过程,我们可以根据需求利用能够产生随机数的函数来完成在图像中添加高斯噪声的任务。在OpenCV 4中提供了fill()函数可以产生均匀分布或者高斯分布(正态分布)的随机数,我们可以利用该函数产生符合高斯分布的随机数,之后在图像中加入这些随机数即可,我们首先了解该函数的使用方式,该函数的函数原型在代码清单5-5中给出。

代码清单5-5 fill()函数原型
1.  void cv::RNG::fill(InputOutputArray  mat,
2.                         int  distType,
3.                         InputArray  a,
4.                         InputArray  b,
5.                         bool  saturateRange = false
6.                         )
  • mat:用于存放随机数的矩阵,目前只支持低于5通道的矩阵。
  • distType:随机数分布形式选择标志,目前生成的随机数支持均匀分布(RNG::UNIFORM,0)和高斯分布(RNG::NORMAL,1)。
  • a:确定分布规律的参数。当选择均匀分布时,该参数表示均匀分布的最小下限;当选择高斯分布时,该参数表示高斯分布的均值。
  • b:确定分布规律的参数。当选择均匀分布时,该参数表示均匀分布的最大上限;当选择高斯分布时,该参数表示高斯分布的标准差。
  • saturateRange:预饱和标志,仅用于均匀分布。

该函数用于生成指定分布形式的随机数填充矩阵,可以生成符合均匀分布的随机数和符合高斯分布随机数。函数的第一个参数输入用于存储生成随机数的矩阵,但是矩阵的通道数必须小于等于4。第二个参数是选择随机数分布形式的标志,该函数目前只支持两种分布形式,分别是均匀分布(RNG::UNIFORM,简记0)和高斯分布(RNG::NORMAL,简记1)。函数的第三个和第四个参数为确定随机数分布规律的参数,第三个参数在均匀分布时表示均匀分布的最小下限,在高斯分布时表示高斯分布的均值;第四个参数在均匀分布时表示均匀分布的最大上限,在高斯分布时表示高斯分布的标准差。最后一个参数是预饱和标志,仅用于均匀分布,我们使用其默认式即可。需要注意的是该函数属于OpenCV 4的RNG类,是一个非静态成员函数,因此在使用的时候不能像使用正常函数一样的直接使用,而需要首先创建一个RNG类的变量,之后通过访问这个变量中函数进行调用这个函数,具体使用方式在代码清单5-6中给出。

代码清单5-6 RNG::fill()函数的使用
1.  cv::RNG rng;
2.  rng.fill(mat, RNG::NORMAL, 10, 20);

在图像中添加高斯噪声大致分为以下4个步骤:

  • Step1:首先需要创建一个与图像尺寸、数据类型以及通道数相同的Mat类变量.
  • Step2:通过调用fill()函数在Mat类变量中产生符合高斯分布的随机数。
  • Step3:将原图像和含有高斯分布的随机数矩阵相加。
  • Step4:得到添加高斯噪声之后的图像。

依照上述思想,在代码清单5-7中给出了在图像中添加高斯噪声的示例程序,程序实现了对灰度图像和彩色图像添加高斯噪声,在图像中添加高斯噪声的结果如图5-8、图5-9所示,由于高斯噪声是随机生成的,因此每次运行结果会有差异。

代码清单5-7 myGaussNoise.cpp图像中添加高斯噪声
1.  #include <opencv2\opencv.hpp>
2.  #include <iostream>
3.
4.  using namespace cv;
5.  using namespace std;
6.
7.  int main()
8.  {9.      Mat lena = imread("lena.png");
10.     Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);
11.     if (lena.empty()||equalLena.empty())
12.     {13.         cout << "请确认图像文件名称是否正确" << endl;
14.         return -1;
15.     }
16.     //生成与原图像同尺寸、数据类型和通道数的矩阵
17.     Mat lena_noise = Mat::zeros(lena.rows, lena.cols, lena.type());
18.     Mat equalLena_noise = Mat::zeros(lena.rows, lena.cols, equalLena.type());
19.     imshow("lena原图", lena);
20.     imshow("equalLena原图", equalLena);
21.     RNG rng;  //创建一个RNG类
22.     rng.fill(lena_noise, RNG::NORMAL, 10, 20);  //生成三通道的高斯分布随机数
23.     rng.fill(equalLena_noise, RNG::NORMAL, 15, 30);  //生成三通道的高斯分布随机数
24.     imshow("三通道高斯噪声", lena_noise);
25.     imshow("单通道高斯噪声", equalLena_noise);
26.     lena = lena + lena_noise;  //在彩色图像中添加高斯噪声
27.     equalLena = equalLena + equalLena_noise;  //在灰度图像中添加高斯噪声
28.     //显示添加高斯噪声后的图像
29.     imshow("lena添加噪声", lena);
30.     imshow("equalLena添加噪声", equalLena);
31.     waitKey(0);
32.     return 0;
33. }

图5-8 myGaussNoise.cpp程序中灰度图添加高斯噪声结果 图5-9 myGaussNoise.cpp程序中彩色图添加高斯噪声结果

OpenCV 4开发详解
往期推荐
【OpenCV 4开发详解】Mat类介绍
【OpenCV 4开发详解】Mat类构造与赋值
【OpenCV 4开发详解】4种读取Mat类元素的的方法
【OpenCV 4开发详解】图像的读取与显示
【OpenCV 4开发详解】视频加载与摄像头调用
【OpenCV 4开发详解】图像与视频的保存
【OpenCV 4开发详解】保存和读取XML和YMAL文件
【OpenCV 4开发详解】颜色模型与转换
【OpenCV 4开发详解】多通道分离与合并
【OpenCV 4开发详解】图像像素统计
【OpenCV 4开发详解】两图像间的像素操作
【OpenCV 4开发详解】图像二值化
【OpenCV 4开发详解】图像LUT查找表
【OpenCV 4开发详解】图像连接
【OpenCV 4开发详解】图像仿射变换
【OpenCV 4开发详解】图像透视变换
【OpenCV 4开发详解】图像极坐标变换
【OpenCV 4开发详解】图像上绘制几何图形
【OpenCV 4开发详解】图像金字塔
【OpenCV 4开发详解】窗口交互操作
【OpenCV 4开发详解】图像直方图绘制
【OpenCV 4开发详解】直方图操作
【OpenCV 4开发详解】直方图应用
【OpenCV 4开发详解】图像模板匹配
【OpenCV 4开发详解】图像卷积
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。

【OpenCV 4开发详解】图像噪声的种类与生成相关推荐

  1. 【OpenCV 4开发详解】分割图像——分水岭法

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  2. 【OpenCV 4开发详解】图像修复

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  3. 【OpenCV 4开发详解】分割图像——Mean-Shift分割算法

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  4. 【OpenCV 4开发详解】分割图像——Grabcut图像分割

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  5. 【OpenCV 4开发详解】图像膨胀

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  6. 【OpenCV 4开发详解】图像腐蚀

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  7. 【OpenCV 4开发详解】图像距离变换

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  8. 【OpenCV 4开发详解】图像连通域分析

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  9. 【OpenCV 4开发详解】图像二值化

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

最新文章

  1. c语言程序中变量先引用声明,C语言如何跨文件调用函数定义中声明的变量
  2. JavaScript函数大全
  3. 神策数据加入中国大数据产业生态联盟,神策营销云及融媒解决方案获联盟认证...
  4. 如何消耗更少资源?Unity优化技巧(上)
  5. php打印 二维数组,PHP中遍历二维数组_以不同形式的输出操作实例
  6. 人工智能急需网络安全“背书”
  7. Vagrant+PHPStorm+Google+XDebug断点调试
  8. static关键字_一题搞定static关键字
  9. 【QA】哈工大张伟男:任务型对话系统
  10. FFmpeg滤镜代码级分析
  11. unique函数_包含虚函数的类应该有虚析构函数或保护析构函数?
  12. 【SystemVerilog基础】OOP思想之重载
  13. 什么是宽带薪酬?宽带薪酬系统如何实施?
  14. 【技术贴】网页部分图片显示x红叉,网页图片不显示,网页图片显示异常,网页图片打不开。...
  15. Linux如何修改主机名hostname
  16. 从键盘读入10个的整数,判断正数和负数的个数
  17. 产品经理PM相关书籍---推荐阅读
  18. :hover的知识点
  19. 经典题目题解:连续子串和
  20. 【看表情包学Linux】进程状态解析 | 运行态 | 终止态 | 进程挂起与阻塞 | 运行态R | 阻塞态S/D | 死亡态X | 僵尸态Z | 暂停态T/t | 僵尸进程 | 孤儿进程

热门文章

  1. 微软沈向洋:写给AI新潮流——人工智能创作的五点建议
  2. Java 11 正式发布!
  3. 谷歌开发者大会杀出技术黑马,知乎AI终于不再隐藏实力了
  4. 360推两款无刘海新机,主打安全和AI,起售价1199
  5. 2018 区块链技术及应用峰会(BTA)·中国全日程新鲜出炉,更多精彩议题看不停
  6. 月入5W,月花销不足2K的程序员,可免费获得AI女友一名
  7. 牛逼哄哄的布隆过滤器,到底有什么用?
  8. NullPointerException 的处理新方式,Java14 真的太香了!
  9. Google 出品的 Java 编码规范,值得借鉴!
  10. 数据集获取加速神器来了!