光流法检测——特征点

来源:互联网 发布:java 反射 用途 编辑:程序博客网 时间:2024/06/05 19:12

转自 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 100int 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;}


原创粉丝点击