转自:http://blog.csdn.net/yanmy2012/article/details/8110316

索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量

Sobel卷积因子为:

该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

具体计算如下:

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

通常,为了提高效率使用不开平方的近似值:

然后可用以下公式计算梯度方向:

若图像为:

则使用近似公式的计算的结果为:

Sobel算子另一种形式是各向同性Sobel(Isotropic Sobel)算子,也有两个,一个是检测水平边沿的,另一个是检测垂直边沿的 。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。将Sobel算子矩阵中的所有2改为根号2,就能得到各向同性Sobel的矩阵。

  由于Sobel算子是滤波算子的形式,用于提取边缘,可以利用快速卷积函数, 简单有效,因此应用广泛。美中不足的是,Sobel算子并没有将图像的主体与背景严格地区分开来,即Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。

参考:http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm

http://blog.csdn.NET/tianhai110/article/details/5663756

除此之外:由于基础核具有关于0,0,0所在的中轴正负对称,所以通过对基础核的旋转,和图像做卷积,可以获得灰度图的边缘图,同时消去旋转角方向+180°上的边缘,迭代多个方向即可消去多个方向的边缘,但是为消去的边缘会加倍。

基础核:

-1

0

1

-2

0

2

-1

0

1

旋转后的核(顺时针为正)

45°

-2

-1

0

-1

0

1

0

1

2

90°

-1

-2

-1

0

0

0

1

2

1

135°

0

-1

-2

1

0

-1

2

1

0

180°

1

0

-1

2

0

-2

1

0

-1

225°

2

1

0

1

0

-1

0

-1

-2

270°

1

2

1

0

0

0

-1

-2

-1

原图:

结果图如下,按0°,45°,90°,135°,180°,225°,270°排序

代码如下:

#include "cv.h"

#include "cxmisc.h"

#include "highgui.h"

#include <vector>

#include <string>

#include <algorithm>

#include <stdio.h>

#include <ctype.h>

#pragma comment(lib, "G:\\OpenCV-2.1.0\\vc2008\\lib\\cxcore210d.lib")

#pragma comment(lib, "G:\\OpenCV-2.1.0\\vc2008\\lib\\cv210d.lib")

#pragma comment(lib, "G:\\OpenCV-2.1.0\\vc2008\\lib\\highgui210d.lib")

//对不同深度图片和较大的图片进行放缩,以至于可以在显示器上完全显示

void ShowConvertImage(char name[200],IplImage* Image)

{

 cvNamedWindow(name,1);

 char savename[350];

 sprintf(savename,"%s.jpg",name);

 

 cvSaveImage(savename,Image);

    if(Image->width<1280)

 {

  

  if(Image->depth!=IPL_DEPTH_8U)

  {   

    IplImage* NormalizeImage=NULL;

    NormalizeImage=cvCreateImage(cvGetSize(Image),IPL_DEPTH_8U,1);

    cvConvertScale(Image,NormalizeImage,1,0);//将图转为0-256,用于图片显示,

    cvShowImage(name,NormalizeImage);

             cvReleaseImage(&NormalizeImage);

  }

  else

  {

             cvShowImage(name,Image);

  }

 }

 else

 {

  IplImage* ImageResize=cvCreateImage(cvSize(1280,Image->height/(Image->width/1280)),Image->depth ,Image->nChannels);

  cvResize(Image,ImageResize,1);

     if(ImageResize->depth!=IPL_DEPTH_8U)

  {   

    IplImage* NormalizeImage=NULL;

    NormalizeImage=cvCreateImage(cvGetSize(ImageResize),IPL_DEPTH_8U,1);

    cvConvertScale(Image,NormalizeImage,1,0);//将图转为0-256,用于图片显示,

    cvShowImage(name,NormalizeImage);

             cvReleaseImage(&NormalizeImage);

  }

  else

  {

             cvShowImage(name,ImageResize);

  }

 

  cvReleaseImage(&ImageResize); 

 }

 

}

