Sobel 导数

目标

本文档尝试解答如下问题:

  • 如何使用OpenCV函数 Sobel 对图像求导。
  • 如何使用OpenCV函数 Scharr 更准确地计算  核的导数。

原理

Note

以下内容来自于Bradski和Kaehler的大作: Learning OpenCV .

  1. 上面两节我们已经学习了卷积操作。一个最重要的卷积运算就是导数的计算(或者近似计算).

  2. 为什么对图像进行求导是重要的呢? 假设我们需要检测图像中的 边缘 ,如下图:

    你可以看到在 边缘 ,相素值显著的 改变 了。表示这一 改变 的一个方法是使用 导数 。 梯度值的大变预示着图像中内容的显著变化。

  3. 用更加形象的图像来解释,假设我们有一张一维图形。下图中灰度值的”跃升”表示边缘的存在:

  4. 使用一阶微分求导我们可以更加清晰的看到边缘”跃升”的存在(这里显示为高峰值)

  5. 从上例中我们可以推论检测边缘可以通过定位梯度值大于邻域的相素的方法找到(或者推广到大于一个阀值).

  6. 更加详细的解释,请参考Bradski 和 Kaehler的 Learning OpenCV 。

Sobel算子

  1. Sobel 算子是一个离散微分算子 (discrete differentiation operator)。 它用来计算图像灰度函数的近似梯度。
  2. Sobel 算子结合了高斯平滑和微分求导。

计算

假设被作用图像为 :

  1. 在两个方向求导:

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

    2. 垂直变化: 将:math:I 与一个奇数大小的内核  进行卷积。比如,当内核大小为3时,  的计算结果为:

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

    有时也用下面更简单公式代替:

Note

当内核大小为  时, 以上Sobel内核可能产生比较明显的误差(毕竟,Sobel算子只是求取了导数的近似值)。 为解决这一问题,OpenCV提供了 Scharr 函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确,其内核为:

关于( Scharr )的更多信息请参考OpenCV文档。在下面的示例代码中,你会发现在 Sobel 函数调用的上面有被注释掉的 Scharr 函数调用。 反注释Scharr调用 (当然也要相应的注释掉Sobel调用),看看该函数是如何工作的。

源码

  1. 本程序做什么?

    • 使用 Sobel算子 产生的输出图像上,检测到的亮起的 边缘 相素散布在更暗的背景中。
  2. 下面是本教程的源码,你也可以从 here 下载
#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; /// 装载图像
src = imread( argv[1] ); if( !src.data )
{ return -1; } GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT ); /// 转换为灰度图
cvtColor( src, src_gray, CV_RGB2GRAY ); /// 创建显示窗口
namedWindow( window_name, CV_WINDOW_AUTOSIZE ); /// 创建 grad_x 和 grad_y 矩阵
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y; /// 求 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 ); /// 求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 ); /// 合并梯度(近似)
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;
  2. 装载原图像 src:

    src = imread( argv[1] );
    
    if( !src.data )
    { return -1; }
  3. 第一步对原图像使用 GaussianBlur 降噪 ( 内核大小 = 3 )

    GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
    
  4. 将降噪后的图像转换为灰度图:

    cvtColor( src, src_gray, CV_RGB2GRAY );
    
  5. 第二步,在 x 和 y 方向分别”求导“。 为此,我们使用函数 Sobel :

    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 );
    /// 求 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_orderx 方向求导的阶数。
    • y_ordery 方向求导的阶数。
    • scaledelta 和 BORDER_DEFAULT: 使用默认值

    注意为了在 x 方向求导我们使用:  , . 采用同样方法在 y 方向求导。

  6. 将中间结果转换到 CV_8U:

    convertScaleAbs( grad_x, abs_grad_x );
    convertScaleAbs( grad_y, abs_grad_y );
  7. 将两个方向的梯度相加来求取近似 梯度 (注意这里没有准确的计算,但是对我们来讲已经足够了)。

    addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
    
  8. 最后,显示结果:

    imshow( window_name, grad );
    

结果

  1. 这里是将Sobel算子作用于 lena.jpg 的结果:

