在C ++中提供对类数据成员的回调函数访问

时间:2012-12-27 23:09:21

标签: c++ opencv callback

我在我的项目中使用C ++中的opencv库,但是我在使用MouseCallback时遇到了问题。

我有一个类BoardCalibration,它有两个数据成员,我需要在回调函数中使用它们。你可以在下面看到这个课程:

class BoardCalibration{
private:
    Rect _box;  <-- data members i need to upadte inside the callback function
    bool _drawingBox; <--

public:
    BoardCalibration();
    static void my_mouse_callback(int event, int x, int y, int flags, void* param);
    Rect calibrate(Mat& image);
    void drawBox(IplImage* img);
};

在calibrate()方法中调用接收回调my_mouse_callback函数的函数。代码:

Rect BoardCalibration::calibrate(Mat& image){
    IplImage * img = new IplImage(image);

    namedWindow("Calibration");

    IplImage *temp = cvCloneImage(img);
    cvSetMouseCallback("Calibration", my_mouse_callback, (void *)img);

    while (1){

        imshow("Calibration", Mat(img));
        cvCopyImage(img,temp);

        if( _drawingBox ){
            drawBox(temp);
        }

        imshow("Calibration", Mat(temp));

        if (waitKey(1)>=0)
            break;
    }

    cout << "calibrated\n";

    delete img;
    return _box;
}

my_mouse_callback的实现是:

static void my_mouse_callback(int event, int x, int y, int flags, void* param){

    IplImage* image = (IplImage*) param;

    switch( event ) {
    case CV_EVENT_MOUSEMOVE: {
        if( _drawingBox ) {
            _box.width  = x-_box.x;
            _box.height = y-_box.y;
        }
                             }
                             break;
    case CV_EVENT_LBUTTONDOWN: {
        _drawingBox = true;
        _box = Rect( x, y, 0, 0 );
                               }
                               break;   
    case CV_EVENT_LBUTTONUP: {
        _drawingBox = false; 
        if( _box.width<0 ) { 
            _box.x+=_box.width;  
            _box.width *=-1; 
        }
        if( _box.height<0 ) { 
            _box.y+=_box.height; 
            _box.height*=-1; 
        }

        //drawBox(image, box);  // keep draw on screen
        // display rectangle coordinates
        cout << "TopLeft: (" << _box.x << "," << _box.y << "), BottomRight: (" 
            << _box.x+_box.width << "," << _box.y+_box.height << ")" << endl;
                             }
                             break;
    }
}

正如你所看到的那样,我试图在这里找到_box和_drawingBox成员,但因为它是静态方法,所以它无法识别它们。 我怎么解决这个问题??我无法更改my_mouse_callback的原型,否则cvSetMouseCallback不会接受它。 我也无法在类之外定义那些数据成员,因为它给了我已经定义的错误。 还有什么我可以尝试??? 感谢。

3 个答案:

答案 0 :(得分:6)

我对opencv一无所知,但是这个怎么样

struct Helper
{
    IplImage * pI;
    BoardCalibration * pObj;
};


Rect BoardCalibration::calibrate(Mat& image)
{
    .... stuff ....

    Helper * p = new Helper;
    p->pI = img;
    p->pObj = this;

    cvSetMouseCallback("Calibration", my_mouse_callback, (void *)p);

    .... stuff ...   


    delete p;
    delete img;
    return _box;

}


static void BoardCalibration::my_mouse_callback(int event, int x, int y, int flags, void* param)
{
    Helper * p = (Helper *)param;
    IplImage* image = p->pI;
    BoardCalibration * pBC = p->pObj;

    switch( event ) 
    {
        case CV_EVENT_MOUSEMOVE: 
        {
            if( pBC->_drawingBox )  // use the pBC pointer

            ... stuff ...


    }

    ... stuff ...

}

我不知道您的代码流程,以确定何时应该删除辅助对象。所以我在delete Helper object附近有delete img代码,因为如果该代码是正确的,那么这也可能是delete Helper对象的正确位置。但你需要检查一下。只有当您确定到那时该回调将完成为该调用运行时,您才需要删除此对象。

答案 1 :(得分:1)

好的,我明白了。你应该这样做。它已经成功了。

1) cvSetMouseCallback("Calibration", my_mouse_callback, (void *)this); // Callback function to give it a this pointer.
2) BoardCalibration* ptr = (BoardCalibration*) param; // ptr pointer to your class.
3) e.g ptr->  _box oder ptr-> _drawingBox //all the private parameters,that you need to use, do this:
祝你好运。我希望它能帮助你解决问题。 比特塞尔。 Qiuyue Wang。

答案 2 :(得分:0)

我不知道细节如何做,但我有一个想法,如果我们可以

cvSetMouseCallback("Calibration", my_mouse_callback, (void *)img);

param(object)是要传递给回调函数的用户定义参数。 因此,如果我们可以代替img,请使用pointer指向class,也许我们可以使用this->所有私有参数或class。功能。 但我有这个想法,你应该尝试一下,也许是成功的......

祝你好运。 告诉我你是否成功了。 旺。