2010-11-22 6 views
2

こんにちは、 オプティカルフローメソッドを使用してビデオシーケンスを安定させるプロジェクトを行っています。 私はこれまでオプティカルフローをうまく行ってきました。しかし、私は私の前に2つの支店があります。 1-オプティカルフローを取得した後、イメージ変位の平均を求めてから、2番目のフレームのフィーチャから平均を減算しました。次に何をすべきか?画像安定化

2 - または私は私が変換行列を計算し、その後、私はその後、cvWarpPerspective cvPerspectiveTransformを使用した画像を、安定化ためにOpenCVの機能を使用することができますが、私は「悪いフラグ」

することができますが、エラーを取得していますコードを見て、私が欲しいのはイメージを安定させるために何をすべきかです。私はあなたが提供することができる任意のソリューションをしたいですか?

enter code here 
#include <stdio.h> 
#include <stdlib.h>  
//#include "/usr/include/opencv/cv.h"  
#include <cv.h>  
#include <cvaux.h>  
#include <highgui.h>  
#include <math.h>  
#include <iostream> 

#define PI 3.1415926535898 

double rads(double degs) 
{ 
    return (PI/180 * degs); 
} 

CvCapture *cap; 

IplImage *img;  
IplImage *frame;  
IplImage *frame1;  
IplImage *frame3;  
IplImage *frame2;  
IplImage *temp_image1;  
IplImage *temp_image2;  
IplImage *frame1_1C;  
IplImage *frame2_1C;  
IplImage *eig_image;  
IplImage *temp_image;  
IplImage *pyramid1 = NULL;  
IplImage *pyramid2 = NULL; 

char * mapx; 
char * mapy; 

int h; 
int corner_count; 
CvMat* M = cvCreateMat(3,3,CV_32FC1); 
CvPoint p,q,l,s; 
double hypotenuse; 
double angle; 

int line_thickness = 1, line_valid = 1, pos = 0; 
CvScalar line_color; 
CvScalar target_color[4] = { // in BGR order 
     {{ 0, 0, 255, 0 }}, // red  
     {{ 0, 255, 0, 0 }}, // green  
     {{ 255, 0, 0, 0 }}, // blue  
     {{ 0, 255, 255, 0 }} // yellow  
}; 

inline static double square(int a)  
{ 
return a * a; 
} 

char* IntToChar(int num){return NULL;} 

/*{ 
    char* retstr = static_cast<char*>(calloc(12, sizeof(char))); 

    if (sprintf(retstr, "%i", num) > 0) 
    { 
     return retstr; 
    } 
    else 
    { 
     return NULL; 
    } 
}*/ 

inline static void allocateOnDemand(IplImage **img, CvSize size, int depth, int channels) 
{ 
    if (*img != NULL) 
     return; 

    *img = cvCreateImage(size, depth, channels); 

    if (*img == NULL) 
    { 
     fprintf(stderr, "Error: Couldn't allocate image. Out of memory?\n"); 
     exit(-1); 
    } 
} 

void clearImage (IplImage *img) 
{ 
    for (int i=0; i<img->imageSize; i++)  
     img->imageData[i] = (char) 0;  
} 

