本次要整理的内容是基于OpenCV4学习笔记(12)中的三种模糊方式,首先为一张图像添加噪声,分别添加椒盐噪声和高斯噪声,然后通过均值模糊、高斯模糊和中值滤波来分别对比这三种滤波方式对不同种类噪声的抑制效果如何。最后再记录一种新的滤波方式:非局部均值滤波。
RNG rng(0); //创建一个随机数对象;可输入随机数种子
int height = image.rows;
int width = image.cols;
Mat salf_pepper_noise_image = image.clone();
for (int i = 0; i < 10000; i++)
{
//随机生成噪声点的坐标
int x = rng.uniform(0, width);
int y = rng.uniform(0, height);
//让黑白两种噪点数量均衡
if (0 == i % 2)
{
salf_pepper_noise_image.at<Vec3b>(y, x) = Vec3b(255, 255, 255); //(y,x)对应(row, col)
}
else
{
salf_pepper_noise_image.at<Vec3b>(y, x) = Vec3b(0, 0, 0);
}
}
imshow("salf_pepper_noise_image", salf_pepper_noise_image);
代码实现还是比较简单的,利用一个随机数对象来分别随机生成噪声点的x、y坐标,然后就对图像中的该点处的像素值置为0或255,分别代表椒、盐噪声。为了使椒盐两种噪声数量均衡,所以对添加数量做了个取余操作来判断是不是偶数个噪声点,如果是就为盐噪声,不是就为椒噪声。
同时这里有个小细节:0 == i % 2
,就是在使用到==
这个运算符的时候把常数项放到左边,避免因为少打了个 = 号而变成了赋值式,那就会引发错误而且还难以发现。
下面再看高斯噪声的添加。高斯噪声的出现一般是不可避免的,一般会在数码相机的图像采集(acquisition)阶段产生高斯噪声,物理、电、光等各种信号都可能导致产生高斯分布噪声。OpenCV中有一个API可以实现对图像添加高斯噪声,代码如下:
Mat gaussian_noise_image = image.clone();
//定义一张空白图像,用来生成高斯噪声
Mat noise = Mat::zeros(image.size(), image.type());
randn(noise, (10, 100, 10), (30, 30, 30));
//将噪声图和原图相加
add(image, noise, gaussian_noise_image, Mat(), -1);
imshow("gaussian_noise_image", gaussian_noise_image);
imshow("image", image);
这行代码randn(noise, (10, 100, 10), (30, 30, 30))
就实现高斯噪声的添加,第二和第三个参数分别为三通道的均值(mean)和方差(stddev),如果mean和stddev各只写一个则默认三通道具有相同的均值和方差。
最后生成的椒盐噪声图和高斯噪声图,相对于原图效果如下:
Mat blur_salf_pepper_image;
Mat blur_gaussian_image;
Mat median_salf_pepper_image;
Mat median_gaussian_image;
Mat gaussian_gaussian_image;
Mat gaussian_salf_pepper_image;
Mat Denoise_salf_pepper_image;
Mat Denoise_gaussian_image;
//均值滤波去噪
blur(salf_pepper_noise_image, blur_salf_pepper_image, Size(3, 3));
blur(gaussian_noise_image, blur_gaussian_image, Size(3, 3));
imshow("blur_salf_pepper_image", blur_salf_pepper_image);
imshow("blur_gaussian_image", blur_gaussian_image);
//高斯滤波去噪,针对高斯噪声
GaussianBlur(salf_pepper_noise_image, gaussian_salf_pepper_image, Size(), 1);
GaussianBlur(gaussian_noise_image, gaussian_gaussian_image, Size(), 1);
imshow("gaussian_salf_pepper_image", gaussian_salf_pepper_image);
imshow("gaussian_gaussian_image", gaussian_gaussian_image);
//中值滤波去噪,针对椒盐噪声
medianBlur(salf_pepper_noise_image, median_salf_pepper_image, 3);
medianBlur(gaussian_noise_image, median_gaussian_image, 3);
imshow("median_salf_pepper_image", median_salf_pepper_image);
imshow("median_gaussian_image", median_gaussian_image);
我们对上面得到的椒盐噪声图和高斯噪声图分别进行处理后,三种滤波操作分别得到下面三幅对比图像(左边为处理后的椒盐噪声图,右边为处理后的高斯噪声图):
进行逐一分析,可以看出:
(1)均值滤波对高斯噪声有一定的抑制效果,但效果不是很好;而对于椒盐噪声,就只是将噪声的强度略微削弱,仍然存在很明显的椒盐噪声。所以均值滤波对噪声的抑制效果并不是特别的好。
(2)高斯滤波对于椒盐噪声的抑制效果,感觉和均值滤波是半斤八两谁也笑话不了谁,都仍然能看到明显的椒盐噪声;但是对于高斯噪声的抑制效果,高斯滤波是比较好一些的,当放大图片观察的时候,会发现相比原高斯噪声图像,处理后的图像少去了非常多密密麻麻的小点,不仔细看是看不出来的。
(3)中值滤波就很明显了,十足的偏科。对于椒盐噪声的效果非常的好,经过处理后几乎看不出原有的椒盐噪声的痕迹了;但是对于高斯噪声,经过处理后也几乎看不出原有的高斯噪声被抑制的痕迹。。。可见当图像存在椒盐噪声的时候,中值滤波肯定是首选操作。
fastNlMeansDenoisingColored(salf_pepper_noise_image, Denoise_salf_pepper_image, 10, 10, 7, 21);
fastNlMeansDenoisingColored(gaussian_noise_image, Denoise_gaussian_image, 10, 10, 7, 21);
imshow("Denoise_salf_pepper_image", Denoise_salf_pepper_image);
imshow("Denoise_gaussian_image", Denoise_gaussian_image);
代码fastNlMeansDenoisingColored(salf_pepper_noise_image, Denoise_salf_pepper_image, 10, 10, 7, 21)
中,第一个参数是要进行处理的输入图像;第二个参数是输出图像;第四个参数h是权重衰减系数, 决定过滤器强度。h 值高可以很好的去除噪声,但也会把图像的细节抹去;第五个参数hcolor:与h相同,用于彩色图像;第六和第七个参数为模板窗口和搜索窗口的尺寸:模板窗口:搜索窗口一般取 1:3(推荐值为7:21)。
这个API是针对彩色多通道图像来处理的,还有一个APIfastNlMeansDenoising()
是专门用于处理灰度图像的。
处理效果如下:
可以看出,非局部均值滤波对于椒盐噪声几乎是没有效果的,但是对于高斯噪声的抑制效果非常好,处理过后几乎看不出高斯噪声的踪迹。但是如果滤波器强度设置过大,就会使得图像细节被抹除掉,例如猫猫的毛发就没有那么的清晰可见,而是显得涂抹感比较重。所以参数的设置仍是需要根据具体情况来具体调试。
本次整理记录到此结束,感谢阅读~~~
PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!