Sobel算子详解

1 、卷积应用-图像边缘提取

Sobel 算子是一个离散微分算子 (discrete differentiation operator)。 它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。边缘是什么 – 是像素值发生跃迁的地方,是图像的显著特征之一

图1中灰度值的”跃升”表示边缘的存在,图2中使用一阶微分求导我们可以更加清晰的看到边缘”跃升”的存在


测试图片

图一

图二

2 、解析

Sobel算子在x,y两个方向求导


image.png

最终结果

3 、整体代码测试

对于图像的处理,基本的步骤是这样的:
取得图像数据 —— 将图像进行平滑处理 —— 进行边缘检测,阈值分析 —— 进行形态学的操作 —— 获取某些特征点 —— 分析数据

CV_EXPORTS_W 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 );
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:int类型的,表示x方向的差分阶数,1或0
dy:int类型的,表示y方向的差分阶数,1或0
kSize:模板大小,前面虽然提到过,不过对于Sobel算子这里要补充下,这里的取值为1,3,5,7,当不输入的时候,默认为3。特殊的,当kSize = 1的时候,采用的模板为1*3或者3*1 而非平时的那些格式。
CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth,
                          int dx, int dy, double scale = 1, double delta = 0,
                          int borderType = BORDER_DEFAULT );
参数和Sobel算子一致,不过,该函数与Sobel的区别在于,Scharr仅作用于大小为3的内核。具有和sobel算子一样的速度,但结果更为精确
void cv::convertScaleAbs(
    cv::InputArray src, // 输入数组
    cv::OutputArray dst, // 输出数组
    double alpha = 1.0, // 乘数因子
    double beta = 0.0 // 偏移量
);
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv) {
    Mat src, dst;
    src = imread("D:\\2.jpg");
    if (!src.data) {
        printf("could not load image...\n");
        return -1;
    }

    char INPUT_TITLE[] = "input image";
    char OUTPUT_TITLE[] = "sobel-demo";
    namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
    //namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
    imshow(INPUT_TITLE, src);

    Mat gray_src;
    GaussianBlur(src, dst, Size(3, 3), 0, 0);
    cvtColor(dst, gray_src, CV_BGR2GRAY);
    //imshow("gray image", gray_src);

    Mat xgrad, ygrad;
    Scharr(gray_src, xgrad, CV_16S, 1, 0);
    Scharr(gray_src, ygrad, CV_16S, 0, 1);

    //Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
    //Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
    convertScaleAbs(xgrad, xgrad);
    convertScaleAbs(ygrad, ygrad);
    imshow("xgrad", xgrad);
    imshow("ygrad", ygrad);
    
    Mat xygrad = Mat(xgrad.size(), xgrad.type());
    printf("type : %d\n", xgrad.type());
    int width = xgrad.cols;
    int height = ygrad.rows;
    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            int xg = xgrad.at<uchar>(row, col);
            int yg = ygrad.at<uchar>(row, col);
            int xy = xg + yg;
            xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
        }
    }
    
    //addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
    imshow("xygrad", xygrad);

    waitKey(0);
    return 0;
}
Scharr
Sobel
xgrad+ygrad
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 文章目录 1、给定0-1矩阵,求连通域。 二值图像分析最重要的方法就是连通区域标记,它是所有二值图像分析的基础,它...
    王永迪阅读 6,414评论 0 3
  • 1、阈值分割 1.1 简介 图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成...
    Lornatang阅读 9,572评论 0 5
  • 1、阈值分割 1.1 简介 图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单、计算量小、性能较稳定而成...
    木夜溯阅读 22,919评论 9 15
  • sobel算子 定义 Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete different...
    SwiftBirds阅读 1,734评论 0 0
  • 2015-12-07 周一 霾 什么样的记忆最长久? 以前看过一个报道,关于这个问题科学家做过实验,结果发现人类视...
    韩日记阅读 287评论 0 2

友情链接更多精彩内容