int main() 
{ 
    cap = cvCaptureFromCAM(0);  
    //cap = cvCaptureFromAVI("/home/saif/Desktop/NAO.. the project/jj/Test3.avi"); 

    CvSize frame_size; 

    // Reading the video's frame size 
    frame_size.height = (int) cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT); 
    frame_size.width = (int) cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH);  
    cvNamedWindow("Optical Flow", CV_WINDOW_AUTOSIZE); 

    while(true)  
    { 
    frame = cvQueryFrame(cap); 

     if (frame == NULL) 
     {  
      fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n"); 
      return -1;  
     } 

     // Allocating another image if it is not allocated already.  
     allocateOnDemand(&frame1_1C, frame_size, IPL_DEPTH_8U, 1);  
     cvConvertImage(frame, frame1_1C, 0);  
     allocateOnDemand(&frame1, frame_size, IPL_DEPTH_8U, 3);  
     cvConvertImage(frame, frame1, 0); 

     //Get the second frame of video.  
     frame = cvQueryFrame(cap); 

     if (frame == NULL)  
     { 
      fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n"); 
      return -1; 
     } 

     if(!frame) 
     {  
      printf("bad video \n");  
      exit(0); 
     } 

     allocateOnDemand(&frame2_1C, frame_size, IPL_DEPTH_8U, 1); 
     cvConvertImage(frame, frame2_1C, 0);  
     allocateOnDemand(&frame2, frame_size, IPL_DEPTH_8U, 3);  
     cvConvertImage(frame, frame2, 0); 

     CvSize optical_flow_window = cvSize(5,5);  
     eig_image = cvCreateImage(frame_size, IPL_DEPTH_32F, 1);  
     temp_image = cvCreateImage(frame_size, IPL_DEPTH_32F, 1); 

     CvTermCriteria optical_flow_termination_criteria = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3); 

     // Feature tracking 
     CvPoint2D32f frame1_features[4]; 
     CvPoint2D32f frame2_features[4]; 

     //cvCornerEigenValsAndVecs(eig_image, temp_image, 1);  
     corner_count = 4; 

     cvGoodFeaturesToTrack(frame1_1C,eig_image , temp_image, frame1_features, &corner_count, 0.1, .01, NULL, 5, 1);  
     cvFindCornerSubPix(frame1_1C, frame1_features, corner_count,cvSize(5, 5) ,optical_flow_window , optical_flow_termination_criteria); 

     if (corner_count <= 0)  
      printf("\nNo features detected.\n");  
     else  
      printf("\nNumber of features found = %d\n", corner_count); 

     //Locus Kande method.  
     char optical_flow_found_feature[20];  
     float optical_flow_feature_error[20]; 

     allocateOnDemand(&pyramid1, frame_size, IPL_DEPTH_8U, 1);  
     allocateOnDemand(&pyramid2, frame_size, IPL_DEPTH_8U, 1); 

     cvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1, pyramid2, frame1_features, frame2_features, corner_count, optical_flow_window, 5, optical_flow_found_feature, NULL, optical_flow_termination_criteria, NULL); 

    /* 
    double sumOfDistancesX = 0;  
    double sumOfDistancesY = 0; 

    int debug = 0; 

    CvFont font1, font2;  
    CvScalar red, green, blue;  
    IplImage* seg_in = NULL;  
    IplImage *seg_out = NULL; 

    allocateOnDemand(&seg_in, frame_size, IPL_DEPTH_8U, 3);  
    allocateOnDemand(&seg_out, frame_size, IPL_DEPTH_8U, 3); 

    clearImage(seg_in);  
    clearImage(seg_in);  

    for(int i=0; i <corner_count; i++) 
    { 

     if (optical_flow_found_feature[i] == 0) 
      continue;  
     p.x = (int) frame1_features[i].x;  
     p.y = (int) frame1_features[i].y;  
     q.x = (int) frame2_features[i].x;  
     q.y = (int) frame2_features[i].y; 
     angle = atan2((double) p.y - q.y, (double) p.x - q.x); 

      sumOfDistancesX += q.x - p.x;  
      sumOfDistancesY += q.y - p.y; 

      //cvRemap(frame2,frame1,averageDistanceX , averageDistanceY,CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0));  
     } 
     */ 

     /*  
     int averageDistanceX = sumOfDistancesX/corner_count;  
     int averageDistanceY = sumOfDistancesY/corner_count;  
     l.x = averageDistanceX - q.x;  
     s.y = averageDistanceY - q.y; 
     */ 

#define cvWarpPerspectiveQMatrix cvGetPerspectiveTransform 

     //CvMat* N = cvCreateMat(3,3,CV_32FC1); 

     cvGetPerspectiveTransform(frame2_features, frame1_features, M); 
     cvPerspectiveTransform(frame1_features, frame2_features, M);  
     cvWarpPerspective(frame2_features, frame1_features, M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0)); 

     cvShowImage("Optical Flow", frame1);  
     cvWaitKey(50); 
    } 

    cvReleaseCapture(&cap);  
    cvReleaseMat(&M);  

    return 0;  
} 
+0

「不良フラグ」エラーが発生している行を教えてください。 編集:ああ、ようこそ、スタックオーバーフロー! – btown

+0

不良フラグエラー.cvPerspectiveTransformとcvWarpPerpectiveで開始されます。私は、どちらか一方または両方を使って悪い旗を得ることを意味します。 – Mario

答えて

2

あなたは第二の画像からの平均変位を減算したくない、あなたはそれが最初に「一致する」ように、平均変位で(移動)第2の画像を変換したいです。あなたが使用する「変位」は、状況によって異なります。

  • カメラが揺れていても静止していない場合は、2つの連続フレーム間の平均変位を2番目のフレームの変換ベクトルとして使用します。新しいフレームごとに、変換された最初のフレームと新しいフレームの間の変位を計算し、新しいフレームを変換します。
  • あなたのカメラが動き、揺れている場合(つまり、山車の上にヘルメットを取り付けたカメラ)、数フレームにわたるフレーム間の平均変位を見つけてから、その平均変位と前のフレームとの間の変位。

あなたは基本的にオプション2のために行うに必要なものEDIT は、過去数フレームにわたってフレーム間の移動平均の平均値を算出しています。これはいくつでも可能ですが、カルマンフィルタのようなものを使うことをお勧めします。次に、新しいフレームについて、そのフレームと(補正された)前のフレームとの間の動きを計算します。動きから平均動きをその点まで減算し、その差で新しいフレームを移動します。

+0

私は第二の選択肢に行くつもりです。私は非常に不安な動きをしているロボットに取り組んでいます。私のコードでは、変位の平均を求めてからそれを減算することがわかります。しかし、あなたのアイデアは少し異なりますが、私はそれを実装する方法を知らない、私の主な問題はプログラミングです。あなたはより具体的な提案をすることができますか? – Mario

+0

私は実装についてのコメントを追加しました。 –

+0

@jillesdewitこんにちは、カルマンフィルタを使ってフレーム間の平均動きを計算することを提案しました。しかし、ちょっと読んで、私が理解していることは、カルマンフィルタを使って以前に測定した値から値を予測することです。どのように平均運動を計算するのに役立ちますか? –