Ask Your Question
0

OpenCV issue with drawing Farneback optical flow in ROI.

asked 2017-02-20 04:36:15 -0500

kieranfish gravatar image

Hey hey, I've written a code to create bounding boxes and draw the Farneback optical flow inside. The optical flow is calculated normally before hand and then it is drawn separately for each ROI box.

The problem comes when I draw the flow. The flow comes out looking normal, but shifted down and right. Here's the output, notice the bottom right has the flow of the moving person.

person is moving but flow drawn in wrong place

Here is the frame with the flow drawn everywhere, showing where the flow should be drawn.

Flow drawn everywhere to show where it should be

The code attached is stripped down for simplicity, so excuse me if there are a few undeclared Matrices or something.

#include ...

using namespace cv;
using namespace std;

Mat currentImage, img, printr, gray ,prevgray, flow;

void getRectanglesandROI(Mat &Mask, Mat &imgTmp, Mat &imgOut, vector<Rect> &outBoxes);

void DrawFlowMap(Mat Image, Mat ROI, Rect Box, Point centre);

int main (int argc, char *argv[]) {

    VideoCapture inVid("input.avi");

    if (!inVid.isOpened()) {
        cout << "Failed to open the input video" << endl;
        exit(5);}

    int loop=0, count =0, MaxTargets=0;
bool test=true; 

    namedWindow("Detected");

    int ex = inVid.get(CV_CAP_PROP_FOURCC);
    double fps = inVid.get(CV_CAP_PROP_FPS);
    int wait=1000/fps;
    Size S = Size(  (int) inVid.get(CV_CAP_PROP_FRAME_WIDTH), (int) inVid.get(CV_CAP_PROP_FRAME_HEIGHT));
    int fr =inVid.get(CV_CAP_PROP_FRAME_COUNT);

    VideoWriter output;                                        // Open the output
    output.open("output.avi", ex, fps, S, true);
    if (!output.isOpened())
        {
            cout  << "Could not open the output video for write: " << endl;
            return -1;
        }
//=============4EVR=================
    while(test){

    inVid>>currentImage;
        if (currentImage.empty())
        {
            count++;
            //if (count==1){if (waitKey(0)==27){waitKey(2);}}
            if (count==1){fs.release(); break;}
            cout <<"Max Targets=" <<MaxTargets<< endl<< "End of video, looping" << endl<<endl;
            inVid.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
            loop=0;
        }

        cvtColor(currentImage, gray,CV_RGB2GRAY);
        if (prevgray.empty()){gray.copyTo(prevgray);}

        currentImage.copyTo(img);

        calcOpticalFlowFarneback(prevgray,gray,flow,0.5,3,21,20,5,1.2,0);

        vector<Rect> outputBoxes;
        getRectanglesandROI(fgMaskMOG2, img, currentImage, outputBoxes);
        gray.copyTo(prevgray);

        imshow("Detected", currentImage);
        waitKey(wait);
    }
    return 0;
}
//============END===========================================================

void getRectanglesandROI(Mat &Mask, Mat &imgTmp, Mat &imgOut, vector<Rect> &outBoxes){

    vector<vector<Point> > v; 
vector<int> targets;
int tarArea=1;

    findContours(Mask, v, CV_RETR_EXTERNAL/*CV_RETR_LIST*/, CV_CHAIN_APPROX_SIMPLE);

    for (int j = 0; j < v.size(); j++) {
            if (tarArea < v[j].size()) { // excluding tiny contours
                    targets.push_back(j);
            }
    }
        for (int j = 0; j < targets.size(); j++) {  
            drawContours(imgTmp, v, targets[j], Scalar(255, 0, 255), 1, 8);
            Rect rect = boundingRect(v[targets[j]]);

            roi=currentImage(rect);
            DrawFlowMap(currentImage, roi, rect);
            }
}

void DrawFlowMap(Mat Image, Mat ROI, Rect Box){

Point pt1 = Point(Box.x, Box.y);

for( int y=0; y<roi.rows; y+=5){        //this is the issue area, probably.
    for (int x=0;x<roi.cols;x+=5){
        const Point2f& flowatxy=flow.at<Point2f>(y,x);

            line(Image, Point(cvRound(pt1.x+x),             cvRound(pt1.y+y)),
                        Point(cvRound(pt1.x+x+flowatxy.x),  cvRound(pt1.y+y+flowatxy.y)),   Scalar(0,255,0)); ///FLOW LINES
    }
}
}
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2017-02-20 04:48:00 -0500

berak gravatar image

since you calculate the flow on your "large" image, the point coords are not related to your ROI.

try without adding your Point pt1:

for (int y=0; y<roi.rows; y+=5) {
    for (int x=0;x<roi.cols;x+=5) {
        const Point2f& flowatxy=flow.at<Point2f>(y,x);
        line(Image, Point(x,y),
                    Point(cvRound(x+flowatxy.x), cvRound(y+flowatxy.y)), Scalar(0,255,0));
    }
}
edit flag offensive delete link more

Comments

@berak Well, this might be better but it still isn't right. Now it draws it up in the top left corner, which makes sense if you look at the first points in the line function. The for loops will start plotting the line at (0,0) and then (1,0) and so on.

But at least now, it seems like it is plotting the correct flow for the ROI, just in the wrong place. If that makes sense.

kieranfish gravatar imagekieranfish ( 2017-02-20 05:27:40 -0500 )edit

@berak I'VE DONE IT!

I just changed the flowatxy declaration to: const Point2f& flowatxy=flow.at<point2f>( pt1.y+y , pt1.x+x );

kieranfish gravatar imagekieranfish ( 2017-02-20 07:12:06 -0500 )edit
0

answered 2017-02-20 07:12:47 -0500

kieranfish gravatar image

This solved it:

const Point2f& flowatxy=flow.at<Point2f>( pt1.y+y , pt1.x+x );
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2017-02-20 04:36:15 -0500

Seen: 430 times

Last updated: Feb 20 '17