zoukankan      html  css  js  c++  java
  • opencv —— Sobel 一阶导数算子、Scharr 滤波器 一阶导数用于边缘检测

    sobel 算子的基本概念

    sobel 算子是一个主要用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导,用于计算图像灰度函数的近似梯度。

    其基础来自于一个事实,即在边缘部分,像素值出现“跳跃”或者较大的变化。如果在此边缘部分求取一阶导数,会看到极值的出现。正如下图所示:

    Previous theory 

    sobel 算子的计算过程

    (1)分别在 x 和 y 两个方向求导

    x 方向求导:将源图像与 Gx 进行卷积。对竖线敏感(导数大),横线不敏感(导数小)。

    y 方向求导:将源图像与 Gy 进行卷积。对竖线不敏感(导数小),横线敏感(导数大)。

    (2)对于图像的每一点,结合以上两个结果求出近似梯度

    可以简化成:

     

    Sobel 函数

    void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT);
    • src,输入图像,填 Mat 类型即可。
    • dst,输出图像,需要和源图像有一样的尺寸和类型。
    • ddepth,输出图像的深度,满足下列要求:

    src.depth() = CV_8U, ddepth = -1 / CV_16S / CV_32F / CV_64F

    src.depth() = CV_16U / CV_16S, ddepth = -1 / CV_32F / CV_64F

    src.depth() = CV_32F, ddepth = -1 / CV_32F / CV_64F

    src.depth() = CV_64F, ddepth = -1 / CV_64F

    • dx,x 方向上导数的阶数,只能是 0、1、2。若求 x 方向上的一阶导数,dx = 1,dy = 0。
    • dy,y 方向上导数的阶数,只能是 0、1、2。若求 y 方向上的一阶导数,dx = 0,dy = 1。
    • ksize,默认值为 3,表示 sobel 核的大小,必须取 1、3、5、7。
    • scale,计算导数值的缩放因子,默认值为 1,表示默认情况下不进行缩放。
    • delta,输出梯度 = scale * G + delta。
    • borderType,Gx 和 Gy 都有一定大小,边缘会处理不到,需要进行边缘扩展。这个参数指定边缘扩充类型。

     一般情况下,都是使用 ksize×ksize 内核来计算导数的,然而,当 ksize = 1 时,会使用 3×1、1×3 的内核。这种情况下,并没有进行高斯平滑操作。

    代码示例:

    #include<opencv.hpp>
    using namespace cv;
    int main() {
        Mat src = imread("C:/Users/齐明洋/Desktop/证件照/7.jpg");
        GaussianBlur(src, src, Size(3, 3), 0, 0);
        imshow("src", src);
    
        Mat gray, x_img, y_img, sobel_img;
        cvtColor(src, gray, COLOR_BGR2GRAY);
        Sobel(gray, x_img, -1, 1, 0, 3);
        imshow("x_img", x_img);
        Sobel(gray, y_img, -1, 0, 1, 3);
        imshow("y_img", y_img);
    
        addWeighted(x_img, 1, y_img, 1, 0, sobel_img);
    //https://www.cnblogs.com/bjxqmy/p/11986135.html imshow(
    "sobel_img", sobel_img); waitKey(0); }

    效果演示:

     

    补充说明:当内核大小为 3×3 时,sobel 内核可能产生比较明显的误差,毕竟 sobel 算子只是求取了导数的近似值而已。为解决这一问题,OpenCV 提供了 Scharr 函数,但该函数仅作用于 3×3 的内核。该函数的运算与 Sobel 函数一样快,但结果更精确,其内核为

    借鉴博客:https://www.cnblogs.com/wxl845235800/p/7700887.html

    https://www.cnblogs.com/sevenyuan/p/7874344.html

  • 相关阅读:
    VS2013 自动添加头部注释 -C#开发
    在调用Response.End()时,会执行Thread.CurrentThread.Abort()操作
    React
    WebApi基础
    wcf
    memcached系列
    Ioc容器Autofac系列
    使用TortoiseSVN创建版本库
    使用libcurl 发送post请求
    值得推荐的C/C++框架和库
  • 原文地址:https://www.cnblogs.com/bjxqmy/p/12325852.html
Copyright © 2011-2022 走看看