文章目录
- 前言
- 一、方框滤波
- 代码演示
- 二、源码分析
前言
前文我们了解了什么是图像平滑处理、图像滤波、邻域算子与线性邻域滤波、以及如何使用方框滤波,本文我们来分析一下方框滤波的源码。
一、方框滤波
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++】计算机视觉