2011.09.07 05:29 | EDIT
人物のAction Recognitionをするときに,結構な論文がOptical Flow(オプティカルフロー)を使っていたので,ちょっとクラスにしてみました.

実装したのは,PyramidLKとLK,2種類の手法です.

もちろんまだまだ拡張していくのですが,最初のものを残していく意味でも,書いておきます.

実装環境はVisula Studio 2008 ProfessionalとOpenCVです.

CalculateOpticalFlow.h


class CalculateOpticalFlow
{
public:
 CalculateOpticalFlow(void);
 ~CalculateOpticalFlow(void);

 void CalculatePyrLK(IplImage *src1, IplImage *src2, IplImage *display);

 void CalculateLK(IplImage *src1, IplImage *src2, IplImage *display);

private:

 // Pyramid Lucas-Kanade
 char *status;
 int i, j, corner_count;
 CvPoint2D32f *corners1, *corners2;
 IplImage *eig_img, *temp_img;
 IplImage *prev_pyramid, *curr_pyramid;

 // Lucas-Kanade
 int dx, dy, rows, cols;
 CvMat *velx, *vely;

 CvTermCriteria criteria; // Common overship
 

};



CalculateOpticalFlow.cpp


CalculateOpticalFlow::CalculateOpticalFlow(void)
{
 corner_count = 150;

 // Structure of Pyramid Lucas-Kanade
 // IMG_SIZE_X : x image size
 // IMG_SIZE_Y : y image size
 eig_img = cvCreateImage(cvSize(IMG_SIZE_X,IMG_SIZE_Y), IPL_DEPTH_32F, 1);
 temp_img = cvCreateImage(cvSize(IMG_SIZE_X,IMG_SIZE_Y), IPL_DEPTH_32F, 1);
 corners1 = (CvPoint2D32f *)cvAlloc(corner_count * sizeof(CvPoint2D32f));
 corners2 = (CvPoint2D32f *)cvAlloc(corner_count * sizeof(CvPoint2D32f));
 prev_pyramid = cvCreateImage(cvSize(IMG_SIZE_X+8, IMG_SIZE_Y/3), IPL_DEPTH_8U, 1);
 curr_pyramid = cvCreateImage(cvSize(IMG_SIZE_X+8, IMG_SIZE_Y/3), IPL_DEPTH_8U, 1);
 status = (char *)cvAlloc(corner_count);

 // Structure of Lucas-Kanade
 cols = IMG_SIZE_X;
 rows = IMG_SIZE_Y;
 velx = cvCreateMat(rows, cols, CV_32FC1);
 vely = cvCreateMat(rows, cols, CV_32FC1);
 cvSetZero(velx);
 cvSetZero(vely);

 criteria = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 64, 0.01);


}

CalculateOpticalFlow::~CalculateOpticalFlow(void)
{

 cvReleaseImage(&eig_img);
 cvReleaseImage(&temp_img);
 cvReleaseImage(&prev_pyramid);
 cvReleaseImage(&curr_pyramid);

 cvReleaseMat(&velx);
 cvReleaseMat(&vely);
}

// src1 & src2 : source two image to calculate optical flow
// display : drawing line
void CalculateOpticalFlow::CalculatePyrLK(IplImage *src1, IplImage *src2, IplImage *display)
{

 cvGoodFeaturesToTrack(src1, eig_img, temp_img, corners1, &corner_count, 0.0001, 5, NULL);

 cvCalcOpticalFlowPyrLK(src1, src2, prev_pyramid, curr_pyramid, corners1, corners2, corner_count, cvSize(10, 10), 4, status, NULL, criteria, 0);

 for(i = 0; i < corner_count; i++)
  if(status[i])
   cvLine(display, cvPointFrom32f(corners1[i]), cvPointFrom32f(corners2[i]), CV_RGB(255, 0, 0), 1, CV_AA, 0);

}

// src1 & src2 : source two image to calculate optical flow
// display : drawing line
void CalculateOpticalFlow::CalculateLK(IplImage *src1, IplImage *src2, IplImage *display)
{

 cvCalcOpticalFlowLK(src1, src2, cvSize(15, 15), velx, vely);

 for(i = 0; i < cols; i+=5){
  for(j = 0; j < rows; j+=5){

   dx = (int) cvGetReal2D(velx, j, i);
   dy = (int) cvGetReal2D(vely, j, i);
   cvLine(display, cvPoint(i, j), cvPoint(i+dx, j+dy), CV_RGB(255, 0, 0), 1, CV_AA, 0);
  }
 }

}

- スペース認識のため,全角のスペースを使用しております.コーディングの際は半角に直してからご使用ください.




クラスの宣言は,CalculateOpticalFlow COF;というように行い,

関数を使う場合にはCOF.CalculatePyrLK(---);という書き方をします.

さらに拡張しないと,行動の理解までにはならないので,僕はまだまだ頑張ります.

参考
OpenCV sample code オプティカルフロー
スポンサーサイト
コメント:
コメント:を投稿する

トラックバック: