本文主要是介绍Moravec角点检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
#include <opencv2\opencv.hpp>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"/**********************************************************************************
*函数 int getMoravec(IplImage* src,CvSeq* corners)
*输入:
*src : 单通道图像
*corners : 用来保存提取到的角点
*threshold : 角点量的阈值 (具体函数 请看视频)
*输出
*corners : 用来保存提取到的角点
*返回值
*角点的个数
***************************************************************************************/
int getMoravec(IplImage* src,CvSeq* corners , float threshold)
{//窗口大小const int winSize=5; int x,y,halfWinSize=winSize/2;//保存最小的变化量IplImage* diffDst = cvCreateImage(cvGetSize(src),32,1);cvZero(diffDst);//保存角点个数int cornersCount=0;//1.计算图像上每一个点上的 在4个方向上的变化量 并计算出最小值 保存在矩阵diffDst中for(y=halfWinSize;y<src->height-halfWinSize;y++){for(x=halfWinSize;x<src->width-halfWinSize;x++){//compute the reaction in the four directions(0,45,90,135)int winx;//数组reaction[4] 用于保持 在四个方向上的灰度值变化量 //minValue用于保存4个变化量中的最小值float reaction[4],minValue;reaction[0]=0;reaction[1]=0;reaction[2]=0;reaction[3]=0;//提示 下面的4个循环 可以综合成一个循环//0 度方向的变化量保存在reaction[0]中for( winx=-halfWinSize;winx<halfWinSize;winx++){reaction[0] = reaction[0] + pow( cvGetReal2D(src,y,x+winx)-cvGetReal2D(src,y,x+winx+1), 2 );}//45 度方向的变化量保存在reaction[1]中for( winx=-halfWinSize;winx<halfWinSize;winx++){reaction[1] = reaction[1]+pow(cvGetReal2D(src,y+winx,x+winx)-cvGetReal2D(src,y+winx+1,x+winx+1),2);}//90 度方向的变化量保存在reaction[2]中for( winx=-halfWinSize;winx<halfWinSize;winx++){reaction[2] = reaction[2]+pow(cvGetReal2D(src,y+winx,x)-cvGetReal2D(src,y+winx+1,x),2);}//135 度方向的变化量保存在reaction[3]中for( winx=-halfWinSize;winx<halfWinSize;winx++){reaction[3] = reaction[3]+pow(cvGetReal2D(src,y+winx,x-winx)-cvGetReal2D(src,y+winx+1,x-winx-1),2);}//计算4个量中最小值 保存到minValueminValue = reaction[0];minValue = minValue > reaction[1] ? reaction[1] : minValue;minValue = minValue > reaction[2] ? reaction[2] : minValue;minValue = minValue > reaction[3] ? reaction[3] : minValue;//将最小的变化量保存到矩阵cvSetReal2D(diffDst,y,x,minValue);}}//2.获取角点坐标for(y=halfWinSize;y<src->height-halfWinSize;){for(x=halfWinSize;x<src->width-halfWinSize;){float max=0;int flag = 0 ;CvPoint maxLoc;maxLoc.x = -1;maxLoc.y = -1;//首先计算以点(x,y)位中心的winSize*winSize的窗口内部的局部极大值for(int winy=-halfWinSize;winy<=halfWinSize;winy++){for(int winx=-halfWinSize;winx<=halfWinSize;winx++){float value ;value = cvGetReal2D(diffDst,y+winy,x+winx);//计算该窗口内 最大值 保存到max 并保存其坐标到maxLocif(value>max){max = value;maxLoc.x = x+winx;maxLoc.y = y+winy;flag = 1;}}}//如果找到局部极大值 并且该值大于预先设定的阈值 则认为是角点if(flag==1 && max>threshold){cvSeqPush(corners,&maxLoc);cornersCount++; }//下一个窗口x=x+halfWinSize;}//下一行的第一个窗口y=y+halfWinSize;}cvReleaseImage(&diffDst);return cornersCount;
}int main(int argc, char* argv[])
{IplImage* src;//加载源图像src = cvLoadImage("3.jpg",CV_LOAD_IMAGE_GRAYSCALE);if(!src){printf("图像加载失败");}//用于保存最终角点的空间CvMemStorage* mem = cvCreateMemStorage(0);//角点将会保存在一个CvSeq中CvSeq* corners;corners = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvPoint),mem);//角点的个数int cornersCount;//调用函数getMoravec计算角点cornersCount = getMoravec(src,corners,25000);//图像show用于显示角的提取结果IplImage* show= cvCreateImage(cvGetSize(src),8,3);cvCvtColor(src,show,CV_GRAY2BGR);//获取每一个角点的坐标for(int x=0;x<cornersCount;x++){CvPoint* pt = (CvPoint*)cvGetSeqElem(corners,x);//以角点坐标为中心 绘制一个半径为5的圆cvCircle(show,*pt,10,cvScalar(255,0,0,0));}//显示结果cvNamedWindow("dst");cvShowImage("dst",show);cvWaitKey(0);cvReleaseImage(&src);cvReleaseImage(&show);cvReleaseMemStorage(&mem);return 0;
}
运算结果:
角点的数量取决于所设定的阈值的大小。
阈值越小,角点数量越多,精度越低~
【1】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).
(计算每个像素点的兴趣值, 即以该像素点为中心, 取一个w*w(如:5x5)的方形窗口, 计算0度、45度、90度、135度四个方向灰度差的平方和, 取其中的最小值作为该像素点的兴趣值。)
(3)对每个位置minValue 进行判断,是不是大于设定阈值,如果是大于设定阈值,接着判断是不是局部极大值
这篇关于Moravec角点检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!