sobel算子原理、卷积核滤波原理与实现

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

Sobel卷积因子为:

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

具体计算如下:

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

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

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

若图像为:

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

    

举个例子吧。

X

点以

Sobel

方式求导数

Δ

X=1×50+2×30+1×50-

(1×50+2×30+1×50)

=0

这样可以看出这个点不是

边界。

 

    

好了,了解了基本理论之后,我们看看

OpenCv

下的

Sobel

函数吧,

void 

cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int 

aperture_size=3 

);src

:输入图像;

dst

:输出图像;

xorder

方向上的差分

阶数;

yorder

方向上的差分阶数;

aperture_size 

扩展

 Sobel 

核的大小

(既

窗口阶数),必须是

 1

(注意这是一个

3×1

1×3

向量而不是一个方阵)

3, 

 7

    

举个例子吧。

X

点以

Sobel

方式求导数

Δ

X=1×50+2×30+1×50-

(1×50+2×30+1×50)

=0

这样可以看出这个点不是

边界。

 

    

好了,了解了基本理论之后,我们看看

OpenCv

下的

Sobel

函数吧,

void 

cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int 

aperture_size=3 

);src

:输入图像;

dst

:输出图像;

xorder

方向上的差分

阶数;

yorder

方向上的差分阶数;

aperture_size 

扩展

 Sobel 

核的大小

(既

窗口阶数),必须是

 1

(注意这是一个

3×1

1×3

向量而不是一个方阵)

3, 

 7



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°上的边缘,迭代多个方向即可消去多个方向的边缘,但是为消去的边缘会加倍。

基础核:

0°

-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);


}

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习是一种人工智能(AI)的子领域,致力于研究如何利用数据和算法让计算机系统具备学习能力,从而能够自动地完成特定任务或者改进自身性能。机器学习的核心思想是让计算机系统通过学习数据中的模式和规律来实现目标,而不需要显式地编程。 机器学习应用非常广泛,包括但不限于以下领域: 图像识别和计算机视觉: 机器学习在图像识别、目标检测、人脸识别、图像分割等方面有着广泛的应用。例如,通过深度学习技术,可以训练神经网络来识别图像中的对象、人脸或者场景,用于智能监控、自动驾驶、医学影像分析等领域。 自然语言处理: 机器学习在自然语言处理领域有着重要的应用,包括文本分类、情感分析、机器翻译、语音识别等。例如,通过深度学习模型,可以训练神经网络来理解和生成自然语言,用于智能客服、智能助手、机器翻译等场景。 推荐系统: 推荐系统利用机器学习算法分析用户的行为和偏好,为用户推荐个性化的产品或服务。例如,电商网站可以利用机器学习算法分析用户的购买历史和浏览行为,向用户推荐感兴趣的商品。 预测和预测分析: 机器学习可以用于预测未来事件的发生概率或者趋势。例如,金融领域可以利用机器学习算法进行股票价格预测、信用评分、欺诈检测等。 医疗诊断和生物信息学: 机器学习在医疗诊断、药物研发、基因组学等领域有着重要的应用。例如,可以利用机器学习算法分析医学影像数据进行疾病诊断,或者利用机器学习算法分析基因数据进行疾病风险预测。 智能交通和物联网: 机器学习可以应用于智能交通系统、智能城市管理和物联网等领域。例如,可以利用机器学习算法分析交通数据优化交通流量,或者利用机器学习算法分析传感器数据监测设备状态。 以上仅是机器学习应用的一部分,随着机器学习技术的不断发展和应用场景的不断拓展,机器学习在各个领域都有着重要的应用价值,并且正在改变我们的生活和工作方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值