本博客内容来源于网络以及其他书籍,结合自己学习的心得进行重编辑,因为看了很多文章不便一一标注引用,如图片文字等侵权,请告知删除。
图像平滑去噪简介
在这一节,我们首先来解释这个我们这篇文章要描述什么,只需要回答两个问题,第一,什么是图像平滑,什么又是去噪,他们有什么关系;第二为什么要进行图像平滑。
在回答上述两个问题,我们先来了解什么是图像的低频信息,什么是高频信息?
-
高频信息与低频信息
比较直观的认知,如上图正弦波的变化非常的缓慢,频率较低,在正弦波上有一个毛刺,这个毛刺在短时间内就完成了一个变化周期,频率较高。所以我们就把这里的正弦波称为低频信号,而毛刺就称为高频信号。
在图片上低频就是颜色缓慢变化,也就是灰度缓慢地变化,就代表着那是连续渐变的一块区域。相反高频即灰度变化快,相邻区域的灰度差别大,例如边缘,噪点都是灰度变化快的区域。
在描述完高频信息与低频信息之后,我们来解释之前的问题。
-
什么是图像平滑?
图像平滑是要突出图像的低频成分、主干部分或抑制图像噪声和干扰高频成分的图像处理方法,目的是使图像亮度平缓渐变,减小突变梯度,改善图像质量。字面意思就是让图像上颜色灰度变化更光滑。我们也称图像平滑为图像模糊,因为在平滑的时候,也失去了尖锐的特点。
-
什么是图像去噪?
现实中的数字图像在数字化和传输过程中常受到成像设备与外部环境噪声干扰等影响,称为含噪图像或噪声图像。那么除去这些噪声的过程就是图像去噪。
-
图像平滑与图像去噪的关系
如上图所示,可以图像平滑和图像去噪有一部分是相同的,比如都是去掉高频信息。但是也有不同的,比如图像去噪,只想去掉图像的躁点,而不需要模糊到图像上的边缘。而图像平滑时,是不关注是否有噪点的,只是想把灰度变化激烈的部分进行平滑。但是早期图像平滑和去噪很多的算法是相似性的,或者用图像平滑的方法来达到去噪的目的。图像去噪的方法比如还有小波滤波等。
本文章仅介绍这些以图像平滑达到去噪目的的方法,当然不是最高级有效的,但是最简单的,之后我们会再通过单独的文章来介绍当前效果比较好的去噪或者平滑的方法。
图像噪声来源
按照图像噪声的来源我们也可以把噪声分为几种类型。
- 加性噪声,此类噪声与输入图象信号无关,含噪图象可表示为f(x,y)=g(x,y)+n(x,y),信道噪声及光导摄像管的摄像机扫描图象时产生的噪声就属这类噪声;典型的加性噪声有高斯噪声。
- 乘性噪声,此类噪声与图象信号有关,含噪图象可表示为f(x,y)=g(x,y)+n(x,y)g(x,y),飞点扫描器扫描图象时的噪声,电视图象中的相关噪声,胶片中的颗粒噪声就属于此类噪声。
- 量化噪声,此类噪声与输入图象信号无关,是量化过程存在量化误差,再反映到接收端而产生。是数字图像的主要噪声源,其大小显示出数字图像和原始图像的差异
图像噪声类型
上节噪声的来源大概将噪声分为了三类,下面我们按噪声的密度分布来区分。
- 高斯噪声:指噪声服从高斯分布,即某个强度的噪声点个数最多,离这个强度越远噪声点个数越少,且这个规律服从高斯分布。高斯噪声是一种加性噪声,即噪声直接加到原图像上,因此可以用线性滤波器滤除。
- 椒盐噪声(脉冲噪声):类似把椒盐撒在图像上,是一种在图像上出现很多白点或黑点的噪声,如电视里的雪花噪声等。椒盐噪声可以认为是一种逻辑噪声,一般采用中值滤波器滤波可以得到较好的结果。
- 均匀噪声:是指在整个频域内分布状况是常数的噪声。 所有频率具有相同能量密度的随机噪声称为白噪声。
- 瑞利噪声:噪声分布为瑞利分布。
- 指数噪声:噪声分布为指数分布。
- 伽马噪声:噪声分布为伽马(爱尔兰)分布。
如果我们能判断出噪声的来源以及分布状况,对于我们去出噪声会有很大的帮助。上面关于一些噪声的密度分布公式在这篇文章,不再进行详细的描述。后续会有文章进行详细的描述。
图像去噪平滑常见算法详述
这节我们将详述一些平滑去噪的方法,都属于低通滤波,如下:
- 均值滤波
- 高斯滤波
- 中值滤波
- 双边滤波
均值滤波
均值滤波也成线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用原图像中某个像素临近值的均值代替原图像中的像素值。即滤波器的核(kernel)中所有的系数都相等,然后用该核去对图像做卷积。
优点: 在一定程度上拉小灰度差异,减少噪声影响。对高斯噪声的表现比较好。
缺点: 对图像的边缘处也做均值,导致边缘处变模糊。对椒盐噪声的表现比较差。
高斯滤波
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。那么高斯滤波的核怎么得到?
首先我们看一下二维中的高斯函数:可以看出如果我们对高斯函数进行按照上面图离散化,得到高斯核,这个核主要取决于σ。如果σ越小,高斯分布中心区域更加聚集,平滑效果越差;反之,则更离散,平滑效果越明显。
中值滤波
中值滤波器,使用滤波器窗口包含区域的像素值的中值来得到窗口中心的像素值。是一种非线性平滑滤波器。在去噪同时,较好的保持边缘轮廓细节,适合处理椒盐噪声,但对高斯噪声效果不好。
双边滤波
双边滤波器是一种可以保边去噪的滤波器,也是一种加权平均滤波器,与高斯滤波不同的是,其滤波核是由两个函数构成,一个函数是由几何空间距离决定滤波器系数,另一个由像素差值决定滤波器系数。我们具体来看一下。
从上面的高斯滤波我们可以看出是一个有几何空间决定系数的滤波器(越远系数越小),所以第一个函数我们选用高斯函数。
我们看到当高斯函数σ确定时,变量只有x,y 。那么x,y其实就是与中心点的空间上的差值,如果我们将这个差值换成与中心点在像素值上的差值,是不是就是一个由像素值决定的滤波器函数。对,实际上我们也是这么做的,然后得到第二个函数,在一维上的高斯函数:
其中I(x,y)为邻域点的像素值,I(xc,yc)为核中心点(锚点)像素值。
然后我们将两个函数相乘,然后对相乘后的函数进行类似高斯滤波一样的离散化,得到双边滤波核,其实就是先对图像做了一遍高斯滤波,又做了一遍边缘保持操作。
在图像的平坦区域,像素值变化很小,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;在图像的边缘区域,像素值变化很大,像素范围域权重变大,从而保持了边缘的信息。
OpenCV 图像平滑效果展示[代码]
#include <opencv2/opencv.hpp>
#include <iostream>
cv::Mat addSaltNoise(cv::Mat &m, int num)
{
cv::Mat result = m.clone();
std::random_device rd;
std::mt19937 gen(rd());
auto cols = m.cols * m.channels();
for (int i = 0; i < num; i++)
{
auto row = static_cast<int>(gen() % m.rows);
auto col = static_cast<int>(gen() % cols);
auto p = result.ptr<uchar>(row);
p[col++] = 255;
p[col++] = 255;
p[col] = 255;
}
return result;
}
cv::Mat addGaussianNoise(cv::Mat & img, const int& mu,const int & sigma)
{
cv::Mat result = img.clone();
auto cols = img.cols*img.channels();
auto rows = img.rows;
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<> gaussR(mu, sigma);
for (int i = 0; i < rows; i++)
{
auto p = result.ptr<uchar>(i);
for (int j = 0; j < cols; j++)
{
auto tmp = p[j] + gaussR(gen);
tmp = tmp > 255 ? 255 : tmp;
tmp = tmp < 0 ? 0 : tmp;
p[j] = tmp;
}
}
return result;
}
int main(int argc, char *argv[])
{
cv::Mat color_image = cv::imread (argv[1]);
cv::Mat add_g_noise = addGaussianNoise(color_image,10,10);
cv::Mat add_s_noise = addSaltNoise(color_image,200);
cv::imwrite("color_image.png",color_image);
cv::imwrite("add_g_noise.png",add_g_noise);
cv::imwrite("add_s_noise.png",add_s_noise);
cv::Mat add_g_noise_blur,add_g_noise_medianBlur,add_g_noise_GaussianBlur,add_g_noise_bilateralFilter;
cv::blur(add_g_noise,add_g_noise_blur,cv::Size(7,7));
cv::medianBlur(add_g_noise,add_g_noise_medianBlur,7);
cv::GaussianBlur(add_g_noise,add_g_noise_GaussianBlur,cv::Size(5,5),0);
cv::bilateralFilter(add_g_noise,add_g_noise_bilateralFilter, 30, 30 * 2, 30 / 2);
cv::imwrite("add_g_noise_blur.png",add_g_noise_blur);
cv::imwrite("add_g_noise_medianBlur.png",add_g_noise_medianBlur);
cv::imwrite("add_g_noise_GaussianBlur.png",add_g_noise_GaussianBlur);
cv::imwrite("add_g_noise_bilateralFilter.png",add_g_noise_bilateralFilter);
cv::Mat add_s_noise_blur,add_s_noise_medianBlur,add_s_noise_GaussianBlur,add_s_noise_bilateralFilter;
cv::blur(add_s_noise,add_s_noise_blur,cv::Size(5,5));
cv::medianBlur(add_s_noise,add_s_noise_medianBlur,3);
cv::GaussianBlur(add_s_noise,add_s_noise_GaussianBlur,cv::Size(5,5),0);
cv::bilateralFilter(add_s_noise,add_s_noise_bilateralFilter, 5, 5 * 2, 5 / 2);
cv::imwrite("add_s_noise_blur.png",add_s_noise_blur);
cv::imwrite("add_s_noise_medianBlur.png",add_s_noise_medianBlur);
cv::imwrite("add_s_noise_GaussianBlur.png",add_s_noise_GaussianBlur);
cv::imwrite("add_s_noise_bilateralFilter.png",add_s_noise_bilateralFilter);
return 0;
}
均值滤波 | 中值滤波 |
---|---|
高斯滤波 | 双边滤波 |
均值滤波 | 中值滤波 |
---|---|
高斯滤波 | 双边滤波 |
可见对高斯噪声,双边滤波最优秀,即去掉了噪声又保持了边缘,其他几种滤波都很大程序上丢失了边缘。对椒盐噪声,中值滤波最优秀,基本上去掉了所有点的噪声,但是还有有一些模糊,高斯和均值滤波只是在一定程度上弱化了噪声,双边滤波基本上没有起作用。
总结
本文知识对图像的平滑去噪有一个基本的概念,其实平滑去噪还有很多的更高级的方式,使图像还原更好,而且噪声也不会这么简单。当然平滑也不仅仅是处理噪声,比如在美颜中也有很多的使用。本系列会在整理完基本的算法后,在整理一些更加精细复杂的算法。
重要的事情说三遍:
如果您看到我的文章对您有所帮助,那就点个赞呗 ( * ^ __ ^ * )
如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )
如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )
任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。博客地址:开飞机的乔巴
作者简介:开飞机的乔巴(WeChat:zhangzheng-thu),现主要从事机器人抓取视觉系统以及三维重建等3D视觉相关方面,另外对slam以及深度学习技术也颇感兴趣,欢迎加我微信或留言交流相关工作。