OpenCV3入门(六)图像滤波
1、图像滤波理论
1.1图像滤波理论
图像滤波即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作。消除图像中的噪声又叫做图像滤波或平滑,滤波的目的有两个,一是突出特征以方便处理,二是抑制噪声。
空间域滤波就是在图像平面上对像素进行操作。空间域滤波大体分为两类:平滑、锐化。
平滑滤波:模糊处理,用于减小噪声,实际上是低通滤波,典型的滤波器是高斯滤波。
锐化滤波:提取边缘突出边缘及细节、弥补平滑滤波造成的边缘模糊。实际上是高通滤波。
空间域处理可由下式表示:
g(x,y)=T[f(x,y)]
式中,f(x,y)是输入图像,g(x,y)是处理后的图像,T是在点(x,y)的邻域上定义的关于f的一种算子,算子可应用于单幅图像或图像集合。
1.2邻域滤波算子
1)空间滤波器由一个邻域(通常是一个较小的矩形)和对该邻域所包围图像像素执行的预定义操作组成。对预定义的点(x,y)为中心的领域内的像素进行计算。
2)滤波产生一个新像素,用计算后的新像素值代替点(x,y)的值。
3)循环步骤1和2,滤波器的中心遍历图像中的每个像素后,就生成了滤波后的图像。
4)如果在图像像素上执行的是线性操作,则该滤波器称为线性空间滤波器,否则,称为非线性空间滤波器。
一般来说,使用大小为 m×n的滤波器对大小为 M×N的图像进行线性空间滤波,可由下式表示:
2、OpenCV滤波方法
滤波处理分为两大类:线性滤波和非线性滤波。OpenCV里有这些滤波的函数,使用起来非常方便。
线性滤波:
1.方框滤波BoxBlur:模糊图像
2.均值滤波Blur:模糊图像
3.高斯滤波GaussianBlur:信号的平滑处理,去除符合正太分布的噪声
非线性滤波:
1.中值滤波mediaBlur:去除椒盐噪声
2.双边滤波BilateralFilter:保边去噪
3、线性滤波器
3.1平滑滤波
一般来说,图像具有局部连续的性质,即相邻的像素的值相近,而噪声使得噪点处产生像素跳跃,所以通过平滑噪点可以减少噪声,去除图像中的不相关细节。
方框滤波BoxBlur和均值滤波Blur都是对邻域内做平均值来滤波,属于平滑滤波。滤波的输出是包含在滤波器模板邻域内的像素的平均值,方框滤波做归一化之后就变为均值滤波,这两个滤波器都是低通滤波器。
函数原型如下:
CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), bool normalize=true, int borderType=BORDER_DEFAULT ); CV_EXPORTS_W void blur( InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT );
3.2高斯滤波
高斯滤波对于图像来说就是一个低通滤波,广泛用于消除高斯噪声,高速滤波就是一种加权滤波,只不过模板中的系数由高斯分布来确定的,高斯滤波器根据高斯函数的形状来选择滤波模板权值的线性平滑滤波器。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。
CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT );
3.3测试实验
Mat img; Mat img1, img2, img3; int gBoxFilterValue = 3; int gMeanBlurValue = 3; int gGaussianBlurValue = 3; static void OnBoxFilter(int filterSz, void *) { boxFilter(img, img1, -1, Size(filterSz +1, filterSz +1)); imshow("方框滤波", img1); } static void OnMeaanBlur(int filterSz, void *) { blur(img, img2, Size(filterSz + 1, filterSz + 1)); imshow("均值滤波", img2); } static void OnGaussinanBlur(int filterSz, void *) { GaussianBlur(img, img3, Size(filterSz*2 + 1, filterSz*2 + 1), 0, 0); imshow("高斯滤波", img3); } int main() { img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp"); img1 = img.clone(); img2 = img.clone(); img3 = img.clone(); imshow("原图", img); namedWindow("方框滤波", 1); createTrackbar("内核值", "方框滤波", &gBoxFilterValue, 40, OnBoxFilter); OnBoxFilter(gBoxFilterValue, 0); namedWindow("均值滤波", 1); createTrackbar("内核值", "均值滤波", &gMeanBlurValue, 40, OnMeaanBlur); OnMeaanBlur(gMeanBlurValue, 0); namedWindow("高斯滤波", 1); createTrackbar("内核值", "高斯滤波", &gGaussianBlurValue, 40, OnGaussinanBlur); OnGaussinanBlur(gGaussianBlurValue, 0); waitKey(0); }
输出结果如下图。
4、非线性滤波器
4.1中值滤波
中值滤波属于非线性滤波,其思想用滤波模板邻域内的像素的平均值来代替像素点的灰度值。中值滤波器是一种统计排序滤波器,图像上点(x,y),中值滤波以该点为中心,领域内所有像素的统计排序中值作为此点的响应,中值滤波是非线性滤波。相比与均值滤波和高斯滤波,中值滤波可以有效的降低随机噪声,直接忽略掉噪声点,把噪声引起的模糊降到最低。线性滤波器在滤波的同时会造成图像细节模糊,中值滤波可以避免这个问题,其典型的应用就是中值滤波消除斑点噪声、椒盐噪声。
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
使用中值滤波,滤除椒盐噪声例子如下。
img = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp"); salt(img, 1000); img1 = img.clone(); img2 = img.clone(); img3 = img.clone(); imshow("原图", img); namedWindow("高斯滤波", 1); createTrackbar("内核值", "高斯滤波", &gGaussianBlurValue, 40, OnGaussinanBlur); OnGaussinanBlur(gGaussianBlurValue, 0); namedWindow("中值滤波", 1); createTrackbar("内核值", "中值滤波", &gMedianBlurValue, 40, OnMedianBlur); OnMedianBlur(gMedianBlurValue, 0); waitKey(0); }
输出结果如下图。高斯滤波在滤除噪点的同时也造成了图像模糊,如果增大内核则会造成严重模糊失真,而中值滤波对椒盐噪声有很好的抑制作用。
4.2双边滤波
高斯滤波属于加权平均滤波,距离中心点越近的点越有较大权重,这种方法符合图像的平滑变化的特征,但是在边缘区域,像素值出现突变,这种方法反而会滤掉边缘轮廓,损失掉有用的边缘信息。边缘保护滤波方法,双边滤波就是最常用的边缘保护滤波方法,就是为了处理这种情况而发明的。
双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。双边滤波将高斯滤波中通过各个点到中心点的空间临近度计算的各个权值进行优化,将其优化为空间临近度计算的权值和像素值相似度计算的权值的乘积,优化后的权值再与图像作卷积运算,从而达到保边去噪的效果。
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT );
InputArray src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
OutputArray dst: 输出图像,和原图像有相同的尺寸和类型。
int d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
double sigmaColor: 颜色空间过滤器的sigma值,这个参数的值越大,更大的值域空间影响结果。
double sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,更大的定义域空间影响结果。
int borderType=BORDER_DEFAULT:边界模式,有默认值BORDER_DEFAULT.
static void OnBilateralFilter(int filterSz, void *) { bilateralFilter(img, img3, filterSz, filterSz * 2, filterSz / 2); imshow("双边滤波", img3); } namedWindow("双边滤波", 1); createTrackbar("内核值", "双边滤波", &gMedianBlurValue, 40, OnBilateralFilter); OnBilateralFilter(gMedianBlurValue, 0);
输出效果如下图。双边滤波在较大的参数范围内都保持了很好的噪声抑制特性,并且没有造成边缘模糊。
5、遇到的问题medianBlur报异常
调节中值滤波的滑动条时,出现异常。
vs报错:
未经处理的异常:
0x00007FF835C09159 处(位于 Day1.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x000000F29FAFE138 处。
解决方法:
中值滤波的参数ksize需要为偶数。
@param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U. @param dst destination array of the same size and type as src. @param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ... @sa bilateralFilter, blur, boxFilter, GaussianBlur */ CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
使用例子:
static void OnMedianBlur(int filterSz, void *) { if (filterSz % 2 == 0) filterSz += 1; medianBlur(img, img2, filterSz); imshow("中值滤波", img2); }
测试效果图如下:
6、参考文献
1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著
2、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著
3、OpenCV双边滤波详解及实代码实现
https://blog.csdn.net/qq_36359022/article/details/80198890
4、Bilateral Filtering for Gray and Color Images
https://users.soe.ucsc.edu/~manduchi/Papers/ICCV98.pdf
5、Smoothing Images
https://docs.opencv.org/4.1.2/dc/dd3/tutorial_gausian_median_blur_bilateral_filter.html
6、OpenCV图像处理之滤波
https://blog.csdn.net/qq_30815237/article/details/86690190
尊重原创技术文章,转载请注明。