文章目录
前言一、方框滤波代码演示 二、源码分析
前言
前文我们了解了什么是图像平滑处理、图像滤波、邻域算子与线性邻域滤波、以及如何使用方框滤波,本文我们来分析一下方框滤波的源码。
一、方框滤波
void boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1, -1), boolnormalize=true, int borderType=BORDEX_DEFAULT)
其中,第一个参数表示输入的原图像,第二个参数表示目标图像,需要和原图像一样尺寸和类型,第三个参数表示输出图像的深度,-1代表使用原深度,即src.depth(),第四个参数表示 Size 类型的 ksize ,内核的大小。一般用 Size(w, h) 表示内核的大小,其中 w 为像素宽度,h 为像素的高度。Size(3, 3)的核大小。第五个参数表示锚点(平滑的那个点)。默认是 Point(-1, -1)。如果这个点的坐标是负值的话,就取核的中心为锚点。第六个参数六表示内核是否被其区域归一化了,第七个参数表示用于推断图像外部像素的某种边界模式。
代码演示
#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;int main(){ // 读取输入图像 Mat src = imread("D://cc.jpg", IMREAD_COLOR); if (src.empty()) { std::cout << "无法读取图像" << std::endl; return -1; } // 创建输出矩阵 Mat dst; // 应用方框滤波器 int ddepth = -1; // 使用与输入图像相同的深度 Size ksize(3, 3); // 内核的大小 Point anchor(-1, -1); // 内核中的锚点 bool normalize = true; // 归一化内核 int borderType = BORDER_DEFAULT; // 边界类型 boxFilter(src, dst, ddepth, ksize, anchor, normalize, borderType); // 显示结果 imshow("输入", src); imshow("输出", dst); waitKey(0); return 0;}
二、源码分析
//方框滤波器基类生成函数Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize, Point anchor, bool normalize, int borderType){ int sdepth = CV_MAT_DEPTH(srcType); // 获取输入矩阵的深度 int cn = CV_MAT_CN(srcType), sumType = CV_64F; // 获取输入矩阵的通道数,并设置默认的累加类型为CV_64F if (sdepth == CV_8U && CV_MAT_DEPTH(dstType) == CV_8U && ksize.width * ksize.height <= 256) sumType = CV_16U; // 如果输入矩阵和输出矩阵的深度都是CV_8U,并且滤波核的大小不超过256,则将累加类型设置为CV_16U else if (sdepth <= CV_32S && (!normalize || ksize.width * ksize.height <= (sdepth == CV_8U ? (1 << 23) : sdepth == CV_16U ? (1 << 15) : (1 << 16)))) sumType = CV_32S; // 如果输入矩阵的深度小于等于CV_32S,并且滤波核的大小不超过一定阈值,则将累加类型设置为CV_32S sumType = CV_MAKETYPE(sumType, cn); // 根据累加类型和通道数创建累加矩阵的数据类型 Ptr<BaseRowFilter> rowFilter = getRowSumFilter(srcType, sumType, ksize.width, anchor.x); // 获取行方向上的累加滤波器 Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType, dstType, ksize.height, anchor.y, normalize ? 1. / (ksize.width * ksize.height) : 1); // 获取列方向上的累加滤波器 return makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter, srcType, dstType, sumType, borderType); // 创建FilterEngine对象并返回}//方框滤波器实现void boxFilter(InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType){ Mat src = _src.getMat(); // 获取输入矩阵 int sdepth = src.depth(), cn = src.channels(); if (ddepth < 0) ddepth = sdepth; _dst.create(src.size(), CV_MAKETYPE(ddepth, cn)); // 创建输出矩阵 Mat dst = _dst.getMat(); if (borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0) { if (src.rows == 1) ksize.height = 1; // 如果输入矩阵的行数为1,则将滤波核的高度设置为1 if (src.cols == 1) ksize.width = 1; // 如果输入矩阵的列数为1,则将滤波核的宽度设置为1 } Point ofs; // 偏移量 Size wsz(src.cols, src.rows); // 窗口大小 if (!(borderType & BORDER_ISOLATED)) src.locateROI(wsz, ofs); // 定位输入矩阵的感兴趣区域(ROI) Ptr<FilterEngine> f = createBoxFilter(src.type(), dst.type(), ksize, anchor, normalize, borderType); // 创建方框滤波器 f->apply(src, dst, wsz, ofs); // 应用方框滤波器}
通过阅读方框滤波的部分源码,可以发现,boxFilter()函数在调用后先是进行了一系列的判断,确定图像属性,再通过调用createBoxFilter()函数来创建方框滤波器。
? 个人简介:CSDN「博客新星」TOP 10 , C/C++ 领域新星创作者? 作 者:锡兰_CC ❣️? 专 栏:【OpenCV • c++】计算机视觉? 若有帮助,还请关注➕点赞➕收藏,不行的话我再努努力???其他:
更多专栏订阅推荐:
? 【开卷数据结构】? 【备战蓝桥,冲击省一】 ? 从零开始的 c++ 之旅 ? 【OpenCV • c++】计算机视觉