OpenCV每日函数 图像过滤模块 (21) Sobel函数

一、概述

        使用扩展的 Sobel 算子计算第一、第二、第三或混合图像导数。除一种情况外,在所有情况下,都使用 ksize×ksize 可分离核来计算导数。 当 ksize = 1 时,使用 3×1 或 1×3 内核(即不做高斯平滑)。 ksize = 1 只能用于第一个或第二个 x 或 y 导数。

        还有一个特殊的值 ksize = FILTER_SCHARR (-1) 对应于 3×3 Scharr 过滤器,它可能给出比 3×3 Sobel 更准确的结果。 Scharr 算子用于 x 导数,或转置用于 y 导数。        

        该函数通过将图像与适当的内核卷积来计算图像导数:

         Sobel 算子结合了高斯平滑和微分,因此结果或多或少能抵抗噪声。 大多数情况下,使用 (xorder = 1, yorder = 0, ksize = 3) 或 (xorder = 0, yorder = 1, ksize = 3) 调用该函数来计算第一个 x 或 y 图像导数。

        第一种情况对应于一个内核:

         第二种情况对应于一个内核:

二、Sobel函数

 1、函数原型

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

2、参数详解

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

三、OpenCV源码

1、源码路径

opencv\modules\imgproc\src\deriv.cpp

2、源码代码

void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
                int ksize, 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_MAKE_TYPE(ddepth, cn);
    _dst.create( _src.size(), dtype );

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

    Mat kx, ky;
    getDerivKernels( kx, ky, dx, dy, ksize, 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 && ksize == 3 &&
               (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(sobel, cv_hal_sobel, 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, ksize, scale, delta, borderType&~BORDER_ISOLATED);

    CV_OVX_RUN(true,
               openvx_sobel(src, dst, dx, dy, ksize, scale, delta, borderType))

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

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

四、效果图像示例

猜你喜欢

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