参考网址:https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html

一.目标
在这篇指南中你将学会如何:

  • 使用OpenCV 中的Sobel 算子计算图像中的导数。
  • 使用OpenCV 中的Scharr 算子计算一个3*3大小的核的一个更精确的导数。

二.理论
说明:下面的解释说明来自由Bradski 和Kaehler写的《Learning OpenCV》

为什么计算图像中的衍生物的微积分十分重要?让我们想象如果我们想要检测到图像中出现的边缘,如下图:

你会发现在边缘处,像素点亮度出现显著的变化。使用导数能够很好的展现变化。梯度上的变化表现出图像中的较大的变化。

为了图示的更加清晰,假设我们有一个一维的图像,下面图表中亮度值的“跳跃”表现出边缘部分:

如果我们求第一次导数(事实上,图中表现为最大点),边缘部分的“跳跃”更能够表现出来。

所以,根据上述的解释说明,我们可以推导出一个在图像中检测边缘的方法,即通过确定一个梯度值大于领域中其他像素点(推广思路可改用阈值)的点的位置并表现在图像中。

更多的细节解释,可以参考Bradski 和Kaehler 的《Learning OpenCV》

Sobel 算子

  1. Sobel 算子是一个具体的差异化的算子。它用于计算图像中亮度梯度的估计值。
  2. Sobel 算子是将差异化和高斯滤波合并起来

处理
假设待处理的图像为I:

  1. 我们计算两个导数:
    a.水平变化:通过计算I 与核GxG_x的卷积,其中GxG_x是一个具有奇数边长的核。比如对于一个3*3的核,GxG_x可以像下面这样计算:
    GxG_x = ∣∣∣∣−1−2−1000+1+2+1∣∣∣∣ \begin{vmatrix} -1 & 0 & +1\\ -2 & 0 & +2\\-1 & 0 & +1 \end{vmatrix} * I
    b.竖直变化:通过计算I 与核GxG_x的卷积,其中GxG_x是一个具有奇数边长的核。比如对于一个3*3的核,GxG_x可以像下面这样计算:
    GyG_y = ∣∣∣∣−10+1−20+2−10+1∣∣∣∣ \begin{vmatrix} -1 & -2 & -1\\ 0 & 0 & 0\\+1 & +2 & +1 \end{vmatrix} * I
  2. 在图像中的每个像素点上,我们通过使用下述公式计算结果来获取该像素点的梯度的估计值:
    G = (Gx)2+(Gy)2−−−−−−−−−−−√\sqrt{(G_x)^2 + (G_y)^2}

尽管有时会使用下面的公式:
G = |GxG_x| + |GyG_y|

注意:当核的尺寸为3*3时,上面提到的Sobel 算子将会产生很明显的误差(毕竟,Sobel 算子是一种对导数的估计)。OpenCV 强调可以用Scharr 函数来处理使用3*3 的核产生的误差。这种方法和标准的Sobel 算子要快,同时更加准确,它是使用如下的形式的核:
GxG_x = ∣∣∣∣−3−10−3000+3+10+3∣∣∣∣ \begin{vmatrix} -3 & 0 & +3\\ -10 & 0 & +10\\-3 & 0 & +3 \end{vmatrix}
GyG_y = ∣∣∣∣−30+3−100+10−30+3∣∣∣∣ \begin{vmatrix} -3 & -10 & -3\\ 0 & 0 & 0\\+3 & +10 & +3 \end{vmatrix}

你可以在OpenCV 参考中找到更多有关Scharr 的相关信息。并且,在下面相同的代码中,你讲发现不仅有Sobel 算子还有注释过的Scharr 算子。取消注释将展现这个方法的工作原理。

代码:

  1. 这段代码用来干什么?
    使用Sobel 算子并且生成一张图作为输出,输出的图像将在深色的背景上用亮色表示找到的边缘。
  2. 下面展示指导代码:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>using namespace cv;/** @function main */
int main( int argc, char** argv )
{Mat src, src_gray;Mat grad;char* window_name = "Sobel Demo - Simple Edge Detector";int scale = 1;int delta = 0;int ddepth = CV_16S;int c;/// Load an imagesrc = imread( argv[1] );if( !src.data ){ return -1; }GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );/// Convert it to graycvtColor( src, src_gray, CV_BGR2GRAY );/// Create windownamedWindow( window_name, CV_WINDOW_AUTOSIZE );/// Generate grad_x and grad_yMat grad_x, grad_y;Mat abs_grad_x, abs_grad_y;/// Gradient X//Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_x, abs_grad_x );/// Gradient Y//Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_y, abs_grad_y );/// Total Gradient (approximate)addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );imshow( window_name, grad );waitKey(0);return 0;}

注释:

  1. 首先我们声明我们将要使用的变量:
Mat src, src_gray;
Mat grad;
char* window_name = "Sobel Demo - Simple Edge Detector";
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
  1. 然后加载我们的源图像:
src = imread( argv[1] );if( !src.data )
{ return -1; }
  1. 第一步,我们使用高斯滤波过滤噪点(核为3*3):
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
  1. 将过滤后的图像转换成灰度图:
cvtColor( src, src_gray, CV_BGR2GRAY );
  1. 下一步,我们在x 和y 方向上计算导数,我们按照下面的方式使用Sobel 算子:
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;/// Gradient X
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
/// Gradient Y
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );

函数中的参数:

  • src_gray :在我们的例子中是输入的图像,这里图像格式为CV_8U
  • grad_x | grad_y:输出的图像
  • ddepth :输出的图像的深度,我们将格式设置为CV_16S防止溢出。
  • x_order :x轴方向上的导数序列
  • y_order :y轴方向上的导数序列
  • scale ,delta 和BORDER_DEFAULT:使用默认值

