第6章 图像处理
6.2 非线性滤波:中值滤波、双边滤波
6.2.1 非线性滤波
很多情况下,使用领域像素的非线性滤波会得到更好的效果,如在噪声是散粒噪声而不是高斯噪声,即图像偶尔会出现很大值时,高斯滤波效果不如中值滤波
6.2.2 中值滤波(medianBlur)
1.滤波原理:基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,用像素点邻域灰度值的中值替代像素点的灰度值,让周围的像素值接近真实值,从而消除孤立的噪声点,该方法在去除脉冲噪声、斑点噪声(speckle noise)、椒盐噪声(salt-and-pepper noise)的同时又能保留图像的边缘细节。
2.优点:在均值滤波中,由于噪声成份被放入平均计算中,所以输出受到了影响,但在中值滤波中,由于噪声成分很难选上,所以几乎不会影响输出。可克服线性滤波的细节模糊。
3.缺点:中值滤波是均值滤波的5倍以上时间,且不适合细节多的图像
4.取3*3函数窗,计算以点[i,j]为中心的函数窗像素中值,步骤:
(1)按强度值大小排列像素点
(2)选择排序像素集的中间值作为点[i,j]的值
5.封装函数:medianBlur函数
6.函数原型:
void medianBlur(InputArray src,OutputArray dst,int ksize)
7.参数说明:
(1)Mat类型输入图像(1/3/4通道),ksize为3或5时,图像深度应为CV_8U、CV_16U、CV_32F之一
(2)目标图像,与输入图像尺寸类型一致,可用srcImage.clone()初始化目标图像
(3)ksize,孔径的线性尺寸(aperture linear size),必须是大于1的奇数
6.2.3 双边滤波(bilateralFilter)
1.双边滤波:一种非线性滤波方法,图像的空间邻近度和像素值相似度的折中,同时考虑空域信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部特点
2.优点:基于空间分布的高斯滤波函数,较远像素不会太影响边缘像素,保证了边缘保存(edge-preserving)
3.缺点:由于保存了过多高频信息,对彩色图像里的高频噪声不能很好过滤,只能对低频信息较好滤波
4.滤波原理:输出像素依赖于邻域像素值的加权值组合:
加权系数w(i,j,k,l)取决于定义域核和值域核乘积
定义域核:
值域核:
两者相乘后,会产生依赖于数据的双边滤波权重函数
5.封装函数:bilateralFilter函数
6.函数原型:
void bilateralFilter(InputArray src,OutputArray dst,int d,double sigmaColor,double simgmaSpace,int borderType=BORDER_DEFAULT)
7.参数说明:
(1)输入图像,8位或浮点型单通道、三通道图像
(2)目标图像,与输入图像尺寸类型一致
(3)过滤过程中每个像素邻域的直径,为非正数时,从参数sigmaSpace计算它
(4)颜色空间滤波器的sigma值,值越大表明像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域
(5)坐标空间中滤波器的sigma值,坐标空间的标注方差,值越大,表明越远的像素会相互影响,使更大的区域中足够相似的颜色获取相同颜色。d>0时,d指定了领域大小且与sigmaSpace无关,否则d正比于sigmaSpace
(6)用于推断图像外部像素的某种边界模式
6.2.4 非线性滤波示例
1.两种非线性滤波
#include<opencv2/opencv.hpp>#include<opencv2/core/core.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>using namespace cv;int main(){//载入原图Mat srcImage = imread("love.jpg");//显示原图namedWindow("中值滤波【原图】");imshow("中值滤波【原图】", srcImage);//中值滤波Mat dstImage1;medianBlur(srcImage, dstImage1, 7);namedWindow("中值滤波【效果图】");imshow("中值滤波【效果图】", dstImage1);//双边滤波Mat dstImage2;bilateralFilter(srcImage, dstImage2, 25, 25 * 2, 25 / 2);namedWindow("双边滤波【效果图】");imshow("双边滤波【效果图】", dstImage2);waitKey(0);return 0;}
2.滑动条控制滤波模糊度
#include<opencv2/core/core.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>#include<iostream>using namespace cv;using namespace std;//全局变量Mat g_srcImage, g_dstImage1, g_dstImage2;int g_nMedianBlurValue;int g_nBilateralFilterValue;//全局函数static void on_MedianBlur(int, void*);static void on_BilateralFilter(int, void*);int main(){//改变控制台字体颜色system("color 5E");//载入原图g_srcImage = imread("love.jpg");if (!g_srcImage.data){printf("载入原图像失败~!\n");return false;}//复制原图到目标图像g_dstImage1 = g_srcImage.clone();g_dstImage2 = g_srcImage.clone();//初始化内核值g_nMedianBlurValue = 7;g_nBilateralFilterValue = 10;//显示原图namedWindow("非线性滤波【原图】",1);imshow("非线性滤波【原图】", g_srcImage);//========================【<1>中值滤波】=======================//创建窗口namedWindow("中值滤波【效果图】",1);//创建滑动条createTrackbar("内核值:", "中值滤波【效果图】", &g_nMedianBlurValue, 50, on_MedianBlur);on_MedianBlur(g_nMedianBlurValue, 0);//===============================================================//========================【<2>双边滤波】========================//创建窗口namedWindow("双边滤波【效果图】",1);//创建滑动条createTrackbar("内核值:", "双边滤波【效果图】", &g_nBilateralFilterValue, 50, on_BilateralFilter);on_BilateralFilter(g_nBilateralFilterValue, 0);//===============================================================waitKey(0);return 0;}static void on_MedianBlur(int, void*){medianBlur(g_srcImage, g_dstImage1, g_nMedianBlurValue*2+1);imshow("中值滤波【效果图】", g_dstImage1);}static void on_BilateralFilter(int, void*){bilateralFilter(g_srcImage, g_dstImage2, g_nBilateralFilterValue, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);imshow("双边滤波【效果图】", g_dstImage2);}