图像模糊操作
模糊操作时图像处理中最简单和常用的操作之一,使用该操作的原因之一就为了给图像预处理时减低噪声,二值化、特征提取之前最好要给图像降低噪声。
两种常见的噪声:
1、椒盐噪声
椒盐噪声是由图像传感器,传输信道,解码处理等产生的黑白相间的亮暗点噪声。椒盐噪声分为两种即胡椒噪声和盐噪声,胡椒噪声是黑色的,属于低灰度噪声,盐噪声是白色的,属于高灰度噪声,一般两种噪声同时出现,呈现在图像上就是黑白杂点。去除椒盐噪声最常用的算法是中值滤波。
2、高斯噪声
高斯噪声是一种随机噪声,其幅度的统计规律服从高斯分布(正态分布),去高斯噪声最常用的算法是高斯滤波。如下图即是有高斯噪声的。
使用模糊操作的背后是数学的卷积计算。
卷积本身是连续的,但在图像处理中,因为像素是一个一个的,因此得把它看成是离散型的。
k,l是滤波模板大小
h(k,l)---> 卷积和 卷积算子 处理的窗口 滤波模板 掩膜(暂且把他们当作一样东西)
i,j表示元素遍历的行和列
在锐化和模糊时,会用到一些模板,这些模板是一个小如3×3,5×5的矩阵,用来与原图像进行处理(这种处理叫卷积操作)产生新的图像。通常这些卷积算子计算都是线性操作,所以又叫线性滤波。
其中权重核h(k,l)为“滤波系数”。上面的式子可以简记为:
===============================================================
均值滤波(归一化滤波)
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
用 3×3 大小模板进行均值滤波。
由于图像边框上的像素无法被模板覆盖,所以不做处理。
这当然造成了图像边缘的缺失,
3*3 边缘有一圈未被处理
5*5 边缘有两圈未被处理
以(2,2)像素点为例。
则滤波后的结果为:
滤波后(2,2)像素点的值由 10 变为 3
当然OpenCV提供了均值滤波API,这样我们就舍去了很多繁琐的步骤:
void blur(Mat src,Mat dst, Size(xradius,yradius), Point(-1, -1))
- src:原始图像
- dst:模糊图像
- Size( k, l ):滤波模板大小
- Point(-1,-1):中心点定位,表示给掩膜的正中心赋值 ,一般就这样用不用修改
滤波模板大小==卷积和的大小==窗口的大小 --->Size(k,l)一定是奇数1,3,5.... 偶数的话不好处理也不好看。
缺陷:高的像素均值滤波之后值就变低了,失去了其像素值高的特性。
效果图:
对于椒盐噪声:
对于高斯噪声:
===============================================================
中值滤波
中值,中间值,将数据从小到大排序后的中间值
对椒盐噪声有很好的抑制作用
原因:图像在传输过程中难免会有一些噪声,椒盐噪声一般都是由像素极值造成的,而中值滤波可以
很好的解决这个问题。
用 3×3 大小模板进行中值滤波。
以(2,2)像素点为例。
对模板中的 9 个数进行从小到大排序:1,1,1,2,2,5,6,6,10。中间值为 2.所有,中值滤波后(2,2)位置的值变为 2. 同理对其他像素点。
OpenCV提供中值滤波API:
void medianBlur(InputArray src, OutputArray dst, int ksize)
- src:原始图像
- dst:模糊图像
- i :滤波模板大小(宽度),必须为奇数
处理结果:
对于椒盐噪声:
对于高斯噪声
中值滤波对于椒盐噪声抑制作用较强,但是对于高斯噪声就无能为力了!
===============================================================
高斯滤波
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。高斯滤波(保留原有像素的特质,高的像素滤波之后还是高,它是基于权重模糊)
OpenCV提供API:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
- src:原始图像
- dst:模糊图像
- Size( i, i ):滤波模板大小,必须为奇数即1,3,5,7。。。
- σx:x方向标准差
- σy:y方向标准差
处理结果:
===============================================================
双边滤波
双边滤波主要是高斯双边滤波,它也是针对高斯滤波的缺陷而存在的。(美颜app常用)
- 均值模糊无法克服边缘像素信息丢失缺陷。原因是均值模糊是基于平均权重。
- 高斯模糊部分克服了该缺陷,但是无法完全避免,因为没考虑到像素值的不同。
- 双边滤波是保留边缘的滤波方法,避免了边缘信息的丢失,保留了图像轮廓不变。
OpenCV提供的API
void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )
- src:原始图像
- dst:模糊图像
- i :滤波模板大小
- σColor:颜色空间标准差
- σSpace:坐标空间标准差
最终结果:
使用了双边滤波得出中间那幅图,再使用掩膜增加图像的对比度得出右边那幅图。
代码示例如下:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src = imread("liaowenbin.jpg");
if (!src.data)
{
printf("could not find picture .../n");
return -1;
}
char WINDOWNAME_SRC[] = "Src";
char WINDOWNAME_BLUR[] = "blur";
char WINDOWNAME_Gauss[] = "Gaussblur";
char WINDOWNAME_DoubleGauss[] = "DoubleGaussBlur";
char WINDOWNAME_Result[] = "ResultImg";
namedWindow(WINDOWNAME_SRC,WINDOW_AUTOSIZE);
//namedWindow(WINDOWNAME_BLUR,WINDOW_AUTOSIZE);
//namedWindow(WINDOWNAME_Gauss, WINDOW_AUTOSIZE);
namedWindow(WINDOWNAME_DoubleGauss, WINDOW_AUTOSIZE);
namedWindow(WINDOWNAME_Result,WINDOW_AUTOSIZE);
//高斯双边滤波
Mat DoubleGaussDst = Mat(src.size(), src.type());
bilateralFilter(src,DoubleGaussDst,3,1,1);
//提高对比度
Mat resultImg = Mat(src.size(), src.type());
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,
-1,5,-1,
0,-1,0);
filter2D(DoubleGaussDst,resultImg,-1,kernel);
imshow(WINDOWNAME_SRC, src);
//imshow(WINDOWNAME_BLUR,BlurDst);
//imshow(WINDOWNAME_Gauss, GaussDst);
imshow(WINDOWNAME_DoubleGauss, DoubleGaussDst);
imshow(WINDOWNAME_Result, resultImg);
waitKey(0);
return 0;
}