2
votes

I am trying to visualize the output of calcOpticalFlowPyrLK() (OpenCv v3.0.0). I am not trying to draw whole image with optical flow, only the direction arrow. The problem is, I can't get to the output as in the examples. Every 10 frames I renew the points for the calculation of the flow. The function itself

calcOpticalFlowPyrLK(CentroidFrOld, CentroidFrNow, mc, CornersCentroidNow, feat_found, feat_errors, Size(15, 15), 2, cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10, 0.03), 0);

Where CentroidFrOld is grayscale frame, CentroidFrNow is grayscale frame+1, mc is a vector<Point2f> array of points and CornersCentroidNow is an empty array waiting to be filled with new points.

When drawing them I use simple code:

for (size_t i = 0; i < CornersCentroidNow.size(); i++){             
    if (feat_errors[i] > MAX_ERR || feat_found[i] == 0) continue; 
    Point p0(ceil(mc[i].x), ceil(mc[i].y)); // are the points of interest (centroids of contours)
    Point p1(ceil(CornersCentroidNow[i].x), ceil(CornersCentroidNow[i].y));     
    arrowedLine(empty, p0, p1, Scalar(0, 0, 255), 2, 8, 0, 0.2);
}

after this block of code. When I draw them every frame I get this output: First step

If I update the previous frame used for calcOpticalFlowPyrLK() function

CentroidFrOld = CentroidFrNow.clone();

I get this output (the line is short and it is moving foward every 10 frames - as set to get new points) Second step

If the previous points happen to be next points as well

CentroidFrOld = CentroidFrNow.clone();
mc = CornersCentroidNow;

I get this output (the line is short, but it is moving along with the object) Third step

The desired output I can't achieve is

Desired out

Do I need to manually lengthen the line? Noone is doing so in similar examples of implemantation of Optical Flow

1
Completely unrelated - I am not trying to draw whole image with OF and the proposed algorithm at the end of the post is basicly the same as I do, but in the newer version of Opencv, in 2013 there was version 2.3.1, completely different from that which is now - Croolman
you're going to need to show more code to troubleshoot this - in particular the actual call to the calcOpticalFlowPyrLK function. If you are setting it up correctly, it should work to simply draw lines between points in the prevPts array and the nextPts array. I would recommend you reduce arrowedLine to a simpler line draw while debugging - those short lines may be misdrawn arrowheads. - foundry
@foundry I have edited a question - Croolman

1 Answers

3
votes
void drawOptFlowMapF(const Mat& flow, Mat& cflowmap, int step, const Scalar& color) {
    for (int y = 0; y < cflowmap.rows; y += step)
        for (int x = 0; x < cflowmap.cols; x += step)
        {
            const Point2f& fxy = flow.at< Point2f>(y, x);
            line(cflowmap, Point(x, y), Point(cvRound(x + fxy.x), cvRound(y + fxy.y)),
                color);
            circle(cflowmap, Point(cvRound(x + fxy.x), cvRound(y + fxy.y)), 1, color, -1);
        }
}
void displayF(Mat flow)
{
    //extraxt x and y channels
    cv::Mat xy[2]; //X,Y
    cv::split(flow, xy);

    //calculate angle and magnitude
    cv::Mat magnitude, angle;
    cv::cartToPolar(xy[0], xy[1], magnitude, angle, true);

    //translate magnitude to range [0;1]
    double mag_max;
    cv::minMaxLoc(magnitude, 0, &mag_max);
    magnitude.convertTo(magnitude, -1, 1.0 / mag_max);

    //build hsv image
    cv::Mat _hsv[3], hsv;
    _hsv[0] = angle;
    _hsv[1] = cv::Mat::ones(angle.size(), CV_32F);
    _hsv[2] = magnitude;
    cv::merge(_hsv, 3, hsv);

    //convert to BGR and show
    cv::Mat bgr;//CV_32FC3 matrix
    cv::cvtColor(hsv, bgr, cv::COLOR_HSV2BGR);
    cv::imshow("optical flow", bgr);
    imwrite("c://resultOfOF.jpg", bgr);
    cv::waitKey(0);
}