根据数学知识,一维高斯函数能够描述为:
在图像处理中,选定X方向上长度为3的窗口,令δ=1,中心坐标为1,由上述公式,其卷积核(Xa,X,Xb)能够以下计算:ios
Xa = exp(-1*(0-1)(0-1)/(2*1*1))= 0.606530659712633 X = exp(-1*(1-1)(1-1)/(2*1*1))= 1 Xb = exp(-1*(2-1)(2-1)/(2*1*1))= 0.606530659712633
能够看到计算过程没有用到常数部分,是由于须要归一化,常数部分能够省略:算法
Sum = Xa + X + Xb = 2.2130613194252668 Xa = Xa/Sum = 0.274068619061197 X = X/Sum = 0.451862761877606 Xb = Xb/Sum = 0.274068619061197
经过OpenCV验证下上述结果是否正确,OpenCV能够经过函数getGaussianKernel()来实现计算高斯核,运行以下代码,能够发现二者的计算结果是一致的。函数
Mat kernelX = getGaussianKernel(3, 1); cout << kernelX << endl;
上述的推导过程都是一维的,那么二维状况下的卷积核怎么计算呢,其实很简单,转置并相乘就能够了:学习
Mat kernelX = getGaussianKernel(3, 1); cout << kernelX << endl; Mat kernelY = getGaussianKernel(3, 1); Mat G = kernelX * kernelY.t(); cout << G << endl << endl << endl;
运行结果:
在获得卷积核以后,将其放到图像中进行二维卷积,对于原图像中的一个像素P(x,y),有以下卷积过程:
将窗口覆盖的对应位置的像素值相乘后相加,便可获得新图像对应位置的像素值Q(x,y)。当对图像全部的像素值都这样作时,就能够获得滤波后的图像。因为通常状况下老是顺序去卷积的,从左至右,由上而下,因此这个过程就是卷积核的滑动。spa
当滑动到边界的时候,就会产生一个问题,就是卷积核对应的位置没有像素值。这时能够将边界像素值舍弃(卷积),或者自动填充为0(滤波)。.net
在OpenCV中,能够直接使用GaussianBlur()函数实现高斯滤波,可是为了验证和学习高斯滤波算法,也能够本身构建高斯卷积核,使用滤波函数filter2D()进行滤波。其具体实现以下:code
#include <iostream> #include <opencv2\opencv.hpp> using namespace cv; using namespace std; int main() { //从文件中读取成灰度图像 const char* imagename = "C:\\Data\\imgDemo\\lena.jpg"; Mat img = imread(imagename, IMREAD_GRAYSCALE); if (img.empty()) { fprintf(stderr, "Can not load image %s\n", imagename); return -1; } //直接高斯滤波 Mat dst1; GaussianBlur(img, dst1, Size(3, 3), 1, 1); //自定义高斯滤波器 Mat kernelX = getGaussianKernel(3, 1); Mat kernelY = getGaussianKernel(3, 1); Mat G = kernelX * kernelY.t(); Mat dst2; filter2D(img, dst2, -1, G); //比较二者的结果 Mat c; compare(dst1, dst2, c, CMP_EQ); // imshow("原始", img); imshow("高斯滤波1", dst1); imshow("高斯滤波2", dst2); imshow("比较结果", c); waitKey(); return 0; }
能够看到这里分别用GaussianBlur()和filter2D()进行了高斯滤波,并经过compare()函数进行比较。运行结果以下所示,二者的滤波结果基本一致,说明构建的卷积核是正确的。
htm
1.OpenCV实现二维高斯核GaussianKernel
2.opencv3.2.0图像处理之高斯滤波GaussianBlur API函数
3.OpenCV高斯滤波器详解及代码实现blog