컴퓨터비전/영상처리

옵티컬 플로우 Optical Flow -1

object0814 2015. 4. 4. 22:28

어떤 물체를 추적할때 가장 간단한 방법이 해당 블록(영역)을 다음 프레임에서 어딨을지 찾아가는
방법이 가장 간단한 추적 방법일 것이다.



OpenCV에서는 이 방법을 하나의 메소드 형태로 제공한다.


1
2
void cvCalcOpticalFlowBM(const CvArr* prev, const CvArr* curr, CvSize block_size, 
            CvSize shift_size, CvSize max_range, int use_previous, CvArr* velx, CvArr* vely)
cs


파라메타로 prev는 이전프레임으로 (8비트, 1채널 영상)을 입력받으며, curr는 현재 프레임으로 

이전 프레임과 동일하게 8비트 1채널 영상을 입력 받는다.

block_size는 두 영상에서 비교할 블록의 크기를 의미하며, shift_size는 탐색할 영역 크기를 나타낸다.

velx와 vely는 속도 벡터를 나타내는 변수로 1채널 32비트 실수 영상이다. 

max_range는 curr에서 최대 탐색 범위를 나타내고 usePreviosu가 1이면 velx와 vely에 있는 이전 결과를 사용한다.


            

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <cv.h>
#include <highgui.h>
#include <opencv\cvaux.h>
 
int main() 
{
    IplImage *prev = NULL, *curr = NULL;
    IplImage *velx = NULL, *vely = NULL;
 
    prev = cvLoadImage("img/prev.bmp"0);
    curr = cvLoadImage("img/curr.bmp"0);
 
    CvSize block_Size = cvSize(1010);
    CvSize shift_size = cvSize(55);
    CvSize max_range = cvSize(55);
    int usePrevious = 0;
 
    int sX = (prev->width - block_Size.width) / shift_size.width + 1;
    int sY = (prev->height - block_Size.height) / shift_size.height + 1;
 
    velx = cvCreateImage(cvSize(sX, sY), IPL_DEPTH_32F, 1);
    vely = cvCreateImage(cvSize(sX, sY), IPL_DEPTH_32F, 1);
 
    cvCalcOpticalFlowBM(prev, curr, block_Size, shift_size, max_range, usePrevious, velx, vely);
 
    IplImage *result = cvLoadImage("img/curr.bmp"1);
    
    double dx, dy;
    CvPoint p1, p2;
    int threshold = 2;
 
    // Draw OpticalFlow Vector
    for (int y = 0; y < sY; y++)
    {
        for (int x = 0; x < sX; x++)
        {
            dx = cvGetReal2D(velx, y, x);
            dy = cvGetReal2D(vely, y, x);
 
            if (sqrt(dx * dx + dy * dy) < threshold)
                continue;
 
            p1.x = block_Size.width + x * shift_size.width;
            p1.y = block_Size.height + y * shift_size.height;
 
            p2.x = cvRound(p1.x + dx);
            p2.y = cvRound(p1.y + dy);
 
            cvLine(result, p1, p2, CV_RGB(02550), 1, CV_AA);
        }
    }
 
    cvNamedWindow("velx");
    cvShowImage("velx", velx);
    cvNamedWindow("vely");
    cvShowImage("vely", vely);
 
    cvNamedWindow("OpticalFlow Result");
    cvShowImage("OpticalFlow Result", result);
    cvWaitKey(0);
 
    cvDestroyAllWindows();
 
    return 0;
}
cs


입력 영상 및 결과 영상

    


 결과 영상      (vely)   (velx)