对于做图像处理的工程师来说,Sobel非常熟悉且常用。但是当我们需要使用Sobel进行梯度运算,且希望得到“数学结果”(作为下一步运算的基础)而不是“图片效果”的时候,就必须深入了解Sobel的知识原理和OpenCV实现的细节(当然我们是OpenCV支持则)。这里对具体内容进行研究。

一、基本原理
一般来说,用来表示微分的最常用的算子是索贝尔(Sobel)算子,它可以实现任意阶导数和混合偏导数(例如: ∂2/∂x∂y)。

在x方向上用Sobel算子进行近似一阶求导的结果

Sobel算子效果,y方向近似一阶导数

OpenCV中给出了函数使用的定义

,      ,      ,      // 偏移
  int             borderType = cv::BORDER_DEFAULT  // 边框外推方法
);

1、其中src和dst是源图像和目标图像,可以通过指明参数ddepth来确定目标图像的深度或类型(如CV_32F)。举个例子,如果src是一幅8位图像,那么dst需要至少CV_16S的深度保证不出现溢出;

2、xorder和yorder是求导顺序,其取值范围为0、1和2。0表示在这个方向上不进行求导,那2代表什么?

3、ksize是一个奇数,表示了调用的滤波器的宽和高,目前最大支持到31;

4、阈值和偏移将在把结果存入dst前调用,这有助于你将求导结果可视化.borderType参数的功能与其他卷积操作完全一样。

上面有一个遗留问题,就是xorder(yorder)取2的时候代表什么?为此翻阅OpenCV源码

step1

step 2

step3

  )
        ksizeX ;
      )
        ksizeY ;
    CV_Assert( ktype , ktype, , , ktype, ,    )
        CV_Error( CV_StsOutOfRange, );
    CV_Assert( dx    );
    ; k ; k    )
            kerI[] ;
         )
        {
             )
                kerI[] , kerI[] , kerI[] ;
             )
                kerI[] , kerI[] , kerI[] ;
            ] , kerI[] , kerI[] ;
        }
        ] ;
            ; i ] ;
            ; i ; i];
                ; j ];
                    kerI[j] ; i ];
                ; j ] ] ]);
        . . ));
        temp.convertTo(*kernel, ktype, scale);
    }
}
其中
 

那么,可以看见,当order ==2 时候,生成了[1 -2 1]作为类似的模板,不管是什么,这个不是我想要的。

除了上面看到的,还可以发现同时设置xorder 和 yorder的时候,最后并没有看到相加的动作。而如果我们计算的结果是梯度场的时候,就不仅要算xorder,而且要算yorder,并且最后要把这两个结果求和。如果自己编码,那么可能如下:

) ) ) ) ) );
   ) )   ) );
   gradSum += (abs(vx)+abs(vy));        
 
二、定量研究
    如果直接用自然图片(比如lena),sobel计算之后可能啥都看不出来。为了定量研究,必须自己做图片。
    搞成这样,看的清楚
,),CV_8UC1,Scalar());
    line(matTst,Point(,),Point(,),Scalar());
    line(matTst,Point(,),Point(,),Scalar());
求一遍X方向的导数
,);
为什么要用16s?首先,所有的模式为CV_{8U,16S,16U,32S,32F,64F}C{1,2,3},其中U代表char,S代表short,F代表float,这个和c++里面一样;8只能是正数,16/32都可以是负数。所有的C1和C都是一样的,比如cv_8uc1 == cv_8u。那么原始图像是CV_8UC1,也就是CV_8U了,那么进行卷积计算,也就是原图像和
-1 0 1
-2 0 2
-1 0 1
或者类似的东西进行卷积计算,那么结果得到最大为 1*255+2*255+1*255 - 0  > 10000,最小的结果为 0 - 1*255+2*255+1*255  < -10000,所以要用CV_16SC1来保存,才合适。那么得到的结果为
​首先是有正有负,集中在中间区域值变化非常的大。取其中一个像素来看
中心位置 使用
-1 0 1
-2 0 2
-1 0 1
进行卷积,那么结果为
0*-1 + 255*0 + 0*1 +255*-2 +255*0 + 255*2 + 0 *-1 +255*0+0*1 = 0+0+0-255+0+255*2+0+0+0 = 0
其他结果也是,那么结果是符合卷积运算的。
计算Y方向卷积
,);
  
计算XY的卷积
  ,);
这个结果不是我想要的,我想要的是 (abs(vx)+abs(vy));    
那么这样实现
//求和

matXY = abs(matX) + abs(matY);

甚至可以进一步帮助显示
//方便显示
 normalize(matXY,matXY,0,255,NORM_MINMAX);

matXY.convertTo(matXY,CV_8UC1);

);都是不一样的
三、小结反思
应该说,Sobel大概能够做什么?这个很早之前就已经知道了。但是为什么能够达到这样的效果?这个问题,一直到我需要使用Sobel进行相关的数学计算的时候才能够搞明白。
掌握知识最后要归结到数学抽象层次,才能够算是彻底掌握。这是Sobel之外的获得。
感谢阅读至此,希望共同进步!

