샨샨 2020. 11. 23. 17:02
반응형

Basic concept

1. ROI가 설정된다.

2.ROI 영역을 히스토그램 혹은 feature로 표현한다.

3.그 다음 frame에서 ROI와 가장 유사한 patch를 찾는다.

 

Mean shift

-점의 밀도가 최대인 위치로 이동

 

- Histogram back-projection

1. model image의 2차원 히스토그램을 계산한다. (계산했을 때 살색이 굉장히 많기 때문에, 특정부분만 흰색인 결과 도출)

2. 손일 확률이 높은 부분은 하얀색, 아닌부분은 검정색으로 back projection이 일어남

 

tracking using mean shift

1. 자동차의 히스토그램 구함

2. target image 에서 자동차의 히스토그램에 유사한 부분은 밝고, 아닌부분은 어둡게 함

3. 밝기값의 밀도가 높은 곳을 추적 = 자동차 부분

 

cam shift

- mean shift와 유사

- mean shift는 물체의 크기가 변해도 ROI 크기가 똑같음

- cam shift는 이러한 단점을 보완해, 물체의 크기가 변하면 ROI 변경

 

cam shift 예제 코드

#include "cv.hpp"
#include <iostream>

using namespace cv;
using namespace std;

struct CallbackParam{
    Mat frame; //영상
    Point pt1, pt2; //포인터
    Rect roi; //roi
    bool drag;// drag 여부
    bool updated; //update 여부
};
void onMouse(int event, int x, int y, int flags, void* param){
    CallbackParam *p = (CallbackParam *)param;
    if(event == EVENT_LBUTTONDOWN){
        p->pt1.x = x;
        p->pt1.y =y;
        p->pt2 = p-> pt1;
        p->drag = true;
    }
    if(event == EVENT_LBUTTONUP){
        int w = x - p->pt1.x;
        int h = y - p->pt1.y;
        p->roi.x = p->pt1.x;
        p->roi.y = p->pt1.y;
        p->roi.width = w;
        p->roi.height = h;
        p->drag = false;
        if(w >=10 && h>=10){
            p->updated = true;
        }
    }
    if(p->drag && event == EVENT_MOUSEMOVE){
        if(p->pt2.x != x || p->pt2.y != y){
            Mat img = p->frame.clone();
            p->pt2.x = x;
            p->pt2.y = y;
            rectangle(img, p->pt1, p->pt2, Scalar(0,255,0),1);
            imshow("Tracker",img);
        }
    }
}
int main(int argc, char *argv[]){
    VideoCapture cap(0);
    CallbackParam param;
    Mat frame, m_backproj, hsv;
    Mat m_model3d;
    Rect m_rc;
    float hrange[]={0,180};
    float vrange[]={0,255};
    float srange[]={0,255};
    const float* ranges[]={ hrange,srange,vrange};
    int channels[]={0,1,2};
    int hist_sizes[]={16,16,16};

    if(!cap.isOpened()){
        cout << "can't open the file"<<endl;
        return 0;
    }

    //click and drag on image to set ROI
    cap >> frame;  //첫번재 프레임 display
    imshow("Tracker",frame);
    param.frame = frame;
    param.drag = false;
    param.updated = false;
    setMouseCallback("Tracker",onMouse,&param); //관심영역 지정

    bool tracking = false;
    while(true){

        if(param.drag){
            if(waitKey(33)==27) break;
            continue;
        }
        cvtColor(frame,hsv,COLOR_BGR2HSV); //hsv 로 변경

        if(param.updated){ //드래그한 영역 histogram 계산 
            Rect rc = param.roi;
            Mat mask = Mat::zeros(rc.height, rc.width, CV_8U);
            ellipse(mask,Point(rc.width /2, rc.height/2),Size(rc.width/2,rc.height/2),0,0,360,255,CV_FILLED);
            Mat roi(hsv,rc);
            calcHist(&roi,1,channels,mask,m_model3d,3,hist_sizes,ranges);
            m_rc = rc;
            param.updated = false;
            tracking = true;
        }
        cap >> frame;
        if(frame.empty()) break;
        if(tracking){
            calcBackProject(&hsv,1,channels,m_model3d,m_backproj,ranges);
    // tracking
            CamShift(m_backproj,m_rc,cvTermCriteria(TermCriteria::EPS | TermCriteria::COUNT,20,1));
            rectangle(frame, m_rc, Scalar(0,0,255),3);
        }

        imshow("Tracker",frame); //image display

        char ch = waitKey(33);
        if(ch ==27) break;
        else if(ch==32){
            while((ch=waitKey(33))!=32 && ch != 27);
            if(ch == 27) break;
        }
    }

    return 0;

}

 

Optical flow (광학 흐름)

두 개의 비디오 프레임 사이에 이미지 객체의 동작 패턴

물체가 움직이면 그에 따른 명암 변화가 발생 -> 물체의 움직임 모션 필드를 표현

optical flow의 가정

  • 밝기값은 인접한 픽셀에서 변하지 않는다.
  • 픽셀의 움직임은 인접픽세의 움직임과 유사하다.

KLT algorithm

-추적에 유리한 특징점을 골라낸다.

 

 

반응형