OpenCV每日函数 图像过滤模块 (19) Scharr函数

一、概述

        使用 Scharr 算子计算第一个 x 或 y 图像导数。该函数使用 Scharr 算子计算第一个 x 或 y 空间图像导数。 该调用

Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)

        相当于

Sobel(src, dst, ddepth, dx, dy, FILTER_SCHARR, scale, delta, borderType).

        当kernel的尺寸为3×3时,Sobel计算的结果不是很精确,为了得到更精确的计算结果常采用下图所示的Scharr kernel:

         Scharr变换可以看做是使用了Scharr核的Sobel变换,是一种经过改进的Sobel变换,同样也要区分x和y方向分开计算梯度。

        需要注意的是在计算Scharr梯度时,dx和dy要满足如下的关系(实际就是说要么dx=1 并且 dy=0;要么dx=0 并且 dy=1),否则会抛异常:

CV_Assert( dx >= 0 && dy >= 0 && dx+dy == 1 )

        也就是每次只能求x方向或者y方向单个方向的梯度,而且只能求一阶梯度,不像Sobel()中dx或dy可以设置为更大的值计算更高阶的梯度。

二、Scharr函数

1、函数原型

cv::Scharr (InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)

2、参数详解

src 输入图像。
dst 输出与 src 大小和通道数相同的图像。
ddepth 输出图像深度,见组合
dx 导数 x 的阶数。
dy 导数 y 的阶数。
scale 计算导数值的可选比例因子; 默认情况下,不应用缩放(有关详细信息,请参阅 getDerivKernels)。
delta 在将结果存储到 dst 之前添加到结果中的可选增量值。
borderType 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。

三、OpenCV源码

1、源码路径

opencv\modules\imgproc\src\deriv.cpp

2、源码代码

void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
                 double scale, double delta, int borderType )
{
    CV_INSTRUMENT_REGION();

    CV_Assert(!_src.empty());

    int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
    if (ddepth < 0)
        ddepth = sdepth;
    int dtype = CV_MAKETYPE(ddepth, cn);
    _dst.create( _src.size(), dtype );

    int ktype = std::max(CV_32F, std::max(ddepth, sdepth));

    Mat kx, ky;
    getScharrKernels( kx, ky, dx, dy, false, ktype );
    if( scale != 1 )
    {
        // usually the smoothing part is the slowest to compute,
        // so try to scale it instead of the faster differentiating part
        if( dx == 0 )
            kx *= scale;
        else
            ky *= scale;
    }

    CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
               (size_t)_src.rows() > ky.total() && (size_t)_src.cols() > kx.total(),
               ocl_sepFilter3x3_8UC1(_src, _dst, ddepth, kx, ky, delta, borderType));

    CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
               (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
               ocl_sepFilter2D(_src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType))

    Mat src = _src.getMat();
    Mat dst = _dst.getMat();

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

    CALL_HAL(scharr, cv_hal_scharr, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
             ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, dx, dy, scale, delta, borderType&~BORDER_ISOLATED);

    //CV_IPP_RUN_FAST(ipp_Deriv(src, dst, dx, dy, 0, scale, delta, borderType));

    sepFilter2D( src, dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
}

四、效果图像示例

原图

 

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125257111