使用索贝尔(Sobel)进行梯度运算时的数学意义和代码实现研究的更多相关文章

  1. Excel—如何解决数组求和运算时行列不匹配产生的错误

    1.如下所示: 使用SUM对两个数组A1:B2,C1:E3进行运算时,由于行列不匹配返回了错误值. 2.可通过使用IFERROR进行解决. 对判断生成的错误值,通过用0替代进行解决. 3.除以上外,由 ...

  2. 使用C/C++,赋值运算时发生的转换

    使用C/C++,赋值运算时发生的转换主要有以下四种情况 一: 两边类型不同: 结果: 自动完成类型转换! 二: 长数赋给短数: 结果: 截取长数的低位送给短数! 三: 短数赋给长数: 结果: 原来是什 ...

  3. Double 类型运算时的精度问题

    double 类型运算时的 计算的精度不高,常常会出现0.999999999999999这种情况,那么就须要用BigDecimal   它是java提供的用来高精度计算的工具类 以下是对这个类的一个包 ...

  4. 细心!SQL语句进行运算时使用字符串时缺失精度的细节!

    昨天没有更新,特此来说明下原因,昨天回到家时已经甚晚,正逢公司这几天项目比较紧张(bug多,赶需求,看着bug单齐刷刷的转过来,心都颤抖了一下),没有及时准备素材,今天又加了一天班(现在还在公司,偷个 ...

  5. php运算时默认的类型转换

    php属于弱类型语言,使用数据时无需指定其数据类型.对于学C语言入门的我,刚刚接触时感觉很神奇,但是随之而来的也有烦恼. 总结一下php中默认的类型转换,按照运算符类型,只总结能够自动做类型转换的运算 ...

  6. Java中byte、short、char、int、long运算时自动类型转化问题

    -------------------------------------------------------------------------------------------------- ★ ...

  7. sql server 中进行除法运算时,如何得到结果是小数形式呢?

    我们正常进行除法运算时,sql默认是返回一个四舍五入的数 比如12除以5,17除以3 --算法1:返回结果:2 需要的是2.40 ) as 结果1 --算法2:返回结果:5 需要的是5.67 ) as ...

  8. 机器学习进阶-图像形态学操作-梯度运算 cv2.GRADIENT(梯度运算-膨胀图像-腐蚀后的图像)

    1.op = cv2.GRADIENT 用于梯度运算-膨胀图像-腐蚀后的图像 梯度运算:表示的是将膨胀以后的图像 - 腐蚀后的图像,获得了最终的边缘轮廓 代码: 第一步:读取pie图片 第二步:进行腐 ...

  9. C# 中的隐式类型转换(运算时的隐式转换)和显示类型转换

    区别: 隐式转换失败编译会报错. 显示转换有可能精度丢失. 根据项目的编译设置,显示转换溢出可能会报错,如果设置溢出且未使用checked检查,运行时如果发生溢出会产出未知的计算结果. 在数字运算时, ...

随机推荐

  1. iOS - UIScrollView xib添加约束的坑

    一.Storyboard中的UIScrollView使用自动布局 在使用storyboard和xib时,我们经常要用到ScrollView,还有自动布局AutoLayout,但是ScrollView和 ...

  2. 解决wamp、vertrigo等集成环境安装后apache不能启动的问题

    如果不是端口的问题,通常就是由于缺少vc库文件的支持,把vc2005.vc2008.vc2010抖安装一遍就呢过解决问题

  3. 【Java nio】buffer

    package com.slp.nio; import org.junit.Test; import java.nio.ByteBuffer; /** * Created by sanglp on 2 ...

  4. LeetCode——Lowest Common Ancestor of a Binary Search Tree

    Description: Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given no ...

  5. 配置maven使用nexus

    本文简单介绍使用配置maven使用nexus仓库,在团队中使用nexus,避免每个人都从中央仓库去下载依赖,节省带宽,提高下载速度,同时也减少了中央仓库的压力 配置在maven中使用nexus很简单( ...

  6. [SQL] 获取 Microsoft SQL Server 2008 的数据表结构

    then d.name else '' end , 表说明 then isnull(f.value,'') else '' end , 字段序号 = a.colorder , 字段名 = a.name ...

  7. 【office2010】office2010安装问题的解决方案。

    今天想在公司电脑上按上一个office2010,结果出现一个问题,导致研究了一下午才解决:现总结解决方案: 安装office 2010,提示需要安装MSXML版本6.10.1129.0组件.但是在网上 ...

  8. 前端模拟(mock)接口数据(koa)

    在前后端分离开发项目时,经常会有前后端进度不一致,可能前端界面开发已经完成,就等接口了,如果等接口出来再联调的话时间可能会来不及. 这个时候,前端就可以根据制定好的接口规范和接口文档来mock接口数据 ...

  9. [Nginx] – 安全优化 – 配置文件优化

    1.配置Nginx gzip压缩实现性能优化 1.Nginx gzip压缩功能介绍  Nginx gzip压缩模块提供了压缩文件内容的功能,用户请求的内容在发送出用客户端之前,Nginx服务器会根据一 ...

  10. SpringCloud 进阶之Zuul(路由网关)

    1. Zuul(路由网关) Zuul 包含了对请求的路由和过滤两个最主要的功能; 路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础; 过滤功能:负责对请求的处理过程进行干 ...