光流法检测——特征点

转自 http://blog.csdn.net/ji0525084/article/details/8854247

#include "stdafx.h"
#include <highgui.h>
#include <cxcore.h>
#include <cv.h>
#include <stdio.h>
#define max_corner 100


int main(int argc, char* argv[])
{
	CvCapture * capture = cvCaptureFromAVI("rgb.avi");
	IplImage * cur_frame = NULL;
	IplImage * cur_copy = NULL;
	IplImage * cur_mov = NULL;
	IplImage * cur_gray = NULL;
	IplImage * pre_gray = NULL;
	IplImage * TempFrame = NULL;
	IplImage * TempFrame1 = NULL;
	IplImage * pre_pyramid = NULL;
	IplImage * cur_pyramid = NULL;
	CvPoint2D32f pre_feature[max_corner];
	CvPoint2D32f cur_feature[max_corner];
	int corner_num = max_corner;
	int reverse_num = 0;
	int frmnum = 0;
	char FeatureFound[max_corner];
	CvPoint Point1 = cvPoint(160,30);
	CvRect ROIRect = cvRect(Point1.x,Point1.y,300,210);
	CvRect ROIRect1 = cvRect(Point1.x,Point1.y,90,180);
	CvRect ROIRect2 = cvRect(Point1.x+ROIRect1.width,Point1.y,135,210);
	CvRect ROIRect3 = cvRect(Point1.x+ROIRect1.width+ROIRect2.width,Point1.y,80,210);
//	cvNamedWindow("pre_feature",1);
	cvNamedWindow("cur_feature",1);
	cvNamedWindow("cur_mov",1);
	while(cur_frame = cvQueryFrame(capture))
	{
		frmnum++;
		//cur_frame->origin = 0;
	//	cvFlip(cur_frame,NULL,0);
		if(frmnum == 1){
			cur_copy = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_8U,3);
			cur_mov = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_8U,3);
		}
		cvCopy(cur_frame,cur_copy,0);//cur_copy是用来标记角点的图像
		cvCopy(cur_frame,cur_mov,0);//cur_mov是用来标记角点运动的图像
	//	cvShowImage("src",cur_frame);
//		cvWaitKey(0);
		//cvRectangle(cur_frame,cvPoint(430,30),cvPoint(430+ROIRect3.width,30+ROIRect3.height),CV_RGB(255,0,0),3,8);
		/*cvNamedWindow("cur_frame",1);
		cvShowImage("cur_frame",cur_frame);
		cvWaitKey(1);
		cvDestroyWindow("cur_frame");*/
		cvSetImageROI(cur_frame,ROIRect);
		
			
			if(frmnum == 1)
			{
				cur_gray = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_8U,1);
				pre_gray = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_8U,1);
				TempFrame = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_32F,1);
				TempFrame1 = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_32F,1);
				pre_pyramid = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_32F,1);
				cur_pyramid = cvCreateImage(cvGetSize(cur_frame),IPL_DEPTH_32F,1);
				cvCvtColor(cur_frame,cur_gray,CV_BGR2GRAY);
				cvCopy(cur_gray,pre_gray,0);//保存第一帧
			}
		
			else //if((frmnum-1)%15==0)
			{
				/*cvNamedWindow("preGRAY",1);
				cvShowImage("preGRAY",pre_gray);
				cvWaitKey(1);
				cvDestroyWindow("preGRAY");*/
				cvCvtColor(cur_frame,cur_gray,CV_BGR2GRAY);
				//cvRectangle(cur_gray,Point1,cvPoint(Point1.x+ROIRect.width,Point1.y+ROIRect.height),CV_RGB(255,0,0),3,8);
				/*cvNamedWindow("ROIGRAY",1);
				cvShowImage("ROIGRAY",cur_gray);
				cvWaitKey(1);
				cvDestroyWindow("ROIGRAY");
				cvNamedWindow("preGRAY1",1);
				cvShowImage("preGRAY1",pre_gray);
				cvWaitKey(1);
				cvDestroyWindow("preGRAY1");*/


				//找角   点
				cvGoodFeaturesToTrack( 
					pre_gray,//输入图像,8-位或浮点32-比特,单通道
					TempFrame,//临时浮点32-位图像,尺寸与输入图像一致 
					TempFrame1, //另外一个临时图像,格式与尺寸与 eig_image 一致
					pre_feature,//输出参数,检测到的角点
					&corner_num,//
					0.01, //经验值,最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子。	
					3,//0.01, //经验值,限制因子。得到的角点的最小距离。使用 Euclidian 距离 
					NULL);
				//在cur_copy(彩色图像)中标出上一帧的角点位置
				for(int i=0;i<corner_num;i++)
				{
					int x = pre_feature[i].x + Point1.x;
					int y = pre_feature[i].y + Point1.y;//因为标记时是以主窗口的左上角为起始点的,而非兴趣区域的坐标原点
					cvLine(cur_copy,cvPoint(x,y),cvPoint(x,y),CV_RGB(255,0,0),3,8,0);//画出角点
				}
		//		cvNamedWindow("pre_feature",1);
			//	cvShowImage("pre_feature",cur_copy);
			//	cvWaitKey(0);
		//		cvDestroyWindow("pre_feature");

				//找到当前帧中与上一帧匹配的角点位置
				if(corner_num==0)
					return 0;
				CvSize ModelWind = cvSize(3,3);
				CvTermCriteria termination_criteria = cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.3 );
				cvCalcOpticalFlowPyrLK( //&&&金字塔光流法跟踪
					pre_gray,					cur_gray,
					pre_pyramid,//第一帧的金字塔缓存
					cur_pyramid, //第二帧的金字塔缓存
					pre_feature,//需要发现光流的点集
					cur_feature,//包含新计算出来的位置的 点集 				
					corner_num,

					ModelWind, //每个金字塔层的搜索窗口尺寸 
					5, //经验值,金字塔层数
					FeatureFound,//数组。如果对应特征的光流被发现,数组中的每一个元素都被设置为 1, 否则设置为 0。
					0,//经验值
					termination_criteria,//经验值
					0 );
				//在cur_copy(彩色图像)中标出当前帧匹配到的角点位置
 				for(int i=0;i<corner_num;i++)
				{
					int x1 = cur_feature[i].x + Point1.x;
					int y1 = cur_feature[i].y + Point1.y;//因为标记时是以主窗口的左上角为起始点的,而非兴趣区域的坐标原点
					cvLine(cur_copy,cvPoint(x1,y1),cvPoint(x1,y1),CV_RGB(0,255,0),3,8,0);
				}
