可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较

在学习图像滤波中了解到图像滤波具有可分离性,首先理解可分离滤波的概念:可分离性指的是先对X(Y)方向滤波,再对Y(X)方向滤波的结果与将两个方向联合滤波器的整体滤波结果相同。

两个滤波器的联合就是将两个方向的滤波器相乘,一个是一维行向量,一个是一维列向量,相乘得到的是一个矩阵滤波器即联合滤波器。

如果在使用filter2D()函数进行滤波前计算联合滤波器,需要调用两次的filter2D函数,实现起来比较冗杂。故在OpenCV4中提供了sepFilter2D()滤波函数,此函数可以输入两个方向的滤波器。

官方给出的函数原型为:

void cv::sepFilter2D(InputArray  src,
                          OutputArray  dst,
                          int  ddepth,
                          InputArray  kernelX,
                          InputArray  kernelY,
                          Point  anchor = Point(-1,-1),
                          double  delta = 0,
                          int  borderType = BORDER_DEFAULT 
                          )

参数详解如下: 

  • src:待滤波图像
  • dst:输出图像,与输入图像src具有相同的尺寸、通道数和数据类型。
  • ddepth:输出图像的数据类型(期望深度desired depth),根据输入图像的数据类型不同拥有不同的取值范围,当赋值为-1时,输出图像的数据类型自动选择。
  • kernelX:X方向的滤波器,
  • kernelY:Y方向的滤波器。
  • anchor:内核的基准点(锚点),其默认值为(-1,-1)代表内核基准点位于kernel的中心位置。基准点即卷积核中与进行处理的像素点重合的点,其位置必须在卷积核的内部。
  • delta:偏值,在计算结果中加上偏值。
  • borderType:像素外推法选择标志。默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。

对比一下filter2D()函数的原型:

void cv::filter2D(InputArray   src,
                  OutputArray  dst,
                  int          ddepth,
                  InputArray   kernel,
                  Point        anchor=Point(-1, -1),
                  double       delta=0,
                  int          borderType=BORDER_DEFAULT
                  )

 参数详解可以见:cv.filter2D() 函数详解https://blog.csdn.net/hysterisis/article/details/113097507 

可以发现sepFilter2D()可以输入两个方向的卷积核。而filter2D()函数需要通过滤波器尺寸区分滤波操作是作用在X还是Y方向上。

在此比较了filter2D()函数依次进行两个方向的滤波的结果与sepFilter2D()函数实现联合滤波的结果。同时将两个方向的滤波器核输入到sepFilter2D()中,验证两种结果是否相同。最后利用自定义的滤波器,对图像依次进行X方向滤波和Y方向滤波,查看滤波结果是否与使用联合滤波器的滤波结果一致。

实现代码如下:

//============================代码清单 *可分离图像滤波*==========================
 #include 
#include 

 using namespace cv;
 using namespace std;
int main()
 {
	      system("color F0");  //更改输出界面颜色
	     float points[25] = { 1,2,3,4,5,
	                          6,7,8,9,10,
	                          11,12,13,14,15,
	                          16,17,18,19,20,
	                          21,22,23,24,25 };
	     Mat data(5, 5, CV_32FC1, points);
	     //X方向、Y方向和联合滤波器的构建
		     Mat a = (Mat_(3, 1) << -1, 3, -1);
	     Mat b = a.reshape(1, 1);
	     Mat ab = a * b;
	     //验证高斯滤波的可分离性
		     Mat gaussX = getGaussianKernel(3, 1);
	     Mat gaussData, gaussDataXY;
	    GaussianBlur(data, gaussData, Size(3, 3), 1, 1, BORDER_CONSTANT);
	    sepFilter2D(data, gaussDataXY, -1, gaussX, gaussX, Point(-1, -1), 0, BORDER_CONSTANT);
	     //输入两种高斯滤波的计算结果
		cout << "gaussData=" << endl
		 << gaussData << endl << endl;
	    cout << "gaussDataXY=" << endl
	     << gaussDataXY << endl << endl;
	     //线性滤波的可分离性
		  Mat dataYX, dataY, dataXY, dataXY_sep;
	     filter2D(data, dataY, -1, a, Point(-1, -1), 0, BORDER_CONSTANT);
	     filter2D(dataY, dataYX, -1, b, Point(-1, -1), 0, BORDER_CONSTANT);
	     filter2D(data, dataXY, -1, ab, Point(-1, -1), 0, BORDER_CONSTANT);
	     sepFilter2D(data, dataXY_sep, -1, b, b, Point(-1, -1), 0, BORDER_CONSTANT);
	     //输出分离滤波和联合滤波的计算结果
		 cout << "dataY=" << endl
		 << dataY << endl << endl;
	     cout << "dataYX=" << endl
		 << dataYX << endl << endl;
	     cout << "dataXY=" << endl
		 << dataXY << endl << endl;
	     cout << "dataXY_sep=" << endl
		 << dataXY_sep << endl << endl;
	     //对图像的分离操作
		     Mat img = imread("D:\\folder\\图片素材\\1.tif");
	     if (img.empty())
		     {
		         cout << "请确认图像文件名称是否正确" << endl;
	         return -1;
		     }
	     Mat imgYX, imgY, imgXY;
	     filter2D(img, imgY, -1, a, Point(-1, -1), 0, BORDER_CONSTANT);
	     filter2D(imgY, imgYX, -1, b, Point(-1, -1), 0, BORDER_CONSTANT);
	     filter2D(img, imgXY, -1, ab, Point(-1, -1), 0, BORDER_CONSTANT);
	     imshow("img", img);
	     imshow("imgY", imgY);
	     imshow("imgYX", imgYX);
	     imshow("imgXY", imgXY);
	     waitKey(0);
	     return 0;
}

得出的数据矩阵滤波结果:

可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第1张图片

 可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第2张图片

 可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第3张图片                   可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第4张图片

 图像滤波结果:

可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第5张图片

可分离滤波:OpenCV4中的sepFilter2D()函数与filter2D()函数比较_第6张图片

你可能感兴趣的:(OpenCV,计算机视觉,opencv,c++,图像处理)