Sobel 边缘检测算子
转自:http://blog.csdn.net/xiaqunfeng123/article/details/17302003
Sobel 算子是一个离散微分算子 (discrete differentiation operator)。 它结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。
图像边缘,相素值会发生显著的变化了。表示这一改变的一个方法是使用 导数 。 梯度值的大变预示着图像中内容的显著变化。用更加形象的图像来解释,假设我们有一张一维图形。下图2中灰度值的”跃升”表示边缘的存在,图3中使用一阶微分求导我们可以更加清晰的看到边缘”跃升”的存在。

图1、lena.jpg

图2、像素一维图形

图3、一阶导数
具体是采用卷积的计算方法实现的。假设被作用的图像为
,在两个方向上求导:
水平变化求导:将
与一个奇数大小的内核
进行卷积。比如,当内核大小为3时,
的计算结果为图4a:
垂直变化求导:将 I 与一个奇数大小的内核
进行卷积。比如,当内核大小为3时,
的计算结果为图4b:
在图像的每一点,结合以上两个结果求出近似 梯度 ,如图4c:

图4a

图4b

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

两种实现版本:
C 版本:
cvSobel ( const cvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size =3 )
src, dst 分别是源图像和目标图像,xorder ,yorder – 分别为x,y方向导数运算参数,可取0,1,2 。aperture_size是方形滤波器的宽,是小于7的奇数。
具体见《Learning OpenCV》那本书,P.170页
下面是代码,比较简单:
#include <highgui.h>
#include <cv.h> using namespace cv;
using namespace std; int main(int argc, char ** argv)
{
IplImage* src, *dstx,*dsty,*dst; src = cvLoadImage( "car.png", );
dst = cvCreateImage( cvGetSize( src ), IPL_DEPTH_16S, );
dstx = cvCreateImage( cvGetSize( src ), IPL_DEPTH_16S, );
dsty = cvCreateImage( cvGetSize( src ), IPL_DEPTH_16S, ); cvNamedWindow( "src" );
cvNamedWindow( "sobel" ); cvShowImage( "src", src ); cvSobel( src, dstx, , , ); //sobel
cvSobel( src, dsty, , , );
cvAddWeighted(dstx,0.5,dsty,0.5,,dst); cvShowImage( "sobel", dst ); cvWaitKey();
cvReleaseImage( &src );
cvReleaseImage( &dst ); return ;
}
效果图:

