2.7 Sobel导数

OpenCV函数

              Sobel(src_gray,grad_x/grad_y,ddepth,x_order,y_order,scale,delta,BORDER_DEFAULT )

              Scharr( )

边缘检测

为何要求导,如下图:

 假设需要检测图中的边缘,可以看到在边缘像素值显著改变,灰度值跃升

利用一阶导数可以清晰喊道跃升(高峰值)

从以上推论,检测边缘可以通过定位梯度值大于邻域的像素的方法找到(或者推广到大于一个阈值)

Sobel算子

Sobel算子是一个邻域微分算子(discrete differentiation operator)。它用来计算图像灰度函数的近似梯度。

Sobel算子结合了高斯平滑和微分求导。

计算

假设源图像为I

在两个方向求导

               水平变化:将I与一个奇数内核Gx进行卷积。比如,当内核大小为3时,Gx的计算结果为:

             垂直变化:将I与一个奇数大小的内核Gy进行卷积:

在图像的每一点,结合以上两个结果求出近似梯度。

当内核大小为3时,Sobel内核可能产生比较明显的误差(毕竟Sobel算子只求取了倒数的近似值),为解决这一个问题,

OpenCV提供了另一个Scharr函数,该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果更精确。

其内核为:

#include <opencv2/opencv.hpp>
#include <iostream>
#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
using namespace cv;

int main() {
    Mat src, src_gray;
    Mat grad;
    char* window_name =(char*)"Sobel Demo-Simple Edge Detector";
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;
    int c;

    //装载图像
    src = imread("D:\Pic\4141.jpg");
    if (!src.data) {
        return -1;
    }
    GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT);

    //转为灰度图
    cvtColor(src, src_gray, CV_RGB2GRAY);

    //创建显示窗口
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;

    //求x方向梯度
    Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
    convertScaleAbs(grad_x, abs_grad_x);

    //求y方向梯度
    Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
    convertScaleAbs(grad_y, abs_grad_y);

    //合并梯度
    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);

    imshow(window_name, grad);
    waitKey(0);

    return 0;
}
原文地址:https://www.cnblogs.com/zuoyou151/p/9721636.html