测试图片:
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; }