噪声的种类和生成
图像在获取或者传输过程中会受到随机信号的干扰而产生噪音
例如电阻引起的热噪声、光子噪声、暗电流噪声等由于图像噪声会妨碍人们对图像的理解和以及后续的处理工作
因此去除噪声的影响在图像处理中具有十分重要的作用
图像常见噪声有4种:高斯噪声、椒盐噪声、泊松噪声和乘性噪声
椒盐噪声rand()
椒盐噪声又称脉冲噪声,会随机改变图像中的像素值,是由相机成像、图像传像、解码处理等过程产生的黑白相间的亮暗点噪声
其样子就像图像上随机地撒上一些盐粒和黑椒粒,因此称为椒盐噪声
OpenCV4未提供专门用于为图像添加椒盐噪声的函数
考虑到椒盐噪声会在图像中任何一个位置随机产生,因此需要使用OpenCV4提供的能够产生随机数的函数rand()
为了能够生成不同数据类型的随机数,该函数由多种演变形式(如:rand_double、rand_int())
rand()函数原型:
int cvflann::rand()
double cvflann::rand_double(double high = 1.0,
double low = 0
)
int cvflann::rand_int(int high = RAND_MAX,
int low = 0
)
- high:输出随机数的最大值
- low:输出随机数的最小值
这三个函数都可以用来生成随机数,区别在于,第一个函数rand()函数不需要输入任何参数,返回的随机数为int类型
第二个函数rand_double()需要输入随机数的上下边界,默认情况下生成的随机数在0~1范围,返回的随机数为double类型
第三个函数rand_int()也需要输入上下边界,不同的是,默认情况下最大值是RAND_MAX,这是系统定义的宏变量
小技巧:可以通过求余数的方法实现对随机数的设置,例如: int a = rand % 100 可以保证余数在0~100范围
在图像中添加椒盐噪声大致分为4个步骤
第一步:确定添加椒盐噪声的位置,可以通过随机函数生成两个随机数来取确定椒盐噪声产生的行和列
第二步:确定噪声的种类。可以通过随机数来确定噪声点是黑色还是白色
第三步:修改图像像素灰度值。判断图像通道数,通道数不同的图像中像素表示白色的方式不同
第四步:得到含有椒盐噪声的图像
示例:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
//椒盐噪声函数
void saltAndPepper(Mat image,int n)
{
for (int k = 0; k < n/2; ++k)
{
//随机确定图像中位置
int i ,j;
i = rand() % image.cols; //取余数运算,保证在图像的列数内
j = rand() % image.rows; //取余数运算,保证在图像的行数内
int write_black = rand() % 2; //判定是白色噪声还是黑色噪声
if ( write_black == 0 ) //添加白色噪声
{
if ( image.type() == CV_8UC1 ) //出来灰度图像
{
image.at<uchar>(j,i) = 255; //白色噪声
}
else if ( image.type() == CV_8UC3 ) //处理彩色图像
{
image.at<Vec3b>(j,i)[0] = 255; //Vec3b为OpenCV定义的3歌值的向量类型
image.at<Vec3b>(j,i)[1] = 255; //[]指定通道,B:0,G:1,R:2
image.at<Vec3b>(j,i)[2] = 255;
}
}
else //添加黑色噪声
{
if ( image.type() == CV_8UC1 )
{
image.at<uchar>(j,i) = 255;
}
else if ( image.type() == CV_8UC3 ) //处理彩色图像
{
image.at<Vec3b>(j,i)[0] = 0; //Vec3b为OpenCV定义的3歌值的向量类型
image.at<Vec3b>(j,i)[1] = 0; //[]指定通道,B:0,G:1,R:2
image.at<Vec3b>(j,i)[2] = 0;
}
}
}
}
int main()
{
Mat lena = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg");
Mat equalLena = imread("E:\\CLion\\opencv_xin\\SG\\SG_1.jpg",IMREAD_ANYDEPTH); //IMREAD_GRAYSCALE效果相同
if (lena.empty() || equalLena.empty())
{
cout << "Error" << endl;
return -1;
}
imshow("lena原图",lena);
imshow("equalLena原图",equalLena);
saltAndPepper(lena,10000); //彩色图像添加椒盐噪声
saltAndPepper(equalLena,10000); //灰度图像添加椒盐噪声
imshow("lena添加噪声",lena);
imshow("equalLena添加噪声",equalLena);
waitKey(0);
return 0;
}

