c++ - How to make cv::setMouseCallback function work -
i've seen few questions same. still unable make code work after reading answers. sorry in advance if repeating posts.
i managed write code :
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <string> bool leftbuttondown = false, leftbuttonup = false; cv::mat img; cv::point cor1, cor2; cv::rect rect; void mousecall(int event, int x, int y, int, void*) { if (event == cv::event_lbuttondown) //finding first corner { leftbuttondown = true; cor1.x = x; cor1.y = y; std::cout << "corner 1: " << cor1 << std::endl; } if (event == cv::event_lbuttonup) { if (abs(x - cor1.x)>20 && abs(y - cor1.y)>5) //finding second corner , checking whether region small { leftbuttonup = true; cor2.x = x; cor2.y = y; std::cout << "corner 2: " << cor2 << std::endl; } else { std::cout << "select more 5 pixels" << std::endl; } } if (leftbuttondown == true && leftbuttonup == false) //when left button clicked , let off { //draw rectangle continuously cv::point pt; pt.x = x; pt.y = y; cv::mat temp_img = img.clone(); rectangle(temp_img, cor1, pt, cv::scalar(0, 0, 255)); cv::imshow("original", temp_img); } else if (event == cv::event_mousemove) //tracking mouse movement { std::cout << "mouse moving on window - position (" << x << ", " << y << ")" << std::endl; } if (leftbuttondown == true && leftbuttonup == true) //when selection done { rect.width = abs(cor1.x - cor2.x); rect.height = abs(cor1.y - cor2.y); rect.x = cv::min(cor1.x, cor2.x); rect.y = cv::min(cor1.y, cor2.y); cv::mat cuttempimg(img, rect); //selecting roi(region of interest) original img cv::namedwindow("cut temporary image"); cv::imshow("cut temporary image", cuttempimg); //showing cropped image leftbuttondown = false; leftbuttonup = false; } } int main(){ img = cv::imread("image.jpg"); cv::namedwindow("original"); cv::imshow("original", img); cv::setmousecallback("original", mousecall); //setting mouse callback selecting region mouse while (char(cv::waitkey(1) != 'q')) //waiting 'q' key finish execution { } return 0; } and working fine. want make same code, using class.(oop)
but cv::setmousecallback function not letting me that. can 1 me fix this?
my second code :
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <string> class resizeimage { cv::mat img; cv::point cor1, cor2; cv::rect rect; std::string name; public: void setimg(cv::mat img) { this->img = img; }; cv::mat getimg() { return img; }; void setrect(); int getcoordinates1x() { return cor1.x; }; int getcoordinates1y() { return cor1.y; }; int getcoordinates2x() { return cor2.x; }; int getcoordinates2y() { return cor2.y; }; void setcoordinates1(int x, int y) { this->cor1.x = x; this->cor1.y = y; }; void setcoordinates2(int x, int y) { this->cor2.x = x; this->cor2.y = y; }; void mousecall(int event, int x, int y, int flags, void* param); void showimgoriginal(); void setimgname(std::string name) { this->name = name; }; std::string getimgname() { return name; }; }; void resizeimage :: showimgoriginal() { cv::namedwindow(name, cv_window_autosize); cv::imshow(name, img); }; void resizeimage::setrect() { rect.width = abs(cor1.x - cor2.x); rect.height = abs(cor1.y - cor2.y); rect.x = cv::min(cor1.x, cor2.x); rect.y = cv::min(cor1.y, cor2.y); } void resizeimage::mousecall(int event, int x, int y, int flags, void* param) { if (event == cv::event_lbuttondown) //finding first corner { leftbuttondown = true; setcoordinates1(x,y); std::cout << "corner 1: " << getcoordinates1x()<<" "<<getcoordinates1y() << std::endl; } if (event == cv::event_lbuttonup) { if (abs(x - cor1.x)>20 && abs(y - cor1.y)>5) //finding second corner , checking whether region small { leftbuttonup = true; setcoordinates2(x, y); std::cout << "corner 2: " << getcoordinates2x() << " " << getcoordinates2y() << std::endl; } else { std::cout << "select more 5 pixels" << std::endl; } } if (leftbuttondown == true && leftbuttonup == false) //when left button down { cv::point pt; pt.x = x; pt.y = y; cv::mat temp_img = img.clone(); rectangle(temp_img, cor1, pt, cv::scalar(0, 0, 255)); //drawing rectangle continuously cv::imshow("original", temp_img); } else if (event == cv::event_mousemove) //tracking mouse movement { std::cout << "mouse moving on window - position (" << x << ", " << y << ")" << std::endl; } if (leftbuttondown == true && leftbuttonup == true) //when selection done { setrect(); cv::mat cuttempimg(img, rect); //selecting roi(region of interest) original img cv::namedwindow("cut temporary image"); cv::imshow("cut temporary image", cuttempimg); //showing cropped image leftbuttondown = false; leftbuttonup = false; } } int main(){ cv::mat img = cv::imread("image.jpg"); resizeimage img_; img_.setimg(img); img_.setimgname("original"); img_.showimgoriginal(); cv::setmousecallback(img_.getimgname(),img_.mousecall()); while (char(cv::waitkey(1) != 'q')) //waiting 'q' key finish execution { } return 0; } code after changes :
//program loading image, , showing user. //user can use mouse make rectangle , cut loaded image. //command line tracking mouse movements , coordinates of rectangle. //user can end program using 'q'. #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> #include <string> bool leftbuttondown = false, leftbuttonup = false; //flags mouse clicks class resizeimage { cv::mat img; //image process cv::point cor1, cor2; //coordinates of selected rectangle cv::rect rect; //rectangle std::string name; //windows name public: ////////////////////////////////////////////////////////////////////////////// resizeimage() { std::cout << "starting..."<<std::endl; }; //constructor/destructor ~resizeimage() { std::cout << "ending..." << std::endl; }; ////////////////////////////////////////////////////////////////////////////// void setimg(cv::mat img) { this->img = img; }; void setimgname(std::string name) { this->name = name; }; //set functions void setrect(); void setcoordinates1(int x, int y) { this->cor1.x = x; this->cor1.y = y; }; void setcoordinates2(int x, int y) { this->cor2.x = x; this->cor2.y = y; }; ////////////////////////////////////////////////////////////////////////////// int getcoordinates1x() { return cor1.x; }; //getfunctions int getcoordinates1y() { return cor1.y; }; int getcoordinates2x() { return cor2.x; }; int getcoordinates2y() { return cor2.y; }; cv::mat getimg() { return img; }; std::string getimgname() { return name; }; ////////////////////////////////////////////////////////////////////////////// static void mousecall(int event, int x, int y, int flags, void* param); //static function ////////////////////////////////////////////////////////////////////////////// void showimgoriginal(); //show function (priting image) ////////////////////////////////////////////////////////////////////////////// }; void resizeimage :: showimgoriginal() { //showing image cv::namedwindow(name, cv_window_autosize); cv::imshow(name, img); }; void resizeimage::setrect() { //calculating selected rectangle rect.width = abs(cor1.x - cor2.x); rect.height = abs(cor1.y - cor2.y); rect.x = cv::min(cor1.x, cor2.x); rect.y = cv::min(cor1.y, cor2.y); } void resizeimage::mousecall(int event, int x, int y, int flags, void* param) { if (event == cv::event_lbuttondown) //finding first corner { leftbuttondown = true; ((resizeimage*)param)->cor1.x = x; ((resizeimage*)param)->cor1.y = y; //saving coordinates std::cout << "corner 1: " << ((resizeimage*)param)->cor1.x << " " << ((resizeimage*)param)->cor1.y << std::endl; //printing coordinates } if (event == cv::event_lbuttonup) { if (abs(x - ((resizeimage*)param)->cor1.x)>20 && abs(y - ((resizeimage*)param)->cor1.y)>10) //finding second corner , checking whether region small { leftbuttonup = true; ((resizeimage*)param)->cor2.x = x; ((resizeimage*)param)->cor2.y = y; //saving coordinates std::cout << "corner 2: " << ((resizeimage*)param)->cor2.x << " " << ((resizeimage*)param)->cor2.y << std::endl; //printing coordinates } else { std::cout << "select more 10 pixels" << std::endl; } //warning if region small } if (leftbuttondown == true && leftbuttonup == false) //when left button down { cv::point pt; pt.x = x; pt.y = y; cv::mat temp_img = ((resizeimage*)param)->img.clone(); rectangle(temp_img, ((resizeimage*)param)->cor1, pt, cv::scalar(0, 0, 255)); //drawing rectangle continuously } else if (event == cv::event_mousemove) //tracking mouse movement { std::cout << "mouse moving on window - position (" << x << ", " << y << ")" << std::endl; } if (leftbuttondown == true && leftbuttonup == true) //when selection done { ((resizeimage*)param)->setrect(); cv::mat cuttempimg(((resizeimage*)param)->img, ((resizeimage*)param)->rect); //selecting roi(region of interest) original img cv::namedwindow("cut temporary image"); cv::imshow("cut temporary image", cuttempimg); //showing cropped image leftbuttondown = false; leftbuttonup = false; } } int main() { cv::mat img = cv::imread("image.jpg"); resizeimage img_; img_.setimg(img); img_.setimgname("original"); img_.showimgoriginal(); cv::setmousecallback(img_.getimgname(),resizeimage::mousecall,&img_); while (char(cv::waitkey(1) != 'q')) //waiting 'q' key finish execution { } return 0; }
if want use class method callback, should indeed declare method static. however, need pass object callback able access non static members of class such cor1 or cor2.
here minimal example of how can achieve this:
class call { public: call(int i) : a(i){}; int a; static void mouse(int event, int x, int y, int flags, void* param) { std::cout << ((call*)param)->a << std::endl; } }; cv::namedwindow("call"); call call(10); cv::setmousecallback("call", call::mouse, &call); cv::imshow("call", cv::mat(100, 100, cv_8u, cv::scalar(0))); cv::waitkey(); i create call object , use mouse method window callback while still passing object call back.
Comments
Post a Comment