OPencv筆記2:光流法檢測——特徵點

#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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章