//对较大的图片缩放,不然显示器分辨率不支持,只能部分显示,具体见http://blog.csdn.net/yanmy2012/article/details/8110516

int MaxImageWidth=2650;

float Scale=1;

int MinPicWidth=640;

int MinPicHeight=428*MinPicWidth/640;

int Maxradius_self=68*MinPicWidth/640;

int Minradius_self=50*MinPicWidth/640;

int Radius_dist=20*MinPicWidth/640;

int MaxPicWidth=MinPicWidth*Scale;

int MaxPicHeight=MinPicHeight*Scale;

void main()

{

IplImage * pictemp=NULL;

    IplImage * pic=NULL;

    char *imgpath="12.jpg"; 

    pictemp=cvLoadImage(imgpath,-1);///获取图片,原色获取

 //pictemp=cvLoadImage("IMG_02071.jpg",-1);///获取图片,原色获取

    /////////////////改变图片的像素大小

 

 

 if(pic!=NULL)

 {

  cvReleaseImage(&pic);

 }

   

 if(pictemp->width>MaxImageWidth)

 {

     pic=cvCreateImage(cvSize(MaxPicWidth,MaxPicHeight),pictemp->depth ,3);

   

     cvResize(pictemp,pic,CV_INTER_AREA );

 }

 else

 {

 

    pic=cvCloneImage(pictemp);

 

 }  

    ShowConvertImage("pic",pic);

    cvReleaseImage(&pictemp);

 

 IplImage * Gray_pic=cvCreateImage(cvGetSize(pic),pic->depth ,1);

 cvCvtColor(pic,Gray_pic, CV_BGR2GRAY );    //////将Image变成灰度图片保存在gray中

 cvCanny(Gray_pic,Gray_pic,50,150,3);

    IplImage * Result_pic=cvCreateImage(cvGetSize(pic),IPL_DEPTH_16S ,1);

   // IplImage * Result_pic=cvCreateImage(cvGetSize(pic),IPL_DEPTH_8U ,1);

CvMat *kernel=cvCreateMat(3,3,CV_32FC1);

 ///卷积核的初始化

 ////90度模板卷积核

 {

    cvSetReal2D(kernel,0,0, 1);  cvSetReal2D(kernel,0,1, 2); cvSetReal2D(kernel,0,2, 1);

    cvSetReal2D(kernel,1,0, 0);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2, 0);

 cvSetReal2D(kernel,2,0,-1);  cvSetReal2D(kernel,2,1,-2); cvSetReal2D(kernel,2,2,-1);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果90°",Result_pic);

////225度模板卷积核

 {

    cvSetReal2D(kernel,0,0, 2);  cvSetReal2D(kernel,0,1, 1); cvSetReal2D(kernel,0,2, 0);

    cvSetReal2D(kernel,1,0, 1);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2,-1);

 cvSetReal2D(kernel,2,0, 0);  cvSetReal2D(kernel,2,1,-1); cvSetReal2D(kernel,2,2,-2);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果225°",Result_pic);

 ////180度模板卷积核

 {

    cvSetReal2D(kernel,0,0, 1);  cvSetReal2D(kernel,0,1, 0); cvSetReal2D(kernel,0,2,-1);

    cvSetReal2D(kernel,1,0, 2);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2,-2);

 cvSetReal2D(kernel,2,0, 1);  cvSetReal2D(kernel,2,1, 0); cvSetReal2D(kernel,2,2,-1);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果180°",Result_pic);

 ////135度模板卷积核

 {

    cvSetReal2D(kernel,0,0, 0);  cvSetReal2D(kernel,0,1,-1); cvSetReal2D(kernel,0,2,-2);

    cvSetReal2D(kernel,1,0, 1);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2,-1);

 cvSetReal2D(kernel,2,0, 2);  cvSetReal2D(kernel,2,1, 1); cvSetReal2D(kernel,2,2, 0);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果135°",Result_pic);

 //90度模板卷积核

 {

    cvSetReal2D(kernel,0,0,-1);  cvSetReal2D(kernel,0,1,-2); cvSetReal2D(kernel,0,2,-1);

    cvSetReal2D(kernel,1,0, 0);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2, 0);

 cvSetReal2D(kernel,2,0, 1);  cvSetReal2D(kernel,2,1, 2); cvSetReal2D(kernel,2,2, 1);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果90°",Result_pic);

 ////45度模板卷积核

 {

    cvSetReal2D(kernel,0,0,-2);  cvSetReal2D(kernel,0,1,-1); cvSetReal2D(kernel,0,2, 0);

    cvSetReal2D(kernel,1,0,-1);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2, 1);

 cvSetReal2D(kernel,2,0, 0);  cvSetReal2D(kernel,2,1, 1); cvSetReal2D(kernel,2,2, 2);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果45°",Result_pic);

 ////0度模板卷积核

 {

    cvSetReal2D(kernel,0,0,-1);  cvSetReal2D(kernel,0,1, 0); cvSetReal2D(kernel,0,2, 1);

    cvSetReal2D(kernel,1,0,-2);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2, 2);

 cvSetReal2D(kernel,2,0,-1);  cvSetReal2D(kernel,2,1, 0); cvSetReal2D(kernel,2,2, 1);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(1,1));

    ShowConvertImage("卷积结果0°",Result_pic);

   

 //315度模板卷积核

 {

    cvSetReal2D(kernel,0,0, 0);  cvSetReal2D(kernel,0,1, 1); cvSetReal2D(kernel,0,2, 2);

    cvSetReal2D(kernel,1,0,-1);  cvSetReal2D(kernel,1,1, 0); cvSetReal2D(kernel,1,2, 1);

 cvSetReal2D(kernel,2,0,-2);  cvSetReal2D(kernel,2,1,-1); cvSetReal2D(kernel,2,2, 0);

 }

 ////////////进行卷积核计算

 cvFilter2D(Gray_pic,Result_pic,kernel,cvPoint(-1,-1));

    ShowConvertImage("卷积结果315",Result_pic);

    

 

 cvSobel(Gray_pic,Result_pic,0,1,3);

 ShowConvertImage("Sobel结果X=0,Y=1",Result_pic);

 cvSobel(Gray_pic,Result_pic,0,2,3);

 ShowConvertImage("Sobel结果X=0,Y=2",Result_pic);

 cvSobel(Gray_pic,Result_pic,1,0,3);

 ShowConvertImage("Sobel结果X=1,Y=0",Result_pic);

 cvSobel(Gray_pic,Result_pic,1,1,3);

 ShowConvertImage("Sobel结果X=1,Y=1",Result_pic);

 cvSobel(Gray_pic,Result_pic,1,2,3);

 ShowConvertImage("Sobel结果X=1,Y=2",Result_pic);

 cvSobel(Gray_pic,Result_pic,2,0,3);

 ShowConvertImage("Sobel结果X=2,Y=0",Result_pic);

 cvSobel(Gray_pic,Result_pic,2,1,3);

 ShowConvertImage("Sobel结果X=2,Y=1",Result_pic);

 cvSobel(Gray_pic,Result_pic,2,2,3);

 ShowConvertImage("Sobel结果X=2,Y=2",Result_pic);

