Opencv mouse drawing C++ tutorial, mouse setMouseCallback region selection
This c++ Opencv tutorial shows you how to draw a rectangle by mouse over the object. The purpose of this is to take a Region of interest for your tracker or any other crop region applications. This is a very useful task. I created a youtube video with who explanation, but everything will be described in the following text.
Opencv video example and code explanation
I try to explain the code and functionality as well on this youtube video. The video describes the code and shows mouse in action drawing the rectangle and update based on actual mouse move.
The opencv mouse call back function code basic description
The first is a structure called initRoi that represents the global state of the mouse. The members of the structure are initial coordinates of mouse x and y, some indicator init that something happened and actual coordinates of x and y. The structure is global, where members are accessible by SelectedRoi.init, SelectedRoi.initX, SelectedRoi.initY, SelectedRoi.actualX and SelectedRoi.actualY. This member value can be access and updated in man function as well in CallBackF function, which is used to determine the type of the action and updating the structure values.
In CallBackF the values are updated as follows: The init is set to 1 by mouse left button down. This action as well as updates the initial x and y coordinates. The init set to 1 SelectedRoi.init != 0 is used in the main function to display rectangle based on initial coordinates and actual mouse position updated by EVENT_MOUSEMOVE. The mouse button-up is set the actual values as well. This is just a basic idea behind it. You can use any other logic behind it.
Opencv setMouseCallback
The windows to display video img Mat content with a rectangle is called "Video". The namedWindow and imshow are the standard functions to display the video content in opencv. The setMouseCallback the function to work with mouse over the "Video" window. It is named callBack because the CallBackF is the function used as the parameter of the function.
namedWindow("Video", WINDOW_AUTOSIZE);
setMouseCallback("Video", CallBackF, 0);
imshow("Video", img);
My CallBackF has parameter event, x, y, flags and img are not used right now.
static void CallBackF(int event, int x, int y, int flags, void* img)
Opencv mouse region selection tutorial code
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// global structure to remember some states changed
// by mouse action and move
struct initRoi {
// by mouse action and move
struct initRoi {
// on off
int init;
//initial coordination based on EVENT_LBUTTONDOWN
int initX;
int initY;
// actual coordination
int actualX;
int actualY;
//Selected Rect
Rect roiRect;
//Selected Mat roi
Mat takenRoi;
}SelectedRoi;
//event int is compared to determine action of the mouse EVENT_RBUTTONDOWN
// EVENT_LBUTTONDOWN, EVENT_LBUTTONUP, EVENT_MOUSEMOVE.
// If the event is evauated as happened the global structure SelectedRoi
// is updated.
static void CallBackF(int event, int x, int y, int flags, void* img) {
//Mouse Right button down
if (event == EVENT_RBUTTONDOWN) {
cout << "right button " << endl;
return;
}
//Mouse Left button down
if (event == EVENT_LBUTTONDOWN) {
SelectedRoi.initX = x;SelectedRoi.initY = y;
SelectedRoi.init = 1;
cout << "left button DOWN" << endl;
return;
}
//Mouse Left button up
if (event == EVENT_LBUTTONUP) {
SelectedRoi.actualX = x;
SelectedRoi.actualX = y;
cout << "left button UP" << endl;
return;
}
//Mouse move coordinates update
if (event == EVENT_MOUSEMOVE) {//Mouse move coordinates update
cout << "event mouse move"<< endl;
SelectedRoi.actualX = x;
SelectedRoi.actualY = y;
SelectedRoi.roiRect = Rect(SelectedRoi.initX, SelectedRoi.initY,
SelectedRoi.actualX, SelectedRoi.actualY);
return;
}
}
void main()
{
// capture
VideoCapture cap(0);
// Set initial state for the SelectedRoi structure
//- The init is set = 1 by left button down action
//- This start to display image if (SelectedRoi.init != 0) in main for loop
//- The init is set = 1 by left button down action
//- This start to display image if (SelectedRoi.init != 0) in main for loop
SelectedRoi.init = 0;
for (;;)
{
if (!cap.isOpened()) {
cout << "Video Capture Fail" << endl;
break;
}
else {
Mat img;
cap >> img;
namedWindow("Video", WINDOW_AUTOSIZE);
// mouse call back function, where CallBackF is function
// with parameters event type, x y coorfinates
// mouse call back function, where CallBackF is function
// with parameters event type, x y coorfinates
setMouseCallback("Video", CallBackF, 0);
if (SelectedRoi.init != 0) {
// draw the rectangle updated by mouse move
// draw the rectangle updated by mouse move
rectangle(img, Rect(SelectedRoi.initX, SelectedRoi.initY,
SelectedRoi.actualX- SelectedRoi.initX, SelectedRoi.actualY- SelectedRoi.initY),
Scalar(255, 255, 255), 1, 8, 0);
}
imshow("Video", img);
int key2 = waitKey(20);
}
}
}
nice thanks