view c/optical-flow.cpp @ 398:3399bd48cb40

Ajout d'une méthode pour obtenir le nombre de FPS Méthode de capture des trames vidéos plus résistante aux erreur Utilisation d'un dictionnaire pour les fichier de configuration afin de garder le nom des sections
author Jean-Philippe Jodoin <jpjodoin@gmail.com>
date Mon, 29 Jul 2013 13:46:07 -0400
parents bc4ea09b1743
children 8e30c9a6ac6f
line wrap: on
line source

#include "cvutils.hpp"
#include "utils.hpp"

#include "opencv/cv.h"
#include "opencv/highgui.h"

#include <iostream>
#include <ctime>

/* MSVC does not have lrintf */
#ifdef _MSC_VER
static inline long lrintf(float f){
/* x64 does not supported embedded assembly */
#ifdef _M_X64
    return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
#else
    int i;
 
    _asm{
        fld f
        fistp i
    };
 
    return i;
#endif
}
#endif

using namespace std;

void videoTiming(CvCapture* inputVideo) {
  IplImage* frame = cvQueryFrame(inputVideo);
  //IplImage* bwFrame = allocateImage(frame->width, frame->height, IPL_DEPTH_8U, 1);

  int frameNum = 0;
  time_t seconds;
  time_t t0 = time(NULL);
  while (frame) {
    frameNum = ::goToFrameNum(inputVideo, frameNum, frameNum+1000);
    seconds = time(NULL)-t0;

    cout << frameNum << " " << seconds << endl;
  }
}

int main(int argc, char *argv[]) {
  //cout << "Hello World" << endl;

  CvCapture *inputVideo = 0;
  if (argc == 1)
    inputVideo = cvCreateCameraCapture(-1);
  else
    inputVideo = cvCaptureFromFile(argv[1]);

  int frameNum = 0;
  cvNamedWindow("Optical Flow", CV_WINDOW_AUTOSIZE);

  // allocate space for pyramids
  IplImage* frame = cvQueryFrame(inputVideo);
  CvSize frameSize = cvSize(frame->width, frame->height);

  IplImage* frame1_1C = ::allocateImage(frameSize, IPL_DEPTH_8U, 1);
  cvConvertImage(frame, frame1_1C);

  IplImage *frame1 = ::allocateImage(frameSize, IPL_DEPTH_8U, 3);
  cvConvertImage(frame, frame1);

  frame = cvQueryFrame(inputVideo);

  IplImage* frame2_1C = ::allocateImage(frameSize, IPL_DEPTH_8U, 1);
  cvConvertImage(frame, frame2_1C);

  IplImage *eig_image = ::allocateImage(frameSize, IPL_DEPTH_32F, 1);
  IplImage *temp_image = ::allocateImage(frameSize, IPL_DEPTH_32F, 1);

  int nFeatures = 1000;
  CvPoint2D32f frame1_features[1000];

  CvPoint2D32f frame2_features[1000];

  char optical_flow_found_feature[1000];
  float optical_flow_feature_error[1000];

  CvSize optical_flow_window = cvSize(3,3);

  CvTermCriteria optical_flow_termination_criteria = cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3 );
  IplImage* pyramid1 = ::allocateImage(frameSize, IPL_DEPTH_8U, 1);
  IplImage* pyramid2 = ::allocateImage(frameSize, IPL_DEPTH_8U, 1);

  int pressedKey = '?';
  while (frame && !::interruptionKey(pressedKey)) {
    cvGoodFeaturesToTrack(frame1_1C, eig_image, temp_image, frame1_features, &nFeatures, 0.05 /*quality*/, 1/* min dist*/, NULL);
    cvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1, pyramid2, frame1_features, frame2_features, nFeatures, optical_flow_window, 5, optical_flow_found_feature, optical_flow_feature_error, optical_flow_termination_criteria, 0 );

    for(int i = 0; i < nFeatures; i++) {
      if (optical_flow_found_feature[i] != 0) {
	int line_thickness = 1;
	CvScalar line_color = CV_RGB(255,0,0);
      
	CvPoint p,q;
	p.x = lrintf(frame1_features[i].x);
	p.y = lrintf(frame1_features[i].y);
	q.x = lrintf(frame2_features[i].x);
	q.y = lrintf(frame2_features[i].y);
	
	double dx = frame2_features[i].x-frame1_features[i].x;
	double dy = frame2_features[i].y-frame1_features[i].y;

	double angle = atan2( (double) p.y - q.y, (double) p.x - q.x );
	double dist = sqrt(square(dx) + square(dy));

	if (dist > 2.) { // min motion distance
	  q.x = lrintf(frame1_features[i].x+dx*3); //(p.x - 3 * hypotenuse * cos(angle));
	  q.y = lrintf(frame1_features[i].y+dy*3); //(p.y - 3 * hypotenuse * sin(angle));
      
	  /* Now we draw the main line of the arrow. */
	  cvLine( frame1, p, q, line_color, line_thickness, CV_AA, 0 );
	  /* Now draw the tips of the arrow.  I do some scaling so that the
	   * tips look proportional to the main line of the arrow.
	   */
	  float arrowSize = 6;
	  p.x = lrintf(q.x + arrowSize * cos(angle + pi / 4));
	  p.y = lrintf(q.y + arrowSize * sin(angle + pi / 4));
	  cvLine( frame1, p, q, line_color, line_thickness, CV_AA, 0 );
	  p.x = lrintf(q.x + arrowSize * cos(angle - pi / 4));
	  p.y = lrintf(q.y + arrowSize * sin(angle - pi / 4));
	  cvLine( frame1, p, q, line_color, line_thickness, CV_AA, 0 );
	}
      }
    }
    cvShowImage("Optical Flow", frame1);
    pressedKey = cvWaitKey(5);
    frame = cvQueryFrame(inputVideo);
    frameNum++;
    cout << frameNum << endl;

    cvCopy(frame2_1C, frame1_1C);
    cvCopy(pyramid2, pyramid1);
    cvConvertImage(frame, frame2_1C);
    cvConvertImage(frame, frame1);
  }

  return 1;
}