cvWaitKey(0);

    cvReleaseImage(&Result_pic);

 cvReleaseImage(&Gray_pic);

 cvReleaseImage(&pic);

 cvReleaseMat(&kernel);

}

我对sobel算子的理解的更多相关文章

  1. 彻底理解数字图像处理中的卷积-以Sobel算子为例

    彻底理解数字图像处理中的卷积-以Sobel算子为例 作者:FreeBlues 修订记录 2016.08.04 初稿完成 概述 卷积在信号处理领域有极其广泛的应用, 也有严格的物理和数学定义. 本文只讨 ...

  2. EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子

    在上篇文章中我们了解了PlateLocate的过程中的所有步骤.在本篇文章中我们对前3个步骤,分别是高斯模糊.灰度化和Sobel算子进行分析. 一.高斯模糊 1.目标 对图像去噪,为边缘检测算法做准备 ...

  3. sobel算子

    #1,个人理解 网上查了很多资料,都说sobel算子是用来检测边缘的,分别给了两个方向上的卷积核,然后说明做法,就说这就是sobel算子.对于我个人来说,还有很多不明白的地方,所以理清下思路. #2, ...

  4. 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

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

  5. 对于Sobel算子的学习

    本来想说很多目前对于 Sobel 算子的认识,但最终还是觉得对于其掌握程度太低,没有一个系统的理解,远不足以写博客,但为了12月不至于零输出,还是决定把自己学习过程中找到的相关资料进行分享. 等到一月 ...

  6. [OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

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

  7. 学习 opencv---(11)OpenC 边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器

    本篇文章中,我们将一起学习OpenCV中边缘检测的各种算子和滤波器——Canny算子,Sobel算子,Laplace算子以及Scharr滤波器.文章中包含了五个浅墨为大家准备的详细注释的博文配套源代码 ...

  8. 边缘检测sobel算子

    sobel算子 - sophia_hxw - 博客园http://www.cnblogs.com/sophia-hxw/p/6088035.html #1,个人理解 网上查了很多资料,都说sobel算 ...

  9. sobel算子的一些细节

    1. 形式 Gy 上下颠倒的 (*A表示卷积图像,忽略先): 看得出来,sobel算子感觉并不统一,特别是方向,我们知道matlab的图像格式是,x轴从左到右,y轴从上到下,原点在左上角. 所以,第二 ...

随机推荐

  1. 部署mongodb中需要注意的调参

    部署mongodb的生产服务器,给出如下相关建议: 使用虚拟化环境: 系统配置 1)推荐RAID配置 RAID(Redundant Array of Independent Disk,独立磁盘冗余阵列 ...

  2. JavaWeb学习总结第一篇--初识JavaWeb

    JavaWeb学习总结(一)-- 初识JavaWeb 一:Web相关概念 Web程序也就是一般所说的网站,由服务器.客户端浏览器和网络组成.Web程序的好处就是使用简单,不需要安装.学习,有一台电脑. ...

  3. 【BZOJ4519】[Cqoi2016]不同的最小割 最小割树

    [BZOJ4519][Cqoi2016]不同的最小割 Description 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分 ...

  4. lvs虚拟服务器

    NAT模式 1.模拟环境: LVS服务器有两块网卡,连接外网(用户端)和内网(服务器),充当"交警"角色. 优点: 节省ip开销 缺点: LVS服务器负载过高,数据吞吐量降低 三台 ...

  5. 如何利用Windows System Image Manager制作一个answer file

    打开Windows System Image Manager 从菜单中创建一个新的Answer File 在窗体左下部的Windows Image处右键,选择菜单Select Windows Imag ...

  6. eclips 创建 maven项目

    Maven安装完成后我们就可以在Eclipse中新建自己的Maven项目了.我们可以在Eclipse中选择new一个project,在出现的对话框中选择Maven目录下的Maven Project. ...

  7. Android Weekly Notes Issue #317

    July 8th, 2018 Android Weekly Issue #317 本期主要内容包括"重磅"的Udacity放弃RN(其实是因为他们RN写的那个Feature不要了) ...

  8. iOS开发数据库-FMDB

    前言 FMDB是以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码:对比苹果自带的Core Data框架,更加轻量级和灵活:提供了多线程安全的数据库操 ...

  9. Trustzone——利用硬件对数据加密,秘钥存在芯片里

    我是看 https://zhuanlan.zhihu.com/p/26441212 这个文章知道trustzone自身会存储秘钥,这个秘钥可以来自用户指纹,也可以来自云端下发的key. Truztzo ...

  10. <%!%>声明的变量和在<%%>中声明的变量的区别

    通过写一个demo,查看Jsp_Servlet源码可知: <%!%>声明的变量是类似类的成员变量,<%%>中的变量是方法中的变量. 参考博客: http://www.cnblo ...