1

How can I add roi-based selection in lkdemo.pp( klt optical flow tracker opencv example) source code? I want select roi in the first frame and track feature point that selected in roi.

#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <ctype.h>

using namespace cv;
using namespace std;

static void help()
{
    // print a welcome message, and the OpenCV version
    cout << "\nThis is a demo of Lukas-Kanade optical flow lkdemo(),\n"
            "Using OpenCV version " << CV_VERSION << endl;

}

Point2f point;
bool addRemovePt = false;

static void onMouse( int event, int x, int y, int , void* )
{
    if( event == CV_EVENT_LBUTTONDOWN )
    {
        point = Point2f((float)x, (float)y);
        addRemovePt = true;
    }
}

int main( int argc, char** argv )
{
    help();

    VideoCapture cap(CV_CAP_ANY);
    TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.03);
    Size subPixWinSize(10,10), winSize(61,61);

    const int MAX_COUNT = 500;
    bool needToInit = false;
    bool nightMode = false;

    //if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
        //cap.open(argc == 2 ? argv[1][0] - '0' : 0);
    //else if( argc == 2 )
        //cap.open(argv[1]);

    if( !cap.isOpened() )
    {
        cout << "Could not initialize capturing...\n";
        return 0;
    }

    namedWindow( "LK Demo", 1 );
    setMouseCallback( "LK Demo", onMouse, 0 );

    Mat gray, prevGray, image;
    vector<Point2f> points[2];

    for(;;)
    {
        Mat frame;
        cap >> frame;
        if( frame.empty() )
            break;

        frame.copyTo(image);
        cvtColor(image, gray, COLOR_RGB2GRAY);

        if( nightMode )
            image = Scalar::all(0);

        if( needToInit )
        {
            // automatic initialization
            goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
            cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
            addRemovePt = false;
        }
        else if( !points[0].empty() )
        {
            vector<uchar> status;
            vector<float> err;
            if(prevGray.empty())
                gray.copyTo(prevGray);
            calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize,10, termcrit, 0, 0.001);
            size_t i, k;
            for( i = k = 0; i < points[1].size(); i++ )
            {
                if( addRemovePt )
                {
                    if( norm(point - points[1][i]) <= 5 )
                    {
                        addRemovePt = false;
                        continue;
                    }
                }

                if( !status[i] )
                    continue;

                points[1][k++] = points[1][i];
                circle( image, points[1][i], 3, Scalar(0,255,0), -1, 8);
            }
            points[1].resize(k);
        }

        if( addRemovePt && points[1].size() < (size_t)MAX_COUNT )
        {
            vector<Point2f> tmp;
            tmp.push_back(point);
            cornerSubPix( gray, tmp, winSize, cvSize(-1,-1), termcrit);
            points[1].push_back(tmp[0]);
            addRemovePt = false;
        }

        needToInit = false;
        imshow("LK Demo", image);

        char c = (char)waitKey(10);
        if( c == 27 )
            break;
        switch( c )
        {
        case 'r':
            needToInit = true;
            break;
        case 'c':
            points[0].clear();
            points[1].clear();
            break;
        case 'n':
            nightMode = !nightMode;
            break;
        }

        std::swap(points[1], points[0]);
        cv::swap(prevGray, gray);
    }

    return 0;
}
Opal
  • 81,889
  • 28
  • 189
  • 210
v sadegh
  • 11
  • 1
  • 3

1 Answers1

0

Here is what I use in those cases :

void SelectNewTemplate(int event, int posx, int posy, int flags, void* userdata)
{
    if( event == EVENT_MBUTTONDOWN )
    {
        waitKey();
    }
    if( event == CV_EVENT_LBUTTONDOWN )
    {
        x1pt = posx;
        y1pt = posy;
    }
    if( event == CV_EVENT_LBUTTONUP )
    {
        x2pt = posx;
        y2pt = posy;

        Rect newTemp(x1pt, y1pt, (x2pt - x1pt), (y2pt - y1pt));
        Mat imgROI = frame(newTemp);
    }
}

Usage : pausing the video with middle mouse button, then left clic, drag and let go, press any key to keep going.


After that you can compute your features on your new ROI image : imgROI.

Hope that helps, Thomas

Thom
  • 495
  • 3
  • 12