高斯噪声RNG::fill()
高斯噪声是指噪声分布的概率密度函数服从高斯分布(正态分布)的一类噪声
产生原因主要是相机在拍摄时视场较暗且亮度不均匀,相机长时间工作使得温度过高同样会引起高斯噪声
另外,电路元器件自身噪声和相互影响也是造成高斯噪声的重要原因之一
OpenCV4未提供专门用于为图像添加高斯噪声的函数
OpenCV4提供了fill()函数,可以产生均匀分布或者高斯分布(正太分布)的随机数
可以利用该函数产生符合高斯分布的随机数,之后在图像中加入这些随机数
fill()函数原型:
void cv::RNG::fill(InputOutArray mat,
int distType,
InputArray a,
InputArray b,
bool saturateRange = false
)
- mat:用于存放随机数的矩阵,目前只支持5通道的矩阵
- distType:随机数分布形式选择标志,目前生成的随机数支持均匀分布(RNG::UNIFORM,0)
和高斯分布(RNG::NORMAL,1)
- a:确定分布规律的参数,但选择均匀分布时,该参数表示均匀分布的最小下限;当选择高斯分布时,表示高斯分布均值
- b:确定分布规律的参数,但选择均匀分布时,该参数表示均匀分布的最大上限;当选择高斯分布时,表示高斯分布的标准差
- saturateRange:预饱和标志,仅用于均匀分布
该函数用于生成指定分布形式的随机数填充矩阵,可以生成符合均匀分布的随机数和符合高斯分布的随机数
第一个参数输入用于储存生成随机数的矩阵,矩阵通道数必须小于5
第二个参数是选择随机数分布形式的标志,目前只支持两种分布形式
均匀分布(RNG::UNIFORM,简记:0)和高斯分布(RNG::NORMAL,简记:1)
第三、四个参数为确定随机数分布规律的参数
最后一个参数是预饱和标志,仅用于均匀分布,一般使用其默认方式即可
注:该函数属于OpenCV4的RNG类,是一个非静态成员函数,因此,在使用的时候,不能像使用正常函数一样直接使用
需要首先创建一个RNG类的变量,之后通过访问这个变量中的函数的方式调用这个函数
RNG::fill()函数的使用:
cv::RNG rng;
rng.fill(mat, RNG::NORMAL, 10, 20)
示例:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat lena = imread("E:\\CLion\\opencv_xin\\SG\\SG_0.jpg");
Mat equalLena = imread("E:\\CLion\\opencv_xin\\SG\\SG_1.jpg",IMREAD_ANYDEPTH); //IMREAD_GRAYSCALE效果相同
if (lena.empty() || equalLena.empty())
{
cout << "Error" << endl;
return -1;
}
//生成与原始图像尺寸、数据类型和哦通道数相同的矩阵
Mat lena_noise = Mat::zeros(lena.rows,lena.cols,lena.type());
Mat equalLena_noise = Mat::zeros(lena.rows,lena.cols,equalLena.type());
imshow("lena原图",lena);
imshow("equalLena原图",equalLena);
RNG rng; //创建一个RNG类
rng.fill(lena_noise,RNG::NORMAL,10,20); //生成三通道的高斯分布随机数
rng.fill(equalLena_noise,RNG::NORMAL,15,30); //生成单通道的高斯分布随机数
imshow("三通道高斯噪声",lena_noise);
imshow("单通道高斯噪声",equalLena_noise);
lena = lena + lena_noise; //在彩色图像中添加高斯噪声
equalLena = equalLena + equalLena_noise; //在灰度图像中添加高斯噪声
//显示添加高斯噪声后的图像
imshow("lena添加噪声",lena);
imshow("equalLena添加噪声",equalLena);
waitKey(0);
return 0;
}
.png)