Moravec角点检测算法原理
2014-03-18 04:52
357 查看
参考资料:
(1)Moravec角点检测算法原理
Moravec角点检测算法是最早的角点检测算法之一。该算法将角点定义为具有低“自相关性”的点。算法会检测图像的每一个像素,将像素周边的一个邻域作为一个patch,并检测这个patch和周围其他patch的相关性。这种相关性通过两个patch间的平方差之和(SSD)来衡量,SSD值越小则相似性越高。
如果像素位于平滑图像区域内,周围的patch都会非常相似。如果像素在边缘上,则周围的patch在与边缘正交的方向上会有很大差异,在与边缘平行的方向上则较为相似。而如果像素是各个方向上都有变化的特征点,则周围所有的patch都不会很相似。
Moravec会计算每个像素patch和周围patch的SSD最小值作为强度值,取局部强度最大的点作为特征点。
(2)Moravec角点检测示意图:
![](http://www.opencvchina.com/data/attachment/forum/201211/15/2015390yu0u2z3j0j4e8q4.jpg)
(3)将moravec角点检测方法公式化:
Moravec 在1981年提出Moravec角点检测算子[1],并将它应用于立体匹配。
首先, 计算每个像素点的兴趣值, 即以该像素点为中心, 取一个w*w(如:5x5)的方形窗口, 计算0度、45度、90度、135度四个方向灰度差的平方和, 取其中的最小值作为该像素点的兴趣值。
![](http://www.opencvchina.com/data/attachment/forum/201211/15/201730uicifmq1ix3fiyci.jpg)
图1- 1 以3x3为例 黑色窗口为I(x,y) 红色窗口为I(x+u,y+v)
其中四种移位 (u,v) = (1,0), (1,1), (0,1), (-1, 1).w(x,y)为方形二值窗口,若像素点在窗口内,则取值为1, 否则为0。
moravec角点检测步骤:
(1)对于每一个像素点,计算在E(u,v),在我们的算法中,(u,v)的取值是((1,0), (1,1), (0,1), (-1, 1).当然,你自己可以改成(1,0),(1,1),(0,1),(-1,1),(-1,0),(-1,-1),(0,-1),(1,-1) 8种情况
(2)计算最小值对每个位置minValue = min{E(u,v)},其中(u,v) = (1,0), (1,1), (0,1), (-1, 1).
(3)对每个位置minValue 进行判断,是不是大于设定阈值,如果是大于设定阈值,接着判断是不是局部极大值
(1)Moravec角点检测算法原理
Moravec角点检测算法是最早的角点检测算法之一。该算法将角点定义为具有低“自相关性”的点。算法会检测图像的每一个像素,将像素周边的一个邻域作为一个patch,并检测这个patch和周围其他patch的相关性。这种相关性通过两个patch间的平方差之和(SSD)来衡量,SSD值越小则相似性越高。
如果像素位于平滑图像区域内,周围的patch都会非常相似。如果像素在边缘上,则周围的patch在与边缘正交的方向上会有很大差异,在与边缘平行的方向上则较为相似。而如果像素是各个方向上都有变化的特征点,则周围所有的patch都不会很相似。
Moravec会计算每个像素patch和周围patch的SSD最小值作为强度值,取局部强度最大的点作为特征点。
(2)Moravec角点检测示意图:
![](http://www.opencvchina.com/data/attachment/forum/201211/15/2015390yu0u2z3j0j4e8q4.jpg)
(3)将moravec角点检测方法公式化:
Moravec 在1981年提出Moravec角点检测算子[1],并将它应用于立体匹配。
首先, 计算每个像素点的兴趣值, 即以该像素点为中心, 取一个w*w(如:5x5)的方形窗口, 计算0度、45度、90度、135度四个方向灰度差的平方和, 取其中的最小值作为该像素点的兴趣值。
![](http://www.opencvchina.com/data/attachment/forum/201211/15/201730uicifmq1ix3fiyci.jpg)
图1- 1 以3x3为例 黑色窗口为I(x,y) 红色窗口为I(x+u,y+v)
其中四种移位 (u,v) = (1,0), (1,1), (0,1), (-1, 1).w(x,y)为方形二值窗口,若像素点在窗口内,则取值为1, 否则为0。
moravec角点检测步骤:
(1)对于每一个像素点,计算在E(u,v),在我们的算法中,(u,v)的取值是((1,0), (1,1), (0,1), (-1, 1).当然,你自己可以改成(1,0),(1,1),(0,1),(-1,1),(-1,0),(-1,-1),(0,-1),(1,-1) 8种情况
(2)计算最小值对每个位置minValue = min{E(u,v)},其中(u,v) = (1,0), (1,1), (0,1), (-1, 1).
(3)对每个位置minValue 进行判断,是不是大于设定阈值,如果是大于设定阈值,接着判断是不是局部极大值
#pragma comment(lib,"cxcore.lib") #pragma comment(lib,"cv.lib") #pragma comment(lib,"highgui.lib") #pragma comment(lib,"ml.lib") #pragma comment(lib,"cvcam.lib") #pragma comment(lib,"cvaux.lib") #include <stdio.h> #include <iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> using namespace std; int getMoravec(IplImage* src,CvPoint* corners , float threshold) { int winsize=5;//窗口的大小 即 5*5 win[5,5] int halfwinsize=winsize/2; IplImage* diffDst=cvCreateImage(cvGetSize(src),32,1); cvZero(diffDst); //float threshold=9500; int conersCount=0; float maxCornersValue=0;//最大角点值 int x,y; /* //滑动窗口 * * * * * * * * * * * * 0 * * * * * * * * * * * * //遍历方式如图 ************** ************** **1111111111** **1111111111** **1111111111** ************** ************** */ for (y=halfwinsize;y<src->height-halfwinsize;y++) { for (x=halfwinsize;x<src->width-halfwinsize;x++) { float reaction[4],minVal; reaction[0]=0; reaction[1]=0; reaction[2]=0; reaction[3]=0; int i; //0 for (i=-halfwinsize;i<halfwinsize;i++)//-2 -1 0 -1 { reaction[0]+= pow(cvGetReal2D(src,y,x+i)-cvGetReal2D(src,y,x+i+1),2); } //45 for (i=-halfwinsize;i<halfwinsize;i++)//-2 -1 0 -1 { reaction[1]+= pow(cvGetReal2D(src,y+i,x+i)-cvGetReal2D(src,y+i+1,x+i+1),2); } //90 for (i=-halfwinsize;i<halfwinsize;i++)//-2 -1 0 -1 { reaction[2]+= pow(cvGetReal2D(src,y+i,x)-cvGetReal2D(src,y+i+1,x),2); } //-45 for (i=-halfwinsize;i<halfwinsize;i++)//-2 -1 0 -1 { reaction[3]+= pow(cvGetReal2D(src,y+i,x-i)-cvGetReal2D(src,y+i+1,x-i-1),2); } //----------------------------- //取最小值 minVal=reaction[0]; minVal=reaction[1]<minVal?reaction[1]:minVal; minVal=reaction[2]<minVal?reaction[2]:minVal; minVal=reaction[3]<minVal?reaction[3]:minVal; cvSetReal2D(diffDst,y,x,minVal); //cvSetReal2D(diffDst,y,x,minValue); //局部 最大值 } }//---------------- for (y=halfwinsize;y<src->height-halfwinsize;y+=halfwinsize) { for (x=halfwinsize;x<src->width-halfwinsize;x+=halfwinsize) { float max=0; int flag=0; CvPoint maxLoc; maxLoc.x=-1; maxLoc.y=-1; //int halfwinsize=halfwinsize; for (int winy=-halfwinsize;winy<halfwinsize;winy++) { for (int winx=-halfwinsize;winx<halfwinsize;winx++) { float value; value=cvGetReal2D(diffDst,y+winy,x+winx); //if(value>0)printf("xxxxxx"); if (value>max) { max=value; flag=1; maxLoc.x=x+winx; maxLoc.y=y+winy; if(max>maxCornersValue)maxCornersValue=value; } } }//------------ if (flag==1 && max>threshold) { corners[conersCount].x=maxLoc.x; corners[conersCount].y=maxLoc.y; conersCount++; } } }//end for printf("图像中最大角点值=%f",maxCornersValue); return conersCount; } int main() { IplImage* src=cvLoadImage("img//Moravec.jpg",CV_LOAD_IMAGE_GRAYSCALE); CvPoint* corners; int cornersCount; corners=(CvPoint*)malloc(sizeof(CvPoint)*9000); int count=getMoravec(src,corners,6500); IplImage* show=cvCreateImage(cvGetSize(src),8,3); cvCvtColor(src,show,CV_GRAY2BGR); for (int i=0;i<count;i++) { cvCircle(show,corners[i],5,cvScalar(0,0,255)); } cvNamedWindow("show"); cvShowImage("show",show); cvWaitKey(0); return 0; }
相关文章推荐
- java interface 用法
- coding---进程、线程的回收
- LeetCode 之排序 sorting
- 新人第一篇
- MVC二级联动使用$.getJSON方法
- Binary Tree Preorder Traversal -- LeetCode
- 完全依赖XP必将自食其果
- vijos 1243 单调队列优化dp
- 002_030 Python CRC 64位循环冗余码校验
- C# RichTextBox 获取当前光标的行号列号
- LeetCode - Reverse Words in a String
- S3C6410 启动u-boot 加载内核和文件系统
- 《Cracking the Coding Interview》——第2章:链表——题目7
- direct填充
- 《Cracking the Coding Interview》——第2章:链表——题目6
- DNS分析之 dnsdict6 使用方法
- msvbvm60中函数介绍
- flex loaderInfo为null在creationComplete事件中
- 腾讯与搜狗的爱情续篇
- 《Cracking the Coding Interview》——第2章:链表——题目5