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