在创建OpenCV的mouseCallback函数的基于类的实现时遇到问题

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

本文关键字:实现 遇到 问题 于类 函数 创建 OpenCV mouseCallback      更新时间:2023-10-16

正如标题所示,我在基于类的C++结构中实现OpenCV的mouseCallback函数时遇到了一些问题。请允许我解释一下。我定义了一个名为BriskMatching的类,在其中我创建了一个成员函数mouseCallback,该函数具有OpenCV所需的正确参数(请参阅下面的代码片段)。

**Briskmatching.h**
class BriskMatching
{
public:
    BriskMatching();
    ~BriskMatching();
public:
    void mouseCallback(int event, int x, int y, int flags, void *param);
};

这一切都很好,但是当我试图通过OpenCV的cv::setMouseCallback函数将此函数设置为指定的鼠标回调函数时,我的问题就出现了。

在我的主函数中,我创建了一个名为briskMatcher的BriskMatching类的实例,然后当需要设置鼠标回调时,我会尝试这样做…

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

不幸的是,这引发了一个错误。

Error   3   error C3867: 'BriskMatching::mouseCallback': function call missing argument list; use '&BriskMatching::mouseCallback' to create a pointer to member c:usersmobilefdocumentsvisual studio 2010projectsopencv_objtrackingopencv_briskmatchingmain.cpp 54  1   OpenCV_BriskMatching

我可以通过在BriskMatching.h中将mouseCallback函数声明为static来消除这个错误,但由于我在mouseCallback函数中引用了许多非静态成员变量,因此我得到了一大堆其他错误。

所以我想问你们的问题是。我应该如何修改我的代码,以便能够正确地将BriskMatching类中声明的mouseCallback函数传递给cv::setMouseCallback函数?

提前感谢您的帮助!

由于成员函数采用this指针,因此需要一个静态包装函数。通常,您使用param参数作为成员函数所属对象的地址,因此您最终会得到这样的结果:

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

然后在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);
}

我也在使用这个方法,但我意识到静态助手类非常严格,并且有类型和方法限制。

为了进一步参考,我定义了一个模板化的免费函数,看起来像:

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);
    }
}

我现在可以用调用类内部的任意函数(匹配签名,但不匹配名称)

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

如果还需要void*ptr,它可能会被扩展,但我在这里省略了它。