如何在类中使用cv :: setMouseCallback? [英] How to use cv::setMouseCallback in class?

查看:876
本文介绍了如何在类中使用cv :: setMouseCallback?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的设置类中使用cv :: setMouseCallback来选择图片的一个区域。这是我的代码:

I want to use cv::setMouseCallback inside my settings class to select an area of a picture. This is my code:

void Settings::on_buttonXML_clicked(){
    cv::VideoCapture webcam;
    webcam.open(INDEX);    
    webcam.read(src);
    color = Scalar(0,0,255);
    coor_num = 0;
    xmlPath="C:/myregion.xml";
    cv::namedWindow("imageWindow", CV_WINDOW_AUTOSIZE );
    cv::imshow("imageWindow", src);
    cv::setMouseCallback( "imageWindow", onMouse, 0 );
    cv::waitKey(0);

}

void Settings::onMouse(int event, int x, int y, int, void* ) {
    if (event == CV_EVENT_LBUTTONUP) {
        Point2f p(x, y);
        coor.push_back(p);
        line(src,p,p,color);
        if(coor.size()>1)
            line(src, p, coor[coor.size()-2], color);
        imshow("imageWindow", src);
    }
    else if (event == CV_EVENT_RBUTTONUP && coor.size()>2){
        line(src, coor[0], coor[coor.size()-1], color);
        getPointsInContour(coor);
        imshow("imageWindow", src);
        waitKey(2000);
        exit(0);
    }
}
void Settings::savePointsAsXML(vector<Point2f> & contour){
    TiXmlDocument doc;
    TiXmlDeclaration decl("1.0", "", "");
    doc.InsertEndChild(decl);
    for(int i = 0; i < contour.size(); i++)
    {
        TiXmlElement point("point");
        point.SetAttribute("x",contour[i].x);
        point.SetAttribute("y",contour[i].y);
        doc.InsertEndChild(point);
    }
    if(doc.SaveFile(xmlPath.c_str()))
        cout << "file saved succesfully.\n";
    else
        cout << "file not saved, something went wrong!\n";
}

void Settings::getPointsInContour(vector<Point2f> & contour){
    vector<Point2f> insideContour;
    for(int j = 0; j < src.rows; j++){
        for(int i = 0; i < src.cols; i++){
            Point2f p(i,j);
            if(cv::pointPolygonTest(contour,p,false) >= 0) // yes inside
                insideContour.push_back(p);
        }
    }
    cout << "# points inside contour: " << insideContour.size() << endl;
    savePointsAsXML(insideContour);
}



我会收到大量未定义的参数:coor,settings:src ,设置:颜色。我有麻烦了解什么需要是静态的,它的工作。这是我的标题:

I'm getting tons of undefined reference to Settings:coor, Settings:src, Settings:color. I'm having trouble understanding what needs to be static for it to work. This is my header:

class Settings
{
private:        
    static void onMouse(int event, int x, int y, int, void* );
    static void savePointsAsXML(std::vector<cv::Point2f> & contour);
    static void getPointsInContour(std::vector<cv::Point2f> & contour);
    static cv::Scalar color;
    static std::vector<cv::Point2f> coor;
    static int coor_num;
    static std::string xmlPath;
    static cv::Mat src;

我的代码中缺少什么?

推荐答案

由于OpenCV有一个类似C的接口,它不需要一个成员函数作为回调,但你可以使用标准的方法来克服这个问题,并传递类实例为 userdata 参数,然后将其转换回实例并调用成员方法。这是一个代码片段:

Since OpenCV has a C like interface it does not take a member function as the callback but you can use standard means to overcome this and pass the class instance as the userdata parameter, then cast it back to the instance and call the member method. Here is a snippet:

void Settings::on_buttonXML_clicked(){
    cv::VideoCapture webcam;
    webcam.open(INDEX);    
    webcam.read(src);
    color = Scalar(0,0,255);
    coor_num = 0;
    xmlPath="C:/myregion.xml";
    cv::namedWindow("imageWindow", CV_WINDOW_AUTOSIZE );
    cv::imshow("imageWindow", src);
    cv::setMouseCallback( "imageWindow", onMouse, this ); // Pass the class instance pointer here
    cv::waitKey(0);
}

// In you header make a static and a member version of onMouse
void onMouse(int event, int x, int y);
static void onMouse(int event, int x, int y, int, void* userdata);

// Implement it to call the member function
void Settings::onMouse(int event, int x, int y, int, void* userdata)
{
    // Check for null pointer in userdata and handle the error
    ...
    Settings* settings = reinterpret_cast<Settings*>(userdata);
    settings->onMouse(event, x, y);
}

希望这解释了这个想法,我写它的内联,所以我很抱歉任何拼写错误。

Hope this explains the idea, I wrote it inline and so I'm sorry for any typos.

这篇关于如何在类中使用cv :: setMouseCallback?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