Engine
Engine

Reputation: 5422

how to use cv::setMouseCallback

I'm trying to use cv::setMouseCallback in my c++ project. I just don't get it. let that I habe a class Stuff how can tell this class you got a frame and run the cv::setMouseCallback on this frame here is an example of what I'm trying to do :

 class Stuff{
 public: 
Stuff();
void setFrame(cv::Mat); 
void mouse (int,int, int, int,void*);
  private :
cv::Mat frame;
int key;
 };

 Stuff::Stuff(){}

 void Stuff::setFrame(cv::Mat framex){
frame = framex;
 }


  int main (){
Stuff  obj;

cv::Mat frame = cv::imread ("examople.jpg");
char* name;
cv::imshow(name,frame);
cv::setMouseCallback(name,obj.mouse,&frame) // I' stop here because that's exactlly what just don't work 
    }

this the error message that get:

   Stuff::mouse : function call missing argument list; use '&Stuff::mouse ' to create a pointer to member 

the real program is too big to put its code here that why I'm trying to simplify the question

Upvotes: 5

Views: 7892

Answers (2)

CapelliC
CapelliC

Reputation: 60014

you must declare a mouse handler as static inside your class. For instance, I have a dragger with a member mouser, that I want to be called. I declare an helper static void mouser, that cast the void* received and calls the member:

class dragger {

void mouser(int event, int x, int y) {
  current_img = original_img.clone();
  Point P(x, y);
  ...
}
static void mouser(int event, int x, int y, int, void* this_) {
  static_cast<dragger*>(this_)->mouser(event, x, y);
}

and instance in dragger constructor in this way

dragger(string w, Mat m) :
    window_id(w), status(0), original_img(m), /*black(0, 0, 0),*/ K(5, 5)
{
   ...
   setMouseCallback(w, mouser, this);
}

...
}

Upvotes: 3

George Aprilis
George Aprilis

Reputation: 1200

First of all you need to create a named window in the main function. namedWindow( "image", 0 ); or something similar will do the job.

The mouse callback function is not associated to the frame variable but it is associated to the window. In your case it would be:

char* name = "image";
cv::namedWindow( name, 0 );
cv::setMousCallback(name, obj.mouse,&frame);

The callbacks are functions that call other functions when an event happens on a window. For the mouse, an event can be the mouse movement, the left, right or middle clicks. Here you can find a list of them, as well as good explanations.

So when this "event" takes place in the window, opencv calls the function whose name was specified in the setMouseCallback as an argument, in your case Stuff::mouse. if you define the function like this:

Stuff::mouse( int event, int x, int y, int flags, void* params )

when it is called the event variable will be filled with the value of the trigger, the x and y with the positions off the mouse on the image etc. If you want to pass the frame in the mouse function you use it as in this question, if you consider the correction of patxiska's answer.

So with a switch you can find out what kind of event it was:

switch( event ){
    case CV_EVENT_LBUTTONDOWN:
        //...
        break;

    case CV_EVENT_RBUTTONDOWN:
        //...
        break;

    case CV_EVENT_FLAG_CTRLKEY:
        //...
        break;
}

and take your frame typecasting it from void* back to a cv::Mat.

Here you can find another example of Opencv's site on how to use a mouse callback.

Hope I helped, I haven't used opencv for a while and I don't have my sample source files now. Callbacks are simplified in the Opencv GUI but that's the logic of working with any GUI. Input such as mouse and keyboard trigger events and the callback functions pass the events to the functions of your implementation.

Upvotes: 1

Related Questions