当前位置:首页 » 《我的小黑屋》 » 正文

【OpenCV • c++】图像平滑处理(2) —— 方框滤波 | 盒滤波 | 源码分析

20 人参与  2024年05月12日 11:50  分类 : 《我的小黑屋》  评论

点击全文阅读


文章目录

前言一、方框滤波代码演示 二、源码分析

前言

  前文我们了解了什么是图像平滑处理、图像滤波、邻域算子与线性邻域滤波、以及如何使用方框滤波,本文我们来分析一下方框滤波的源码。

一、方框滤波

 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++】计算机视觉

点击全文阅读


本文链接:http://zhangshiyu.com/post/107398.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1