OpenCV每日函数 图像过滤模块 (20) sepFilter2D函数

一、概述

        该函数对图像应用可分离的线性滤波器。也就是说,首先,每一行 src 都用一维内核 kernelX 过滤。 然后,结果的每一列都用一维内核 kernelY 过滤。 由 delta 移位的最终结果存储在 dst 中。

        假设图像大小{\displaystyle X\times Y}正在通过一个大小可分离的过滤器{\displaystyle J\times K}. 图像本身是不可分离的。如果使用直接卷积方法计算结果而不利用滤波器​​的可分离性,这将需要大约{\displaystyle XYJK}乘法和加法。如果考虑到过滤器的可分离性,过滤可以分两步进行。第一步将有{\displaystyle XYJ}乘法和加法,第二步将有{\displaystyle XYK}, 总共有{\displaystyle XYJ+XYK}或者{\displaystyle XY(J+K)}乘法和加法。下图给出了直接卷积和可分离卷积的计算复杂度比较:

二、sepFilter2D函数

1、函数原型

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

2、参数详解

src 源图像。
dst 与 src 大小和通道数相同的目标图像。
ddepth 目标图像深度,请参阅组合
kernelX 过滤每一行的系数。
kernelY 过滤每一列的系数。
anchor 内核中的锚点位置。 默认值 (-1,-1) 表示锚点位于内核中心。
delta 在存储过滤结果之前添加到过滤结果中的值。
borderType 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。

三、OpenCV源码

1、源码路径

opencv\modules\imgproc\src\filter.dispatch.cpp

2、源码代码

void sepFilter2D(InputArray _src, OutputArray _dst, int ddepth,
                 InputArray _kernelX, InputArray _kernelY, Point anchor,
                 double delta, int borderType)
{
    CV_INSTRUMENT_REGION();

    CV_Assert(!_src.empty());
    CV_Assert(!_kernelX.empty());
    CV_Assert(!_kernelY.empty());

    CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() >= _kernelY.total() && (size_t)_src.cols() >= _kernelX.total(),
               ocl_sepFilter2D(_src, _dst, ddepth, _kernelX, _kernelY, anchor, delta, borderType))

    Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat();

    if( ddepth < 0 )
        ddepth = src.depth();

    _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
    Mat dst = _dst.getMat();

    Point ofs;
    Size wsz(src.cols, src.rows);
    if( (borderType & BORDER_ISOLATED) == 0 )
        src.locateROI( wsz, ofs );

    CV_Assert( kernelX.type() == kernelY.type() &&
               (kernelX.cols == 1 || kernelX.rows == 1) &&
               (kernelY.cols == 1 || kernelY.rows == 1) );

    Mat contKernelX = kernelX.isContinuous() ? kernelX : kernelX.clone();
    Mat contKernelY = kernelY.isContinuous() ? kernelY : kernelY.clone();

    hal::sepFilter2D(src.type(), dst.type(), kernelX.type(),
                     src.data, src.step, dst.data, dst.step,
                     dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
                     contKernelX.data, kernelX.cols + kernelX.rows - 1,
                     contKernelY.data, kernelY.cols + kernelY.rows - 1,
                     anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED);
}

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125257355
今日推荐