Casey Wang
Casey Wang

Reputation: 45

OpenCV return value from setMouseCallBack in for loop

I am using the setMouseCallBack function to extract pixel coordinate. It can work if the for-loop change to while(1).

Now, I would like to run and record the pixel coordinate value only for 24 times. But, the for-loop doesn't work. How should I do by using setMouseCallBack function?

Thanks!

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;

void mouse_call(int  event, int  x, int  y, int  flag, void *param)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        Point *p = (Point*)param;
        p->x = x;
        p->y = y;
    }
    if (event == EVENT_LBUTTONUP)
    {
        Point *p = (Point*)param;
        p->x = x;
        p->y = y;
    }
}
int main(int argc, char** argv)
{
    static Point p;
    int cor[24][2] = {0};
    string filename;
    cout << "Filename: ";
    cin >> filename;
    img = imread(filename);
    resize(img, img, Size(), 0.5, 0.5, 1);
    namedWindow("Image"); 
    imshow("Image", img); 

    for(int i = 0; i < 24; i++)
    {
        setMouseCallback("Image", mouse_call);
        cor[i][0] = p.x
        cor[i][1] = p.y
    }

    waitKey(0);
    return(0);
}

Upvotes: 2

Views: 2791

Answers (2)

Miki
Miki

Reputation: 41765

You need to set the callback only once. And you need to tell which variable you're passing as param.

I modified a little your code in order to keep it simple:

  • the coordinates are stored in a vector<Point>
  • the vector of coordinates is a global variable. This make a toy program like this easier. For real application, it will probably be a class member.
  • I pass a status flag as parameter of the callback, and it turns true when I reached the required number of points
  • I added a loop that waits for the given number of points to be collected
  • I collect a point only on mouse down event.

Here the code:

#include <opencv2\opencv.hpp>
#include <vector>
#include <iostream>
using namespace cv;
using namespace std;

vector<Point> coords;
int N = 3;

void mouse_call(int  event, int  x, int  y, int  flag, void *param)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        coords.push_back(Point(x,y));

        // Debug
        copy(coords.begin(), coords.end(), ostream_iterator<Point>(cout, " "));
        cout << endl;

        if (coords.size() == N)
        {
            bool* exitflag = static_cast<bool*>(param);
            *exitflag = true;
        }
    }
}

int main()
{
    bool bExit = false;

    string filename;
    cout << "Filename: ";
    cin >> filename;
    Mat3b img = imread(filename);
    resize(img, img, Size(), 0.5, 0.5, 1);

    namedWindow("Image");

    // Set callback
    setMouseCallback("Image", mouse_call, static_cast<void*>(&bExit));

    imshow("Image", img);

    while (!bExit)
    {
        waitKey(30);
    }

    cout << "Found " << N << " points... Exit" << endl;

    return(0);
}

Upvotes: 2

s1hofmann
s1hofmann

Reputation: 1551

Altough your question is a bit unspecific I think your actual problem is quite simple.

Your for loop does work, but you have to keep in mind that there are a lot more mouse events.

Your mouse_call handler also gets spammed with movements events which are neglected by your handler. And since the loop only runs 24 times it has no actual chance to capture a button down event before it's finished.

Upvotes: 1

Related Questions