OpenCV学习笔记(八)之边缘检测算子上篇(Sobel算子实现原理及源码分析)

本文主要介绍了OpenCV中Sobel算子的使用,包括函数介绍、实现流程和源码分析。Sobel算子用于检测图像边缘,通过设置dx和dy参数可以计算X或Y方向的导数。在OpenCV中,Sobel函数根据ddepth参数选择不同的输出精度,并可选择Scharr内核。最后,文章提到了Sobel算子的实现涉及到的sepFilter2D函数进行卷积滤波。

  OpenCV中封装了很多函数,一般我们只需要调用它提供的API函数即可实现各种图像处理操作,如滤波、边缘检测等,这对我们项目开发来说是非常方便的。但是一个优秀的算法工程师必然也是一位优秀的程序员,因为就算你熟知各种算法的原理,但是不知道怎么实现也是不行的,(举个例子:假如你是一位销售员,你脑袋里面有很多非常棒的点子,可是你不知道怎么将它表述出来,那么到最后你依然还是一位处在销售底层的人。) 只有既熟悉原理又会用代码将大脑中好的想法实现,那才是优秀的算法工程师。当然,要完全靠自己从头实现OpenCV中的各种函数也是不现实的,就算你有那能力但是也不一定会有那么多精力。因此折中一点,至少要让自己能看懂OpenCV中各种算法的实现代码(比如说你做人脸识别,至少也要能完全理解SIFT是怎么实现的吧),这样如果有一天需要自己开发新的或者优化现有算法,那对自己的帮助就很大了。

一、Sobel算子函数介绍

OpenCV中Sobel算子被封装在

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 );

这个函数里面,其中:

  1. src表示输入原图像;
  2. dst表示输出目标图像;
  3. ddepth表示用来度量每一个像素中每一个通道的精度,但它本身与图像的通道数无关!depth数值越大,精度越高。在Opencv中,Mat.depth()得到的是一个0~6的数字,分别代表不同的位数,对应关系如下:
    enum{CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6},ddepth 由于Sobel运算时可能会出现比较大的值,因此取值方式有以下几种:
  • 若 ddepth = CV_8U, 取 ddepth = -1 或 CV_16S 或 CV_32F 或 CV_64F
  • 若 ddepth = CV_16U, 或 CV_16S, 取 ddepth = -1 或 CV_32F 或 CV_64F
  • 若 ddepth = CV_32F, 取 ddepth = -1 或 CV_32F 或 CV_64F
  • 若 ddepth = CV_64F, 取 ddepth = -1 或 CV_64F
  • 若 ddepth = -1, 代表输出图像与输入图像相同的深度。
  1. dx表示对X方向进行求导的差分阶数;
  2. dy表示对Y方向进行求导的差分阶数;(其中, dx=1,dy=0,表示计算X方向的导数,检测出的是垂直方向上的边缘;dx=0,dy=1,表示计算Y方向的导数,检测出的是水平方向上的边缘。)
  3. ksize 表示卷积核的大小,只能为奇数 1、3、5、7 等,特殊情况:当ksize <= 0 时,采用的模板为3 * 3 的Scharr内核。
  4. scale 表示缩放尺度,默认为1。
  5. delta:默认0。(还不知道有什么作用,猜测是用来放大的)
    int borderType:滤波时填充的图像边界类型,有如下几种:
enum {
   
    BORDER_REPLICATE=IPL_BORDER_REPLICATE,
	   BORDER_CONSTANT=IPL_BORDER_CONSTANT,
       BORDER_REFLECT=IPL_BORDER_REFLECT, 
       BORDER_WRAP=IPL_BORDER_WRAP,
       BORDER_REFLECT_101=IPL_BORDER_REFLECT_101, 
       BORDER_REFLECT101=BORDER_REFLECT_101,
       BORDER_TRANSPARENT=IPL_BORDER_TRANSPARENT,
       BORDER_DEFAULT=BORDER_REFLECT_101, 
       BORDER_ISOLATED=16 };

默认值为BORDER_DEFAULT,具体边界定义方法参考图像剪切的扩展和高级用法:任意裁剪,边界扩充这篇博客,里面对图像边界的扩充说得很详细。

二、Sobel算子实现流程

在这里插入图片描述

三、Sobel算子源码分析

openCV中Sobel函数定义如下:

void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
                int ksize, double scale, double delta, int borderType )
{
   
   
    Mat src = _src.getMat();
    if (ddepth < 0)
        ddepth = src.depth();
    _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
    Mat dst = _dst.getMat();

#ifdef HAVE_TEGRA_OPTIMIZATION
    if (scale == 1.0 && delta == 0)
    {
   
   
        if (ksize == 3 && tegra::sobel3x3(src, dst, dx, dy, borderType))
            return;
        if (ksize == -1 && tegra::scharr(src, dst, dx, dy, borderType))
            return;
    }
#endif

#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
    if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1)
    {
   
   
        if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale))
            return;
    }
#endif
    int ktype = std::max(CV_32F, std:
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值