opencv moravec角点检测

测试图片:

opencv moravec角点检测_第1张图片

code:

#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv\cxcore.h>
#include <stdlib.h>
#include <stdio.h>

/*-----------------------------------------------------------------------------------
*
*函数 int getMoravec(IplImage* src,CvSeq* corners)
*                                                   
*输入:
*src : 单通道图像
*corners : 用来保存提取到的角点
*threshold : 角点量的阈值 (具体函数 请看视频)
*
*输出
*corners : 用来保存提取到的角点
*
*返回值
*角点的个数
*----------------------------------------------------------------------------------*/

int getMoravec(IplImage* src,CvSeq* corners , float threshold)
{
	//窗口大小   halfWinSize=> 窗口的一半
	const int winSize=5; 
	int x,y,halfWinSize=winSize/2;
	
	//保存最小的变化量
	IplImage* diffDst = cvCreateImage(cvGetSize(src),32,1);
	cvZero(diffDst);
	
	//保存角点个数
	int cornersCount=0;

	//计算图像上每一个点上的 在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个量中最小值  保存到minValue
			minValue = 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);
		}
	}



	//获取角点坐标
	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 并保存其坐标到maxLoc
					if(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("C:\\Users\\zxl\\Desktop\\1.BMP",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,29500);
	
	//图像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,5,cvScalar(255,0,255,0));
	}

	//显示结果
	cvNamedWindow("dst");
	cvShowImage("dst",show);
	cvWaitKey(0);

	cvReleaseImage(&src);
	cvReleaseImage(&show);
	cvReleaseMemStorage(&mem);

	return 0;
}



 

 

 

 

 

你可能感兴趣的:(opencv moravec角点检测)