【从零学习OpenCV 4】高斯滤波
重磅干货,第一时间送达
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
高斯噪声是一种常见的噪声,图像采集的众多过程中都容易引入高斯噪声,因此针对高斯噪声的高斯滤波也广泛应用于图像去噪领域。高斯滤波器考虑了像素离滤波器中心距离的影响,以滤波器中心位置为高斯分布的均值,根据高斯分布公式和每个像素离中心位置的距离计算出滤波器内每个位置的数值,从而形成一个形如图5-15所示的高斯滤波器。之后将高斯滤波器与图像之间进行滤波操作,进而实现对图像的高斯滤波。
图5-15 高斯滤波器空间构型
OpenCV 4提供了对图像进行高斯滤波操作的GaussianBlur()函数,该函数的函数原型在代码清单5-13中给出。
代码清单5-13 GaussianBlur()函数原型
void cv::GaussianBlur(InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
)
src:待高斯滤波图像,图像可以具有任意的通道数目,但是数据类型必须为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。 dst:输出图像,与输入图像src具有相同的尺寸、通道数和数据类型。 ksize:高斯滤波器的尺寸,滤波器可以不为正方形,但是必须是正奇数。如果尺寸为0,则由标准偏差计算尺寸。 sigmaX:X方向的高斯滤波器标准偏差。 sigmaY:Y方向的高斯滤波器标准偏差; 如果输入量为0,则将其设置为等于sigmaX,如果两个轴的标准差均为0,则根据输入的高斯滤波器尺寸计算标准偏差。 borderType:像素外推法选择标志,取值范围在表3-5中给出,默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。
该函数能够根据输入参数自动生成高斯滤波器,实现对图像的高斯滤波,函数的前两个参数与前面介绍的滤波函数的参数含义相同。该函数第三个参数是高斯滤波器的尺寸,与前面函数不同的是,该函数除了必须是正奇数以外,还允许输入尺寸为0,当输入的尺寸为0时,会根据输入的标准偏差计算滤波器的尺寸。函数第四个和第五个参数为X方向和Y方向的标准偏差,当Y方向参数为0时表示Y方向的标准偏差与X方向相同,当两个参数都为0时,则根据输入的滤波器尺寸计算两个方向的标准偏差数值。但是为了能够使计算结果符合自己的预期,建议将第三个参数、第四个参数和第五个参数都明确的给出。
高斯滤波器的尺寸和标准偏差存在着一定的互相转换关系,OpenCV 4提供了输入滤波器单一方向尺寸和标准偏差生成单一方向高斯滤波器的getGaussianKernel()函数,在函数的定义中给出了滤波器尺寸和标准偏差存在的关系,这个关系不是数学中存在的关系,而是OpenCV 4为了方便而自己设定的关系。在了解这个关系之前,我们首先了解以下getGaussianKernel()函数,该函数的函数原型在代码清单5-14中给出。
代码清单5-14 getGaussianKernel()函数原型
Mat cv::getGaussianKernel(int ksize,
double sigma,
int ktype = CV_64F
)
ksize:高斯滤波器的尺寸。 sigma:高斯滤波的标测差。 ktype:滤波器系数的数据类型,可以是CV_32F或者CV_64F,默认数据类型为CV_64F。
该函数用于生成指定尺寸的高斯滤波器,需要注意的是该函数生成的是一个ksize×1的Mat类矩阵。函数第一个参数是高斯滤波器的尺寸,这个参数必须是一个正奇数。第二个参数表示高斯滤波的标准差,这个参数如果是一个负数,则调用程序中默认的高斯滤波器尺寸与标准差的公式,其计算公式如式(5.4)所示。
生成一个二维的高斯滤波器需要调用两次getGaussianKernel()函数,将X方向的一维高斯滤波器和Y方向的一维高斯滤波器相乘,得到最终的二维高斯滤波器。例如计算的X方向的一维滤波器和Y方向的一维滤波器均如式(5.5)所示。
最终二维高斯滤波器计算过程和结果如式(5.6)所示。
为了了解高斯滤波对不同噪声的去除效果,在代码清单5-15中利用高斯滤波分别处理不含有噪声的图像、含有椒盐噪声的图像和含有高斯噪声的图像,处理结果在图5-16、图5-17、图5-18中给出。通过结果可以发现,高斯滤波对高斯噪声去除效果较好,但是同样会对图像造成模糊,并且滤波器的尺寸越大,滤波后图像变得越模糊。
代码清单5-15 myGaussianBlur.cpp图像高斯滤波
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);
Mat equalLena_gauss = imread("equalLena_gauss.png", IMREAD_ANYDEPTH);
Mat equalLena_salt = imread("equalLena_salt.png", IMREAD_ANYDEPTH);
if (equalLena.empty()||equalLena_gauss.empty()||equalLena_salt.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat result_5, result_9; //存放不含噪声滤波结果,后面数字代表滤波器尺寸
Mat result_5gauss, result_9gauss; //存放含有高斯噪声滤波结果,后面数字代表滤波器尺寸
Mat result_5salt, result_9salt; ////存放含有椒盐噪声滤波结果,后面数字代表滤波器尺寸
//调用均值滤波函数blur()进行滤波
GaussianBlur(equalLena, result_5, Size(5, 5), 10, 20);
GaussianBlur(equalLena, result_9, Size(9, 9), 10, 20);
GaussianBlur(equalLena_gauss, result_5gauss, Size(5, 5), 10, 20);
GaussianBlur(equalLena_gauss, result_9gauss, Size(9, 9), 10, 20);
GaussianBlur(equalLena_salt, result_5salt, Size(5, 5), 10, 20);
GaussianBlur(equalLena_salt, result_9salt, Size(9, 9), 10, 20);
//显示不含噪声图像
imshow("equalLena ", equalLena);
imshow("result_5", result_5);
imshow("result_9", result_9);
//显示含有高斯噪声图像
imshow("equalLena_gauss", equalLena_gauss);
imshow("result_5gauss", result_5gauss);
imshow("result_9gauss", result_9gauss);
//显示含有椒盐噪声图像
imshow("equalLena_salt", equalLena_salt);
imshow("result_5salt", result_5salt);
imshow("result_9salt", result_9salt);
waitKey(0);
return 0;
}
图5-16 myGaussianBlur.cpp程序中不含噪声图像高斯滤波结果
图5-17 myGaussianBlur.cpp程序中含椒盐噪声图像高斯滤波结果
图5-18 myGaussianBlur.cpp程序中含高斯噪声图像高斯滤波结果