//				cvNamedWindow("cur_feature",1);
				cvShowImage("cur_feature",cur_copy);
				cvWaitKey(0);
//				cvDestroyWindow("cur_feature");
				//统计角点的运动方向
				int mov_corner = 0;
				int vy = 0;
				reverse_num = 0;
				for(int i=0;i<corner_num;i++){
					if(FeatureFound[i]==0)
						continue;
					int x = abs(pre_feature[i].x); 
					int y = abs(pre_feature[i].y);   
					int x1 = abs(cur_feature[i].x);
					int y1 = abs(cur_feature[i].y);
					double v = sqrt((double)((y1 - y)*(y1 - y) + (x1 - x)*(x1 - x)));
					int abs_vx = abs(x1 - x);
					vy = y1 - y;
					int abs_vy = abs(vy);
					if(abs_vy >= 50)
						continue;
					if(v <= 5 && abs(vy) <= 3)
						continue;
					mov_corner++;
					//if(vy < 0)
					{
						reverse_num++;

						x += Point1.x;
						y += Point1.y;//因为标记时是以主窗口的左上角为起始点的,而非兴趣区域的坐标原点
						cvLine(cur_mov,cvPoint(x,y),cvPoint(x,y),CV_RGB(255,0,0),3,8,0);
						x1 += Point1.x;
						y1 += Point1.y;//因为标记时是以主窗口的左上角为起始点的,而非兴趣区域的坐标原点
						cvLine(cur_mov,cvPoint(x,y),cvPoint(x1,y1),CV_RGB(255,255,255),1,8,0);
					}

				}
//				cvNamedWindow("cur_mov",1);
				cvShowImage("cur_mov",cur_mov);
				cvWaitKey(100);
//				cvDestroyWindow("cur_mov");

				cvCopy(cur_gray,pre_gray,0);
}

}
	cvReleaseImage(&cur_frame);
	cvReleaseImage(&cur_copy);
	cvReleaseImage(&cur_mov);
	cvReleaseImage(&cur_gray);
	cvReleaseImage(&pre_gray);
	cvReleaseImage(&TempFrame);
	cvReleaseImage(&TempFrame1);
	cvReleaseImage(&pre_pyramid);
	cvReleaseImage(&cur_pyramid);
	cvReleaseCapture(&capture);
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值