模糊操作时图像处理中最简单和常用的操作之一,使用该操作的原因之一就为了给图像预处理时减低噪声。
使用模糊操作的背后是数学的卷积计算:
其中权重核
h(k,l)
为“滤波系数”。上面的式子可以简记为:
通常这些卷积算子计算都是线性操作,所以又叫线性滤波。
均值滤波(归一化滤波)
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
用 3×3 大小模板进行均值滤波。
由于图像边框上的像素无法被模板覆盖,所以不做处理。
这当然造成了图像边缘的缺失
以(2,2)像素点为例。
则滤波后的结果为:
滤波后(2,2)像素点的值由 10 变为 3
最终结果:
OpenCV提供均值滤波API:
void blur(Mat src,Mat dst, Size(xradius,yradius), Point(-1, -1))
实例代码:
//均值滤波
void Averblur(){
Mat src,dest;
src = imread("lena_noise.jpg");//对带椒盐噪声的图片进行处理
if(!src.data){
cout << "图像载入失败!" << endl;
return ;
}
namedWindow("均值滤波【原图】",CV_WINDOW_AUTOSIZE);
imshow("均值滤波【原图】",src);
//进行均值滤波
blur(src,dest,Size(11,11));
namedWindow("均值滤波【处理后】",CV_WINDOW_AUTOSIZE);
imshow("均值滤波【处理后】",dest);
cvWaitKey();
}
效果图:
对于椒盐噪声:
对于高斯噪声:
中值滤波
中值,中间值,将数据从小到大排序后的中间值
用 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)
实例代码:
//中值滤波
void Medianblur(){
//void medianBlur(InputArray src, OutputArray dst, int ksize)
/*
ksize:必须大于1还是奇数
*/
Mat src,dest;
src = imread("lena_noise.jpg");
if(!src.data){
cout << "图像载入失败!" << endl;
return ;
}
namedWindow("中值滤波【原图】",CV_WINDOW_AUTOSIZE);
imshow("中值滤波【原图】",src);
//进行中值滤波
medianBlur(src,dest,3);
namedWindow("中值滤波【处理后】",CV_WINDOW_AUTOSIZE);
imshow("中值滤波【处理后】",dest);
cvWaitKey();
}
处理结果:
对于椒盐噪声:
对于高斯噪声
中值滤波对于椒盐噪声抑制作用较强,但是对于高斯噪声就无能为力了!
高斯滤波
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
OpenCV提供API:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
实例代码:
void Gaussianblur(){
//
Mat src,dest;
src = imread("lena_noise2.jpg");
if(!src.data){
cout << "图像载入失败!" << endl;
return ;
}
namedWindow("高斯滤波【原图】",CV_WINDOW_AUTOSIZE);
imshow("高斯滤波【原图】",src);
//进行高斯滤波
GaussianBlur(src,dest,Size(7,7),3,3);
namedWindow("高斯滤波【处理后】",CV_WINDOW_AUTOSIZE);
imshow("高斯滤波【处理后】",dest);
cvWaitKey();
}
处理结果:
双边滤波
- 均值模糊无法克服边缘像素信息丢失缺陷。原因是均值模糊是基于平均权重。
- 高斯模糊部分克服了该缺陷,但是无法完全避免,因为没考虑到像素值的不同。
- 双边滤波是保留边缘的滤波方法,避免了边缘信息的丢失,保留了图像轮廓不变。
OpenCV提供的API:
void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )
实例代码:
//双边滤波
void Bilaterblur(){
//void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )
/*
d:计算的半径
sigmaColor:多少差值之内的像素会被计算
sigmaSpace:如果d>0,那么声明无效,否则根据它来计算d值
*/
Mat src,dest;
src = imread("woman.jpg");
if(!src.data){
cout << "图像载入失败!" << endl;
return ;
}
namedWindow("双边滤波【原图】",CV_WINDOW_AUTOSIZE);
imshow("双边滤波【原图】",src);
//进行双边滤波
bilateralFilter(src,dest,15,150,3);
namedWindow("双边滤波【处理后】",CV_WINDOW_AUTOSIZE);
imshow("双边滤波【处理后】",dest);
//增强对比度
Mat result = Mat::zeros(dest.size(),dest.type());
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
filter2D(dest,result,dest.depth(),kernel);
namedWindow("最终结果",CV_WINDOW_AUTOSIZE);
imshow("最终结果",result);
cvWaitKey();
}
最终结果:
使用双边滤波后再使用掩膜增强对比度,这效果。杠杠滴!!