Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV 2.3 with VS 2008 - Mouse Events

Obligatory - I'm a newbie. Have a job that involves programming and I'm teaching myself as I go. Needless to say as a teacher I get things wrong frequently and thoroughly.

Where I'm at right now: I've created the class "Graph", it (surprisingly enough) makes graphs. But now I want to make it so that on a mouse click I modify the graph. But I can't seem to get a mouse handler to be a member function of the class.

cv::setMouseCallback(windowName, onMouse, 0); // Set mouse handler to be onMouse

Doesn't work with

cv::setMouseCallback(windowName, Graph::onMouse, 0);

It gives me lack of parameter errors. According to this I can't make it a member function. After following the answer given, it compiles but my this pointer is nulled. Ugh.

OnMouse looks like this:

void onMouse(int event, int x, int y,int, void*)
{
    if (event == CV_EVENT_LBUTTONDOWN)
    {
        cvMoveWindow("Window", 500, 500); //Just to see if stuff happened
    }
    return;
}

I don't care about moving the window, I want to modify the graph itself - which is stored as a cv::Mat variable in a Graph object. And I can't figure out how to do it.

Any help would be appreciated, and I really hope this wasn't just gibberish.

like image 955
Russbear Avatar asked Jul 21 '11 19:07

Russbear


2 Answers

Yes callback functions in C++ are a joy, aren't they? You actually have to give OpenCV a function (not a class method) as you've already found out. However, you can hack around this awfulness using the following technique:

class MyClass
{
public:
     void realOnMouse(int event, int x, int y, int flags)
     {
         // Do your real processing here, "this" works fine.
     }
};

// This is a function, not a class method
void wrappedOnMouse(int event, int x, int y, int flags, void* ptr)
{
    MyClass* mcPtr = (MyClass*)ptr;
    if(mcPtr != NULL)
        mcPtr->realOnMouse(event, x, y, flags);
}

int main(int argv, char** argc)
{
    // OpenCV setup stuff...

    MyClass processor;
    cv::setMouseCallback(windowName, wrappedOnMouse, (void*)&processor);

    // Main program logic

    return 0;
}

That last parameter on setMouseCallback is quite useful for overcoming some of the problems you usually encounter like this.

like image 80
Chris Eberle Avatar answered Nov 15 '22 00:11

Chris Eberle


You can also use the onMouse method as a static method.

class Graph
{
public:
     static void onMouse(int event, int x, int y, void* param)
     {
          //Your code here
     }

     //Everything else you may need
}

Now you should be able to call the onMouse method with:

cv::setMouseCallback(windowName, onMouse, (void*) param);

The param can be NULL or whatever you want to pass as parameter to the method, but you'll need to make a type-cast to the desired type.

Hope this was useful. Bye.

like image 31
André Toshio Avatar answered Nov 15 '22 02:11

André Toshio