平滑处理,有时也称模糊处理,是图像处理领域最常用的操作。平滑的目的主要是用来去除噪声。通常平滑操作是通过卷积操作(注:实际上是相关操作,后面的叙述对这两个操作不加区分)完成。下面介绍几种常用的平滑滤波操作。
均值滤波
-
均值滤波是最简单的一种滤波操作,每个被滤波像素通过它邻近像素均值计算得到。
-
均值滤波的kernel如下:
高斯滤波
-
高斯滤波的核是通过高斯函数构建,越靠近中心的像素的值越大,这也反映了图像空域间关系,越邻近的像素相关性越强。
-
二维高斯函数如下:
中值滤波
-
以kernel里像素的中值作为被滤波后像素的值。
-
中值滤波法是一种非线性平滑技术。
-
中值滤波法对消除椒盐噪音非常有效。
双边滤波
-
上面的滤波方法在平滑图像时不仅会平滑噪声,往往还会模糊图像边缘。这是由于它们构造kernel时只用了空间位置信息。
-
双边滤波构造kernel不仅使用空间位置信息,还会使用颜色信息。
在opencv里提供了各种滤波器的调用接口,代码如下:
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{namedWindow("Smoothing Demo", WINDOW_AUTOSIZE);Mat src = imread("G:\\opencvDemo\\lena.jpg");Mat blurImg;Mat gaussianImg;Mat medianImg;Mat bilteralImg;Mat boxImg;Mat filter2DImg;
blur(src, blurImg, Size(5, 5));boxFilter(src, boxImg, -1, Size(5, 5), Point(-1, -1), true);GaussianBlur(src, gaussianImg, Size(5, 5),0,0);medianBlur(src, medianImg, 5);bilateralFilter(src, bilteralImg, 5, 10, 2.5);Mat kernal = Mat::ones(Size(5, 5), CV_8UC1);filter2D(src, filter2DImg, -1, kernal);//imshow("Smoothing Demo", bilteralImg);imwrite("blurImg55.jpg", blurImg);imwrite("boxImg55.jpg", boxImg);imwrite("gaussianImg55.jpg", gaussianImg);imwrite("medianImg55.jpg", medianImg);imwrite("bilteralImg55.jpg", bilteralImg);imwrite("filter2DImg55.jpg", filter2DImg);//waitKey(0);
return 0;
}
实验效果:
原始图像lena.jpg如下:
均值滤波:
滤波函数:blur()
void cv::blur ( InputArray src,OutputArray dst,Size ksize,Point anchor = Point(-1,-1),int borderType = BORDER_DEFAULT ) src : 输入图像dst : 输出图像ksize : kernel尺寸anchor: 被滤波像素在kernel中的位置,默认Point(-1,-1)表示在kernel中心borderType:图像边界填充方式
下图分别是kernel大小为3x3和5x5时的实验效果:
高斯滤波:
滤波函数:GaussianBlur()
void cv::GaussianBlur ( InputArray src,OutputArray dst,Size ksize,double sigmaX,double sigmaY = 0,int borderType = BORDER_DEFAULT ) src : 输入图像dst : 输出图像ksize : kernel尺寸sigmaX: Gaussian kernel在X方向的标准差sigmaY: Gaussian kernel在Y方向的标准差,如果sigmaY=0则sigmaY会被设为和sigmaX相等。如果sigmaX和sigmaY都为0,则它们会根据ksize.width和ksize.height计算得出。borderType:图像边界填充方式
下图分别是kernel大小为3x3和5x5时的实验效果:
中值滤波:
滤波函数:medianBlur()
void cv::medianBlur ( InputArray src,OutputArray dst,int ksize ) src : 输入图像dst : 输出图像ksize : kernel尺寸
下图分别是kernel大小为3x3和5x5时的实验效果:
双边滤波:
函数:bilateralFilter()
void cv::bilateralFilter ( InputArray src,OutputArray dst,int d,double sigmaColor,double sigmaSpace,int borderType = BORDER_DEFAULT ) src : 输入图像dst : 输出图像d : 计算滤波时邻域像素的直径,如果非正数将通过sigmaSpace计算得到。sigmaColor:颜色空间的影响因子。sigmaSpace:空域的影响因子。borderType:图像边界填充方式
下图分别是kernel大小为3x3和5x5时的实验效果:
补充:
下面补充两个滤波函数:
boxFilter()和 filter2D()
1、boxFilter()
void cv::boxFilter ( InputArray src,OutputArray dst,int ddepth,Size ksize,Point anchor = Point(-1,-1),bool normalize = true,int borderType = BORDER_DEFAULT ) normalize = true时,计算结果和均值滤波相同normalize = false时,滤波后像素值为kernel内像素值的和
kernel如下:
下图是normalize = false,ksize为3x3时的结果:
2、filter2D()
void cv::filter2D ( InputArray src,OutputArray dst,int ddepth,InputArray kernel,Point anchor = Point(-1,-1),double delta = 0,int borderType = BORDER_DEFAULT ) kernel是要使用的滤波核,可以自己根据需求随意构建
下图构建了一个3x3全1的滤波核,可以验证结果与上图相同:
小结
以上便是平滑滤波的基本内容,关键在于滤波核的选择。
欢迎留言交流。