Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在课堂上使用cv::setMouseCallback?_C++_Opencv - Fatal编程技术网

C++ 如何在课堂上使用cv::setMouseCallback?

C++ 如何在课堂上使用cv::setMouseCallback?,c++,opencv,C++,Opencv,我想在设置类中使用cv::setMouseCallback来选择图片的一个区域。这是我的代码: 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

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

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);
}
void Settings::on_buttonXML_clicked(){
视频捕捉网络摄像机;
网络摄像头。打开(索引);
网络摄像头读取(src);
颜色=标量(0,0255);
coor_num=0;
xmlPath=“C:/myregion.xml”;
cv::namedWindow(“imageWindow”,cv\u WINDOW\u AUTOSIZE);
cv::imshow(“图像窗口”,src);
cv::setMouseCallback(“imageWindow”,onMouse,0);
cv::waitKey(0);
}
void设置::onMouse(int事件、int x、int y、int、void*){
if(event==CV\u event\u LBUTTONUP){
点2f p(x,y);
合作推回(p);
线条(src、p、p、颜色);
如果(coor.size()>1)
行(src,p,coor[coor.size()-2],颜色);
imshow(“图像窗口”,src);
}
else if(event==CV_event_RBUTTONUP&&coor.size()>2){
行(src,coor[0],coor[coor.size()-1],颜色);
getPointsInContour(coor);
imshow(“图像窗口”,src);
waitKey(2000年);
出口(0);
}
}
void设置::savePointsAsXML(向量和轮廓){
TiXmlDocument文档;
TIXmlDecl(“1.0”、“1.0”、“1.0”);
插入子文档(decl);
对于(int i=0;icout因为OpenCV有一个类似C的接口,所以它不使用成员函数作为回调函数,但您可以使用标准方法来克服这一问题,并将类实例作为
userdata
参数传递,然后将其转换回实例并调用member方法。下面是一个片段:

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);
}
void Settings::on_buttonXML_clicked(){
视频捕捉网络摄像机;
网络摄像头。打开(索引);
网络摄像头读取(src);
颜色=标量(0,0255);
coor_num=0;
xmlPath=“C:/myregion.xml”;
cv::namedWindow(“imageWindow”,cv\u WINDOW\u AUTOSIZE);
cv::imshow(“图像窗口”,src);
cv::setMouseCallback(“imageWindow”,onMouse,this);//在此处传递类实例指针
cv::waitKey(0);
}
//在标题中,创建onMouse的静态版本和成员版本
void onMouse(int事件,int x,int y);
鼠标上的静态void(int事件、int x、int y、int、void*userdata);
//实现它以调用成员函数
void设置::onMouse(int事件、int x、int y、int、void*userdata)
{
//检查userdata中的空指针并处理错误
...
设置*Settings=reinterpret\u cast(用户数据);
设置->onMouse(事件,x,y);
}

希望这能解释这个想法,我是内联编写的,因此我很抱歉有任何打字错误。

您也可以使用指向对象的全局指针,并从非成员回调函数调用成员函数

Class SomeClass
{
   ...
public:
   void callback(int event, int x, int y);
   ...
};

SomeClass* g_ptr;

void onMouse(int event, int x, int y, void*)
{
    g_ptr->callback(event, x, y);
}

void func(void)
{
   SomeClass obj;
   g_ptr = &obj; // Make the global variable point to your object
   cv::namedWindow("winname");
   cv::setMouseCallback("winname", onMouse, 0);
   ...
}

它可能对某些人有用。我的版本不使用全局指针,但使用友元函数:

class App
{
public:
  App();
  ~App();
  void setWin(const std::string& _winname);
  ...
private:
  void on_mouse_internal(int ev, int x, int y);

  std::string winname;

  friend void on_mouse(int ev, int x, int y, int, void* obj);
  ...
};
void on_mouse(int ev, int x, int y, int, void* obj)
{
  App* app = static_cast<App*>(obj);
  if (app)
    app->on_mouse_internal(ev, x, y);
}

App::App()
{
  ...
}

App::~App()
{
  ...
}

void App::setWin(const std::string& _winname)
{
  cv::namedWindow(_winname);
  this->winname = _winname;
  cv::setMouseCallback(winname, on_mouse, this);
}

void App::on_mouse_internal(int ev, int x, int y)
{
  std::cout << "X:" << x << ";Y:" << y << std::endl;
  // here you can specify class members
}
...
class应用程序
{
公众:
App();
~App();
void setWin(const std::string&_winname);
...
私人:
鼠标内部无效(int-ev、int-x、int-y);
std::字符串winname;
鼠标上的朋友无效(int-ev,int-x,int-y,int,void*obj);
...
};
鼠标上的空格(int-ev、int-x、int-y、int、void*obj)
{
App*App=static_cast(obj);
如果(应用程序)
应用程序->鼠标内部(ev、x、y);
}
App::App()
{
...
}
App::~App()
{
...
}
void App::setWin(const std::string&_winname)
{
cv::namedWindow(_winname);
此->winname=\u winname;
cv::setMouseCallback(winname,在鼠标上,这个);
}
void应用程序::在鼠标内部(int-ev、int-x、int-y)
{

我不能谢谢你!这正是我需要的
class App
{
public:
  App();
  ~App();
  void setWin(const std::string& _winname);
  ...
private:
  void on_mouse_internal(int ev, int x, int y);

  std::string winname;

  friend void on_mouse(int ev, int x, int y, int, void* obj);
  ...
};
void on_mouse(int ev, int x, int y, int, void* obj)
{
  App* app = static_cast<App*>(obj);
  if (app)
    app->on_mouse_internal(ev, x, y);
}

App::App()
{
  ...
}

App::~App()
{
  ...
}

void App::setWin(const std::string& _winname)
{
  cv::namedWindow(_winname);
  this->winname = _winname;
  cv::setMouseCallback(winname, on_mouse, this);
}

void App::on_mouse_internal(int ev, int x, int y)
{
  std::cout << "X:" << x << ";Y:" << y << std::endl;
  // here you can specify class members
}
...