C++版本:
先来看一下C++下 Sobel 的定义
C++: void Sobel( InputArray src , OutputArray dst, int ddepth, int dx, int dy, int ksize=3,
double scale=1,double delta=0,intborderType=BORDER_DEFAULT )
各参数的意义如下:
src – 输入图像。dst – 输出图像,与输入图像同样大小,拥有同样个数的通道。
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
当 ddepth为-1时, 输出图像将和输入图像有相同的深度。输入8位图像则会截取顶端的导数。
xorder – x方向导数运算参数。yorder – y方向导数运算参数。
ksize – Sobel内核的大小,可以是:1,3,5,7。 注意:只可以是小于7 的奇数
scale – 可选的缩放导数的比例常数。delta – 可选的增量常数被叠加到导数中。borderType – 用于判断图像边界的模式。
下面是程序:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h> using namespace cv;
using namespace std; int main( int argc, char** argv )
{
Mat src, src_gray;
Mat grad;
char* window_name = "求解梯度";
int scale = ;
int delta = ;
int ddepth = CV_16S; src = imread( "car.png" );
if( !src.data )
{
return -;
}
//高斯模糊
GaussianBlur( src, src, Size(,), , , BORDER_DEFAULT );
//转成灰度图
cvtColor( src, src_gray,CV_RGB2GRAY ); namedWindow( window_name, CV_WINDOW_AUTOSIZE ); Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
//x方向梯度计算
Sobel( src_gray, grad_x, ddepth, , , , scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
//y方向梯度计算
Sobel( src_gray, grad_y, ddepth, , , , scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
//加权和
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, , grad ); imshow( window_name, grad ); waitKey();
return ;
}
如果要用Scharr滤波器的话,把Sobel那行代码替换掉就好了:
Scharr( src_gray, grad_x, ddepth, , , scale, delta, BORDER_DEFAULT );
Scharr( src_gray, grad_x, ddepth, , , scale, delta, BORDER_DEFAULT );
效果图:


参考资料:http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html
转载请注明出处:http://blog.csdn.net/xiaqunfeng123
Sobel 边缘检测算子的更多相关文章
- 边缘检测算子和小波变换提取图像边缘【matlab】
Roberts边缘检测算子:根据一对互相垂直方向上的差分可用来计算梯度的原理,采用对角线方向相邻两像素之差. 小波变换的方法比较适用于展现夹带在正常信号中的瞬间反常现象,具有方向敏感性.所以可以边缘检 ...
- 边缘检测之Sobel检测算子
在讨论边缘算子之前,首先给出一些术语的定义: (1)边缘:灰度或结构等信息的突变处,边缘是一个区域的结束,也是另一个区域的开始,利用该特征可以分割图像. (2)边缘点:图像中具有坐标[x,y],且处在 ...
- 各种边缘检测算子特点比较(canny)
canny 最好.但是容易把噪点误判为边界.sobel prewitt log 效果差不多.prewitt比sobel 去噪效果好.roberts马马虎虎.适合什么图片那得看图片的噪点情况,一般can ...
- 图像特征提取:Sobel边缘检测
前言 点和线是做图像分析时两个最重要的特征,而线条往往反映了物体的轮廓,对图像中边缘线的检测是图像分割与特征提取的基础.文章主要讨论两个实际工程中常用的边缘检测算法:Sobel边缘检测和Canny边缘 ...
- Sobel边缘检测算法(转载)
转载请注明出处: http://blog.csdn.net/tianhai110 索贝尔算子(Sobel operator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰 ...
- OpenCV图像处理篇之边缘检测算子
OpenCV图像处理篇之边缘检测算子 转载: http://xiahouzuoxin.github.io/notes/ 3种边缘检测算子 一阶导数的梯度算子 高斯拉普拉斯算子 Canny算子 Open ...
- ###Canny边缘检测算子
开源中国. #@date: 2014-06-20 #@author: gerui #@email: forgerui@gmail.com 一.一阶微分边缘算子 1. 一阶微分边缘检测算子也称梯度边缘算 ...
- 数字图像处理之sobel边缘检测
在前两部文章介绍了几种边缘检测算法,和位图的内存结构.如果对前两篇文章已经理解透彻 了,那么本文将带你进入数字图像处理的世界. 本文通过C代码实现基本的sobel边缘检测,包括8个方向和垂直方向: 代 ...
- 基于FPGA的Sobel边缘检测的实现
前面我们实现了使用PC端上位机串口发送图像数据到VGA显示,通过MATLAB处理的图像数据直接是灰度图像,后面我们在此基础上修改,从而实现,基于FPGA的动态图片的Sobel边缘检测.中值滤波.Can ...
随机推荐
- https协议详解
HTTPS协议建立过程 1) 客户端首次发送请求时,由于客户端(浏览器等)对一些加解密算法的支持程度不一样,但是在TLS传输中必须使用相同的加解密算法,所以在TLS握手的阶段,客户端告诉服务器端自己支 ...
- OKR相关4本书,好书3本
最近几年看过4本OKR相关的书,有3本是4星.其中第一本是最近看的,剩下3本是2017年看的. OKR源自德鲁克和格鲁夫,跟谷歌是天作之合:4星|<这就是OKR> 4星|<OKR实践 ...
- 【English】20190328
Emotions情绪 [ɪ'moʊʃənz] Run Your Life for Teens影响你的青少年生活[ti:nz] Don't Let Your Emotions Run Your Lif ...
- 初学Python——协程
进程.线程和协程区分 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译为协同的例程,一般我们都简称为协程. 在linux系统中,线程就是轻量级的进程,而我们 ...
- error C2381: “exit”: 重定义;__declspec(noreturn) 不同
问题: error C2381: “exit” : 重定义:__declspec(noreturn) 不同 解决办法: 调换一下头文件的包含次序: #include <GL/glut.h> ...
- iOS开发基础-序列帧动画之Tom猫
新建一个Single View Application,向该工程中导入Tom猫的图片资源,本示例演示Tom猫喝牛奶的动作.图片的名字为 drink_00.jpg.drink_01.jpg.....dr ...
- Redis入门之增删改查等常用命令总结
Redis是用C语言实现的,一般来说C语言实现的程序"距离"操作系统更近,执行速度相对会更快. Redis使用了单线程架构,预防了多线程可能产生的竞争问题. 作者对于Redis源代 ...
- vue脚手架搭建项目引用百度地图--出坑
这是官网地址 https://dafrok.github.io/vue-baidu-map/#/zh/start/installation 需要声明注意的是 BaiduMap 组件容器本身是一个空的块 ...
- javascript高级排序算法之快速排序(快排)
javascript高级排序算法之快速排序(快排)我们之前讨论了javascript基本排序算法 冒泡排序 选择排序 插入排序 简单复习: 冒泡排序: 比较相邻的两个元素,如果前一个比后一个大,则交换 ...
- JAVA多线程-初体验
一.线程和进程 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程. 进程是所有线程的集合,每一个线程是进程中的一条执行路径. 二.为什么使用多线程,哪些场景下使用 多线程的好处是提高程序 ...