2017-02-11 21 views
1

나는 cv::calcOpticalFlowFarneback을 사용하여 openFrameworks에서 ofxOpenCv를 사용하여 비디오의 현재 프레임과 이전 프레임의 옵티컬 플로를 계산했습니다.광학 플로우 필드 주위에 경계 상자 만들기

다음으로 광학 플로우 필드가있는 비디오를 그 위에 그려 넣은 다음 특정 임계 값을 초과하는 영역에서 동작 흐름을 나타내는 벡터를 그립니다.

내가 지금하고 싶은 것은 움직임 영역의 테두리 상자를 만들고 그 중점을 얻어 x, y 위치를 추적 용 변수에 저장하는 것입니다.

이것이 도움이 될 경우 흐름 필드를 그리는 방법입니다.

if (calculatedFlow){ 
    ofSetColor(255, 255, 255); 
    video.draw(0, 0); 
    int w = gray1.width; 
    int h = gray1.height; 
    //1. Input images + optical flow 
    ofPushMatrix(); 
    ofScale(4, 4); 
    //Optical flow 
    float *flowXPixels = flowX.getPixelsAsFloats(); 
    float *flowYPixels = flowY.getPixelsAsFloats(); 
    ofSetColor(0, 0, 255); 
    for (int y=0; y<h; y+=5) { 
     for (int x=0; x<w; x+=5) { 
      float fx = flowXPixels[ x + w * y ]; 
      float fy = flowYPixels[ x + w * y ]; 
      //Draw only long vectors 
      if (fabs(fx) + fabs(fy) > .5) { 
       ofDrawRectangle(x-0.5, y-0.5, 1, 1); 
       ofDrawLine(x, y, x + fx, y + fy); 
       } 
       } 
      } 
      } 

답변

0

flowX에서 새 이미지를 작성하고 flowY로 문제를 해결했습니다. 이것은 flowX와 flowY를 새로운 CV FloatImage에 추가하여 수행되었습니다.

flowX +=flowY; 
flowXY = flowX; 

은 그 때 나는 새로 만든 이미지의 픽셀에서 발견 윤곽을 할 수 있었고, 그때는 운동의 모든 모양의 모든 무게 중심을 저장할 수 있습니다.그래서 추천

는 :

contourFinder.findContours(mask, 10, 10000, 20, false); 
//Storing the objects centers with contour finder. 
vector<ofxCvBlob> &blobs = contourFinder.blobs; 
int n = blobs.size();  //Get number of blobs 
obj.resize(n);   //Resize obj array 
for (int i=0; i<n; i++) { 
    obj[i] = blobs[i].centroid; //Fill obj array 
} 

I는 초기에 이동 만하기 때문에 음의 값의 X 축 및 Y 축으로 한 방향으로 추적되는 것을 발견 하였다. 나는 cv :: Mat에서 abs() 함수를 호출하여 옵티컬 플로우 계산을 변경함으로써이 문제를 해결했습니다.

Mat img1(gray1.getCvImage()); //Create OpenCV images 
Mat img2(gray2.getCvImage()); 
Mat flow; 
calcOpticalFlowFarneback(img1, img2, flow, 0.7, 3, 11, 5, 5, 1.1, 0); 
//Split flow into separate images 
vector<Mat> flowPlanes; 
Mat newFlow; 
newFlow = abs(flow); //abs flow so values are absolute. Allows tracking in both directions. 
split(newFlow, flowPlanes); 
//Copy float planes to ofxCv images flowX and flowY 
IplImage iplX(flowPlanes[0]); 
flowX = &iplX; 
IplImage iplY(flowPlanes[1]); 
flowY = &iplY; 
0

당신이 묻는 것에 대해서는 간단한 대답이 없습니다. 여기에 제안 된 해결책이 있습니다. 여러 단계가 필요하지만 도메인이 충분히 단순하면이 작업을 단순화 할 수 있습니다. 방법을 farneback 사용하여 이전 프레임과 현재 프레임을 비교하는 두 개의 이미지 flow_x, flow_y 각 프레임

  1. 계산 흐름. (코드에서,이 일을하는 것)

  2. 흐름 이미지를 hsv 이미지로 변환합니다. 각 픽셀의 색조 구성 요소는 흐름의 각도를 나타내고 atan2(flow_y/flow_x)이며 각 픽셀의 값 구성 요소는 흐름의 크기를 나타냅니다. sqrt(flow_x\*\*2 + flow_y\*\*2)

  3. 위의 단계에서 thresholding 메커니즘을 사용하여 크기가 특정 임계 값 아래로 떨어지는 플로우 픽셀을 검정색으로 만듭니다.
  4. 색상 범위를 기준으로 HSV 이미지를 분류합니다. 도메인에 대한 선입 선출 정보를 사용하거나 색조 구성 요소의 히스토그램을 사용하고 픽셀을 분류하는 눈에 잘 띄는 범위를 식별 할 수 있습니다. 이 단계의 결과로 각 픽셀에 클래스를 할당 할 수 있습니다.

  5. 각 클래스에 속한 픽셀을 여러 이미지로 분리하십시오. 분할 된 클래스 -1에 속하는 모든 픽셀은 이미지 -1로 이동하고 분할 된 클래스 2에 속한 모든 픽셀은 이미지 2 등으로 이동합니다. 이제 각 분할 된 이미지에는 특정 색상 범위의 HSV 이미지 픽셀이 포함됩니다.

  6. 각 분할 이미지를 흑백 이미지로 변환하고 opencv의 형태 학적 작업을 사용하여 연결을 사용하여 여러 영역으로 분할합니다. (연결된 구성 요소).

  7. 연결된 각 구성 요소의 중심을 찾습니다.

이 문맥에서 도움이 될 것으로 나타났습니다.

+0

이것은 개념을 더 이해하는 데 도움이됩니다. 나는 Cv :: Mat가 움직임의 다른 벡터에서 삼각법을 처리한다고 생각합니다. 왜냐하면 두 픽셀을 모두 얻은 후에 이미지를 임계 값으로 설정해야하기 때문입니다. 고맙습니다. – Elliot