Sobel导数的更多相关文章

  1. 2.7 Sobel导数

    OpenCV函数 Sobel(src_gray,grad_x/grad_y,ddepth,x_order,y_order,scale,delta,BORDER_DEFAULT ) Scharr( ) ...

  2. OpenCV Sobel 导数

    #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #i ...

  3. opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测

    opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测 这章讲了 sobel算子 scharr算子 Laplacion拉普拉斯算子 图像深度问题 Canny检测 图像梯度 sobel算子 ...

  4. 2.opencv图像处理常用操作

    图像的平滑处理 平滑,也称 模糊, 平滑处理时需要用到一个滤波器 .滤波器想象成一个包含加权系数的窗口,这个加权系数也叫做核或者模版. // 图像平滑处理分而学之.cpp : 定义控制台应用程序的入口 ...

  5. 【OpenCV新手教程第14】OpenCVHough变换:霍夫变换线,霍夫变换圆汇编

    本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  6. SciPy模块应用

    1.图像模糊  图像的高斯模糊是非常经典的图像卷积例子.本质上,图像模糊就是将(灰度)图像I 和一个高斯核进行卷积操作:,其中是标准差为σ的二维高斯核.高斯模糊通常是其他图像处理操作的一部分,比如图像 ...

  7. [OpenCV-Python] OpenCV 中的图像处理 部分 IV (二)

    部分 IVOpenCV 中的图像处理 OpenCV-Python 中文教程(搬运)目录 16 图像平滑 目标 • 学习使用不同的低通滤波器对图像进行模糊 • 使用自定义的滤波器对图像进行卷积(2D 卷 ...

  8. [OpenCV-Python] OpenCV 中机器学习 部分 VIII

    部分 VIII机器学习 OpenCV-Python 中文教程(搬运)目录 46 K 近邻(k-Nearest Neighbour ) 46.1 理解 K 近邻目标 • 本节我们要理解 k 近邻(kNN ...

  9. OpenCV常用库函数[典]

    一.core 模块 1.Mat - 基本图像容器 Mat 是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是 ...

随机推荐

  1. synchronized加static区别

    在多线程中,在synchronise方法上加上static 表示的是类锁,锁住的是整个类.而synchroinized 锁住的是当前方法,当前对象.

  2. 在Linux中显示日历(cal)

    cal 2013    显示2013年整年日历 cal 7 2013  显示2013年 7 月 日历

  3. python 基础 9.11 更改数据

    #/usr/bin/python #-*- coding:utf-8 -*- #@Time   :2017/11/24 4:45 #@Auther :liuzhenchuan #@File   :更改 ...

  4. Ubuntu 12.04使用uginx+fastcgi-mono-server2部署asp.net 网站

    Ubuntu 12.04使用uginx+fastcgi-mono-server2部署asp.net 网站 1.安装nginx和mono-fastcgi-server2 sodu apt-get  in ...

  5. 【python】-- 类的反射

    反射 反射我们以后会经常用到,这个东西实现了动态的装配,通过字符串来反射类中的属性和方法 一.反射函数 1.hasarttr(obj,name_str) 作用:判断一个对象obj中是否有对应的name ...

  6. ASP跳出FOR循环

    由于ASP不能使用GOTO语句,我在FOR循环中加入一个FOR循环,若需要跳出,即退出最里面那个FOR循环. DEMO: <%dim aa = 0for i = 1 to 10    for j ...

  7. [ACM] FZU 2087 统计数边 (有多少边至少存在一个最小生成树里面)

    Problem Description 在图论中,树:随意两个顶点间有且仅仅有一条路径的图. 生成树:包括了图中全部顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的. 生成 ...

  8. 关于js sort排序方法

    sort() 方法用于对数组的元素进行排序. 语法:arrayObject.sort(sortby):参数sortby可选.规定排序顺序.必须是函数. 当方法不带参数的时候,将按照字符编码顺序进行排序 ...

  9. 机器学习Coursera学习总结

    Coursera上Andrew NG的机器学习实在是太火了,最近有时间花费了20来天的时间(每天3小时左右)终于学习完了全部的课程,总结如下: (1)适合入门,讲的比较基础,Andrew讲的很棒: ( ...

  10. 帝国cms数据表中文说明

    本文介绍下,帝国cms中各数据表的用途,有需要的朋友,参考下吧. 帝国cms各数据表及用途说明. phome_ecms_infoclass_news 新闻采集规则记录表 phome_ecms_info ...