方框滤波是均值滤波的一般形式,在均值滤波中,将滤波器中所有的像素值求和后的平均值作为滤波后结果,方框滤波也是求滤波器内所有像素值的之和,但是方框滤波可以选择不进行归一化,就是将所有像素值的和作为滤波结果,而不是所有像素值的平均值。

OpenCV 4中提供了boxFilter()函数实现方框滤波,该函数的函数原型在代码清单5-10中给出。

  •  
代码清单5-10 boxFilter()函数原型void cv::boxFilter(InputArray  src,                       OutputArray  dst,                       int  ddepth,                       Size  ksize,                       Point  anchor = Point(-1,-1),                       bool  normalize = true,                       int  borderType = BORDER_DEFAULT                        )
  • src:输入图像。
  • dst:输出图像,与输入图像具有相同的尺寸和通道数。
  • ddepth:输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围,具体的取值范围在表5-1给出,当赋值为-1时,输出图像的数据类型自动选择。
  • ksize:卷积核尺寸。
  • anchor:内核的基准点(锚点),其默认值为(-1,-1)代表内核基准点位于kernel的中心位置。基准点即卷积核中与进行处理的像素点重合的点,其位置必须在卷积核的内部。
  • normalize:是否将卷积核进行归一化的标志,默认参数为true,表示进行归一化。
  • borderType:像素外推法选择标志,取值范围在表3-5中给出,默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。

该函数的使用方式与均值滤波函数blur()几乎一样,但是该函数可以选择输出图像的数据类型,除此之外,该函数的第六个参数表示是否对滤波器内所有的数值进行归一化操作,参数默认状态下需要对滤波器内所有的数值进行归一化。此时,在不考虑数据类型的情况下,框滤波函数boxFilter()和均值滤波函数blur()会具有相同的滤波结果。

除了对滤波器内每个像素值直接求和外,OpenCV 4还提供了sqrBoxFilter()函数实现对滤波器内每个像数值的平方求和,之后根据输入参数选择是否进行归一化操作,该函数的函数原型在代码清单5-11中给出。

  •  
代码清单5-11 sqrBoxFilter()函数原型void cv::sqrBoxFilter(InputArray  src,                          OutputArray  dst,                          int  ddepth,                          Size  ksize,                          Point  anchor = Point(-1, -1),                          bool  normalize = true,                          int  borderType = BORDER_DEFAULT                           )

该函数是在boxFilter()函数功能基础上进行扩展功能,因此两者具有相同的输入参数需求,这里对函数的参数不再进行逐一解释。CV_8U数据类型的图像像素值从0到255,计算平方后数据会变得更大,即使归一化操作也不能保证像素值不会超过最大值,但是CV_32F数据类型的图像像素值是从0到1之间的小数,在0到1之间的数计算平方会变得更小,但是始终保持在0到1之间。因此该函数在处理图像滤波的任务时主要针对的是CV_32数据类型的图像,而且根据计算关系可知,在归一化后图像在变模糊的同时亮度也会变暗。

为了更加了解方框滤波的计算原理,清楚归一化操作和未归一化操作对滤波结果的影响,在代码清单5-12中给出了分别利用方框滤波处理矩阵数据和图像的示例程序。程序中我们创建了一个Mat类型的数据,之后用sqrBoxFilter()函数进行方框滤波,并在图5-13给出归一化后和未归一化后的结果,同时使用boxFilter()函数和sqrBoxFilter()对图像进行方框滤波操作,处理结果如图5-12中所示。

  •  
代码清单5-12 myBoxFilter.cpp图像方框滤波#include <opencv2\opencv.hpp>#include <iostream>
using namespace cv;using namespace std;
int main(){ Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH); //用于方框滤波的图像 if (equalLena.empty()) { cout << "请确认图像文件名称是否正确" << endl; return -1; } //验证方框滤波算法的数据矩阵 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); //将CV_8U类型转换成CV_32F类型 Mat equalLena_32F; equalLena.convertTo(equalLena_32F, CV_32F, 1.0 / 255); Mat resultNorm, result, dataSqrNorm, dataSqr, equalLena_32FSqr; //方框滤波boxFilter()和sqrBoxFilter() boxFilter(equalLena, resultNorm, -1, Size(3,3), Point(-1, -1), true); //进行归一化 boxFilter(equalLena, result, -1, Size(3, 3), Point(-1, -1), false); //不进行归一化 sqrBoxFilter(data, dataSqrNorm, -1, Size(3, 3), Point(-1, -1), true, BORDER_CONSTANT); //进行归一化 sqrBoxFilter(data, dataSqr, -1, Size(3, 3), Point(-1, -1), false, BORDER_CONSTANT); //不进行归一化 sqrBoxFilter(equalLena_32F, equalLena_32FSqr, -1, Size(3, 3), Point(-1, -1), true, BORDER_CONSTANT); //显示处理结果 imshow("resultNorm", resultNorm); imshow("result", result); imshow("equalLena_32FSqr", equalLena_32FSqr); waitKey(0); return 0;}
【从零学习OpenCV 4】方框滤波_方框滤波
图5-13 myBoxFilter.cpp程序中矩阵数据方框滤波结果
【从零学习OpenCV 4】方框滤波_方框滤波_02
图5-14 myBoxFilter.cpp程序中图像方框滤波结果
 
从零学习OpenCV 4往期推荐

【从零学习OpenCV 4】Windows系统中安装OpenCV 4

【从零学习OpenCV 4】Ubuntu系统中安装OpenCV 4

【从零学习OpenCV 4】opencv_contrib扩展模块的安装

【从零学习OpenCV 4】Mat类介绍

【从零学习OpenCV 4】Mat类构造与赋值

【从零学习OpenCV 4】Mat类支持的运算

【从零学习OpenCV 4】这4种读取Mat类元素的的方法你都知道么?

【从零学习OpenCV 4】namedWindow函数&imshow函数的使用

【从零学习OpenCV 4】颜色模型与转换

【从零学习OpenCV 4】多通道分离与合并

【从零学习OpenCV 4】图像像素统计

【从零学习OpenCV 4】两图像间的像素操作

【从零学习OpenCV 4】图像二值化

【从零学习OpenCV 4】LUT查找表

【从零学习OpenCV 4】图像仿射变换

【从零学习OpenCV 4】图像透视变换

【从零学习OpenCV 4】极坐标变换

【从零学习OpenCV 4】绘制几何图形

【从零学习OpenCV 4】图像金字塔

【从零学习OpenCV 4】创建图像窗口滑动条

【从零学习OpenCV 4】鼠标响应

【从零学习OpenCV 4】图像直方图绘制

【从零学习OpenCV 4】直方图归一化

【从零学习OpenCV 4】直方图比较

【从零学习OpenCV 4】直方图均衡化

【从零学习OpenCV 4】直方图匹配

【从零学习OpenCV 4】图像卷积

【从零学习OpenCV 4】图像中添加椒盐噪声

【从零学习OpenCV 4】图像中添加高斯噪声

  ……

 

【从零学习OpenCV 4】方框滤波_方框滤波_03