szakeri
szakeri

Reputation: 159

Having trouble creating a class based implementation of OpenCV's mouseCallback function

As the title suggest, I'm having some trouble implementing OpenCV's mouseCallback function in a class based C++ structure. Allow me to explain. I have defined a class called BriskMatching in which I have created a member function named mouseCallback with the correct parameters that OpenCV requires (please see the code snippet below).

**Briskmatching.h**

class BriskMatching
{
public:
    BriskMatching();
    ~BriskMatching();

public:
    void mouseCallback(int event, int x, int y, int flags, void *param);
};

This is all fine, however my problem arises when I try to set this function as the designated mouse callback function through OpenCV's cv::setMouseCallback function.

In my main function, I create an instance of the BriskMatching class called briskMatcher then when it comes time to set the mouse callback I attempt to do it like so...

cv::setMouseCallback("Matches", BriskMatching::mouseCallback, &matchesImg);

Unfortunately, this throws an error.

Error   3   error C3867: 'BriskMatching::mouseCallback': function call missing argument list; use '&BriskMatching::mouseCallback' to create a pointer to member c:\users\mobilef\documents\visual studio 2010\projects\opencv_objtracking\opencv_briskmatching\main.cpp 54  1   OpenCV_BriskMatching

I could get rid of this error by declaring the mouseCallback function as static in BriskMatching.h but then I get a whole whack of other errors since I refer to many non-static member variables in the mouseCallback function.

So my question to you guys is this. How should I modify my code to be able to properly pass my mouseCallback function declared within the BriskMatching class to the cv::setMouseCallback function?

Thanks for all your help in advanced!

Upvotes: 5

Views: 2641

Answers (2)

Mats Petersson
Mats Petersson

Reputation: 129374

Since a member function takes a this pointer, you will need a static wrapper function. Typically, you use the param parameter to be the address of the object that the member function belongs to, so you end up with something like this:

...
static void mouseCallback(int event, int x, int y, int flags, void *param);

void doMouseCallback(int event, int x, int y, int flags);

And then inside the mouseCallback:

void BriskMatching::mouseCallback(int event, int x, int y, int flags, void *param)
{
    BriskMatching *self = static_cast<BriskMatching*>(param);
    self->doMouseCallback(event, x, y, flags);
}

Upvotes: 12

Samuel
Samuel

Reputation: 6490

I was using this method too, however I realized that the static helper class was quite rigid and type and method bound.

Just for further reference I've defined a templated free function that looks like:

template<typename TClass, void (TClass::*MouseClickType)(int, int, int, int)>
void FreeOnMouseCallback(int event, int x, int y, int flags, void* ptr)
{
    auto* mcPtr = static_cast<TClass*>(ptr);
    if(mcPtr != NULL)
    {
      (mcPtr->*MouseClickType)(event, x, y, flags);
    }
}

And I can now call arbitrary functions (matching the signature, but not the name) inside classes with

 cv::setMouseCallback( WindowName, FreeOnMouseCallback<Calibrator, &Calibrator::OnMouseCallback>, this );

It might be extended if the void* ptr is also required, but I've omitted it here.

Upvotes: 0

Related Questions