注意到我们使用xorder=1x_{order} = 1和yorder=0y_{order} = 0我们在y轴方向上做类似操作。

  1. 将部分得到的结果重新转换为CV_8U
convertScaleAbs( grad_x, abs_grad_x );
convertScaleAbs( grad_y, abs_grad_y );
  1. 最后,我们通过两个方向的梯度估算每个像素点的梯度值(需要指出的是,这并不是最好的计算结果,但是的确符合我们的要求)
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
  1. 最后我们展示出处理后的结果:
imshow( window_name, grad );

结果:
下面是我们通过基本的检测得到的结果图:

【译】Sobel 算子文档相关推荐

  1. grid_sample 算子文档错误 和 使用异常

    我在转torch网络到mindspore过程中需要使用grid_sample算子,根据mindspore1.8版本文档,应该是这个:https://mindspore.cn/docs/zh-CN/r1 ...

  2. mongodb存list_查询 MongoDB 子文档的 List 字段

    [摘要] MongoDB 对于 List 结构中由若干字段组合而成的字符串数据有统计需求时,使用其 shell 脚本来实现有些复杂,而集算器 SPL 语言,则因拥有丰富的接口函数,实现就容易多了.若想 ...

  3. 一打开控制台窗口就中文输入_Lightconverse灯光设计软件中文电子文档教程免费分享...

     点击上面"灯光音响学习网" 即可免费订阅! Lightconverse是一款乌克兰的灯光设计软件,逼真度优于WYSIWYG,素材丰富.有强大的自定义灯库,让离线编程更加方便且不费 ...

  4. VC mfc 多文档程序更改子文档标题名

    VC++新建一个多文档MDI工程:输入工程名,mditest1:其他全部默认:生成项目,运行了看一下,如下: 现在要更改子文档标题:进入类向导,按下图,找到文档类的OnNewDocument函数,进入 ...

  5. Solr嵌套子文档的弊端以及一种替代方式

    背景:在考察了多种工具后,我们决定使用solr来作为多标签用户管理体系的查询方案. 原计划:电话,call客,跟进等等记录上报到kafka,然后通过flume+morphline录入到solr中.每一 ...

  6. 公文转成电子文档需要注意的事项

    事业单位之间会互相传发一些公文,接收单位会对公文进行分析,并给出解决方案,涉及到把公文转成电子文档,目前通过人工敲字实现. 转成电子文档后,需要做好版本管理,几月几号那个部门的文档,几月几日接受了什么 ...

  7. azure 入门_Azure Cosmos DB中的子文档入门

    azure 入门 As we've worked with Azure Cosmos DB, we've seen that we can store data within fields and t ...

  8. 如何插入电子签名_如何在电子文档上签名?可靠电子签名的特征有哪些?

    如何在电子文档上签名?可靠电子签名的特征有哪些? 在电子文档上签名很简单.举例来说, 如果我们想在word文件中插入签名,方法如下: 用扫描仪.相机或手机对手写签名进行扫描或拍摄,并通过PS或其他图片 ...

  9. 如何制作电子文档CHM(How to gernerate chm from assembly)

    2011-09-04 01:12:09|  分类: 默认分类 |  标签:chm  assembly  build  generate |字号大中小订阅 目的  大多数情况下,开发人员编写的代码最后都 ...

最新文章

  1. 使用class-dump导出其他应用头文件
  2. 1.1 《硬啃设计模式》 第1章 大话设计模式
  3. 一句SQL实现获取自增列操作
  4. 视频防抖 Opencv
  5. 我也来推荐一个强大的flash应用
  6. 【华为云技术分享】使用Python连接Kerberos的Presto
  7. 加州伯克利计算机专业录取条件,加州大学伯克利分校计算机专业申请要求
  8. 【区块链】区块链学习要点记录
  9. 后端系统开发利器,gflags概述
  10. 【自定义搜索引擎】Google Chrome管理搜索引擎和网站搜索
  11. 【CodeVS4093】EZ的间谍网络
  12. pytorch入门教程(一):Tensor###tensor好好好####
  13. 中医大2020年7月网考计算机应用基础,2020年7月网络教育统考《计算机应用基础》操作系统应用模拟题试卷2...
  14. 微服务下的几个难点问题及常见的解决方案
  15. 前端iframe标签介绍及使用
  16. 论文投稿指南——中文核心期刊推荐(新闻事业)
  17. 全网页都变灰了,这是怎么实现的?
  18. 【windows10】使用宽带拨号即PPPoE拨号上网
  19. 银行业灾备及业务连续性管理:从混沌走向清明
  20. STM32控制编码器电机实现【速度闭环控制】与【位置闭环控制】

热门文章

  1. GB28181监控视频统一汇聚平台LiveGBS将海康大华华为宇视等厂家监控设备统一接入后如何生成固定播放链接或者固定的流地址可以直接无插件播放或者拉取
  2. 笔记之零基础入门金融风控-贷款违约预测
  3. 国内虚拟主机与香港云主机的优劣势
  4. 07.rpx布局与样式导入
  5. 区块链技术最佳的监管方式是智能合约监管智能合约
  6. 【021】基于springboot的党务管理系统(含管理员、用户党支部三种身份(附源码数据库)
  7. 扫描文件存电子版方法
  8. C++ 开源库,很完整介绍【转】
  9. Eureka的InstanceInfoReplicator类(服务注册辅助工具)
  10. 什么软件可以代替sc防火墙_蜂蜜和糖稀有什么区别?糖稀可以用蜂蜜代替么?...