2010-11-22 2 views
2

안녕하세요, 난 광학 흐름 방법을 사용하여 비디오 시퀀스를 안정화하는 프로젝트를하고 있어요. 나는 광학 흐름을 지금까지 잘 해왔다. 그러나 나는 그것에 앞장서 서 나 앞에서 2 개의 가지가있다. 1- 옵티컬 플로우를 얻은 후에 나는 이미지 변위의 평균을 찾은 다음 두 번째 프레임의 피쳐에서 평균을 뺀다. 다음에해야 할 일은 무엇입니까?이미지 안정화

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

, 당신은 평균 변위에 의해 두 번째 이미지 (이동)를 변환 할 그것을 "일치"첫 있도록. 사용하는 "변위"는 상황에 따라 다릅니다.

  • 카메라가 흔들리지 만 않으면 고정 된 두 개의 연속 프레임 사이의 평균 이동을 두 번째 프레임의 변환 벡터로 사용하십시오. 새로운 각 프레임을 사용하여 변형 된 첫 번째 프레임과 새 프레임 사이의 변위를 계산하고 새 프레임을 변환합니다.
  • 카메라가 움직이고 흔들리는 경우 (예 : mountainbiker에 헬멧을 장착 한 카메라) 몇 프레임에 걸쳐 프레임 간의 평균 변위를 찾은 다음 개별 프레임을 해당 평균 변위와 그것과 이전 프레임 사이의 변위.

편집 당신이 기본적으로 옵션 2를 위해해야 ​​할 것은 지난 몇 프레임에 걸쳐 프레임 사이의 평균 운동의 평균을 계산합니다. 이것은 여러 가지 방법으로 할 수 있지만 칼만 필터 같은 것을 사용하는 것이 좋습니다. 그런 다음 새 프레임에 대해 이전 프레임과 (보정 된) 프레임 사이의 움직임을 계산합니다. 움직임에서 평균 이동을 그 지점까지 빼고 그 차이만큼 새 프레임을 이동합니다.

+0

두 번째 옵션을 사용할 예정입니다. 매우 불안정한 동작을하는 로봇에서 작업하고 있습니다. 당신은 내 코드에서 변위의 평균을 얻은 다음 그것을 빼는 것을 볼 수 있습니다. 하지만 당신의 생각은 조금 다르지만 그것을 구현하는 방법을 모르겠습니다, 내 주요 문제는 프로그래밍입니다. 좀 더 구체적인 제안을 해줄 수 있습니까? – Mario

+0

구현에 대한 의견을 추가했습니다. –

+0

@jillesdewit 안녕하세요, 칼만 필터를 사용하여 프레임 간의 평균 이동을 계산하도록 제안했습니다. 그러나 조금 읽으면서 칼만 필터를 사용하여 이전에 측정 된 값으로부터 값을 예측한다는 사실을 이해했습니다. 평균 운동을 계산하는 데 어떻게 도움이 될까요? –