Comment utiliser cv :: setMouseCallback en classe?

Je souhaite utiliser cv :: setMouseCallback dans ma classe de parameters pour sélectionner une zone d’une image. Ceci est mon 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 & 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 & contour){ vector insideContour; for(int j = 0; j < src.rows; j++){ for(int i = 0; i = 0) // yes inside insideContour.push_back(p); } } cout << "# points inside contour: " << insideContour.size() << endl; savePointsAsXML(insideContour); } 

Je reçois des tonnes de références indéfinies aux parameters: coor, Paramètres: src, Paramètres: couleur. J’ai du mal à comprendre ce qui doit être statique pour que cela fonctionne. Voici mon en-tête:

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

Qu’est-ce qui me manque dans mon code?

Comme OpenCV a une interface semblable à C, il ne prend pas de fonction membre comme rappel, mais vous pouvez utiliser des moyens standard pour y remédier et passer l’instance de la classe comme paramètre userdata , puis la userdata instance et appeler la méthode member. Voici un extrait:

 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(userdata); settings->onMouse(event, x, y); } 

J’espère que cela explique l’idée, je l’ai écrit en ligne et je suis désolé pour les fautes de frappe.

Vous pouvez également utiliser un pointeur global qui pointe sur votre object et appeler votre fonction membre à partir de la fonction de rappel non membre.

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

Cela peut être utile pour quelqu’un. Ma version est sans utilisation de pointeurs globaux, mais avec des fonctions d’amis:

 class App { public: App(); ~App(); void setWin(const std::ssortingng& _winname); ... private: void on_mouse_internal(int ev, int x, int y); std::ssortingng 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(obj); if (app) app->on_mouse_internal(ev, x, y); } App::App() { ... } App::~App() { ... } void App::setWin(const std::ssortingng& _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 } ...