Sobel算子及cvSobel.doc_第1页
Sobel算子及cvSobel.doc_第2页
Sobel算子及cvSobel.doc_第3页
Sobel算子及cvSobel.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Sobel算子及cvSobel(2010-11-28 23:16:15)转载标签: opencvsobel算子cvsobel分类: OpenCV 由于项目里要用到边缘检测,所以今天研究了一下最简单的梯度的方法。 首先,我们来开一下计算机是如何检测边缘的。以灰度图像为例,它的理论基础是这样的,如果出现一个边缘,那么图像的灰度就会有一定的变化,为了方便假设由 黑渐变为白代表一个边界,那么对其灰度分析,在边缘的灰度函数就是一个一次函数y=kx,对其求一阶导数就是其斜率k,就是说边缘的一阶导数是一个常数, 而由于非边缘的一阶导数为零,这样通过求一阶导数就能初步判断图像的边缘了。通常是X方向和Y方向的导数,也就是梯度。理论上计算机就是通过这种方式来获 得图像的边缘。 但是,具体应用到图像中你会发现这个导数是求不了的,因为没一个准确的函数让你去求导,而且计算机在求解析解要比求数值解麻烦得多,所以就想到了一种替代 的方式来求导数。就是用一个33的窗口来对图像进行近似求导。拿对X方向求导为例,某一点的导数为第三行的元素之和减去第一行元素之和,这样就求得了某 一点的近似导数。其实也很好理解为什么它就近似代表导数,导数就代表一个变化率,从第一行变为第三行,灰度值相减,当然就是一个变化率了。这就是所谓的 Prewitt算子。这样近似X方向导数就求出来了。Y方向导数与X方向导数求法相似,只不过是用第三列元素之和减去第一列元素之和。X方向和Y方向导数 有了,那么梯度也就出来了。这样就可以找出一幅图中的边缘了。 还有一个问题,由于求的是33中心点的导数,所以给第二列加了一个权重,它的权重为2,第一列和第三列的权重为1,好了,这就是Sobel算子了。相比Prewitt算子,Sobel的抗噪能力更强。如图所示:这样,中心点的X方向导数就求出来了。 举个例子吧。,X点以Sobel方式求导数X=150+230+150(150+230+150)=0。这样可以看出这个点不是边界。 好了,了解了基本理论之后,我们看看OpenCv下的Sobel函数吧,void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );src:输入图像;dst:输出图像;xorder:x 方向上的差分阶数;yorder:y 方向上的差分阶数;aperture_size 扩展 Sobel 核的大小(既窗口阶数),必须是 1(注意这是一个31或13向量而不是一个方阵), 3, 5 或 7。 下面编写一个Sobel边缘检测的程序吧,平台是VS08,建立Win32控制台应用程序。#include #include void main()IplImage *frame,*gray,*sobel;frame=cvLoadImage(lena.jpg);/加载图像gray=cvCreateImage(cvGetSize(frame),frame-depth,1);/分配图像空间sobel=cvCreateImage(cvGetSize(frame),frame-depth,1);cvNamedWindow(frame);cvNamedWindow(gray);cvNamedWindow(sobel);cvCvtColor(frame,gray,CV_BGR2GRAY);/转为灰度cvSobel(gray,sobel,1,0,3);cvShowImage(frame,frame);/显示图像cvShowImage(gray,gray);cvShowImage(sobel,sobel);cvWaitKey(0);/等待cvReleaseImage(&frame);/释放空间(对视频处理很重要,不释放会造成内存泄露)cvReleaseImage(&gray);cvReleaseImage(&sobel);cvDestroyWindow(frame);cvDestroyWindow(gray);cvDestroyWindow(sobel);运行,你会发现出错,仔细看看没有问题啊。其实,这里是问题的,因为以Sobel方式求完导数后会有负值,还有会大于255的值而你建的Sobel的图像是 IPL_DEPTH_8U,也就是8位无符号数,所以Sobel建立的图像位数不够,要16位有符号的,也就是 IPL_DEPTH_16S。把建立图像这句改为sobel=cvCreateImage(cvGetSize(frame),IPL_DEPTH_16S,1);运行,发现不报错了,但是Sobel图像显示不出来,这是什么原因呢?原来图像显示是以8位无符号显示的,现在是16位有符号,当然显示会出问题了。所以还要将Sobel转为8位无符号。OpenCv里提供了一个函数,就是cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );src:源图像;dst:目标图像;scale:转化前乘的系数;shift转化前加的系数。这样新建一个无符号图像再转换就可以实现了。IplImage *sobel8u=cvCreateImage(cvGetSize(sobel),IPL_DEPTH_8U,1);再在显示图像前加上cvConvertScaleAbs(sobel,sobel8u,1,0);这样就可以看到cvSobel的效果了。可以看X方向或Y方向求导是什么效果。为了方便大家,我把改好后的程序也放上来了。#include #include void main()IplImage *frame,*gray,*sobel;frame=cvLoadImage(e:/p1.jpg);/加载图像gray=cvCreateImage(cvGetSize(frame),frame-depth,1);/分配图像空间sobel=cvCreateImage(cvGetSize(frame),IPL_DEPTH_16S,1);cvNamedWindow(frame);cvNamedWindow(gray);cvNamedWindow(sobel);cvCvtColor(frame,gray,CV_BGR2GRAY);/转为灰度cvSobel(gray,sobel,1,0,3);IplImage *sobel8u=cvCreateImage(cvGetSize(sobel),IPL_DEPTH_8U,1);cvConvertScaleAbs(sobel,sobel8u,1,0);cvShowImage(frame,frame);/显示图像cvShowImage(gray,gray);cvShowImage(sobel,sobel8u);cvWaitKey(0);/等待cvReleaseImage(&frame);/释放空间(对视频处理很重要,不释放会造成内存泄露)cvReleaseImage(&gray);cvReleaseImage(&sobel);cvDestroyWindow(frame);cvDestroyWindow(gray);cvDestroyWindow(sobel);Laplace算子及cvLaplace(2010-11-29 22:56:34)转载标签: laplace算子cvlaplace分类: OpenCV 有了上一篇Sobel算子的基础,Laplace算子就显得十分简单了。Sobel算子一般用来求一阶导数,而有些图像求一阶导数之后边缘也不一定十分清析,需要求其二阶导数,在计算机中,一般运算都用迭代法实现。同样,近似定义其二阶导数。其窗口如图所示:。可以看出f=4Z5-(Z2+Z4+Z6+Z8), 以这种方式就能以二阶导数的方式找出图像的边界。这种方式有其优点也有其缺点,优点就是由于彩用了二阶导数,可以确定边界在亮边还是暗边,暗 边0,亮边0,对边界响应很灵敏。但也就是因为采用了二阶导数,抗噪能力比

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论