OpenCV Mouse Operation-Drawing Rectangles with Mouse

Posted by petrosa on Thu, 12 Sep 2019 12:48:30 +0200

introduce

This code, which I first saw in the sample of the tracking module in the contrib module, comes from roiSelector.hpp. The function of this file is to select a rectangular area in the picture with the mouse. Interested readers can learn the source code here. To take care of some people, it is more straightforward to say that this code is in the following path:

opencv3.2\opencv_contrib-master\modules\tracking\samples

** Note that this is the opencv contrib module, not the OpenCV. ** downloaded from the official website.

Obviously, we know that to select a rectangular area with a mouse, the movement of the mouse can be subdivided into three actions:

  • Press left mouse button
  • Mouse slides non-horizontally and non-vertically
  • The left mouse button is raised.

In the code of roiSelector.hpp, EVENT_LBUTTONUP (left mouse button lifting event) is processed before EVENT_LBUTTONDOWN (left mouse button pressing event) and EVENT_MOUSEMOVE (mouse movement event).
In order to illustrate the specific meaning of the code given by the subject, we must first understand how the first two events, namely, the left mouse button press and the mouse slide, are handled. For illustration purposes, instead of discussing how to draw a rectangle from the center of the rectangle in the code, I simplify the code of these three events as follows. For illustration purposes, the order is adjusted:

PS: Plus, maybe nonsense. In OpenCV, the rectangle is represented by (x,y,width,height), that is, the upper-left coordinates of the rectangular box, with widened height. The image coordinate system of OpenCV is also based on the upper left corner of the image as the origin. The bigger the image goes to the right x, the bigger the image goes down y.

Code interpretation

The code has been simplified, but it should be sufficiently illustrative.

The simplified code is as follows:

switch (event)
    {
    // start to select the bounding box
    case cv::EVENT_LBUTTONDOWN:
        data->isDrawing = true;
        data->box = cv::Rect2d(x, y, 0, 0);
        break;

    // update the selected bounding box
    case cv::EVENT_MOUSEMOVE:
        if (data->isDrawing)
        {
            data->box.width = x - data->box.x;
            data->box.height = y - data->box.y;
        }
        break;

    // cleaning up the selected bounding box
    case cv::EVENT_LBUTTONUP:
        data->isDrawing = false;
        if (data->box.width < 0)
        {
            data->box.x += data->box.width;
            data->box.width *= -1;
        }
        if (data->box.height < 0)
        {
            data->box.y += data->box.height;
            data->box.height *= -1;
        }
        break;
    }

case 1

Let's start with the first case, that is, the first action, the left mouse button press event: EVENT_LBUTTONDOWN.

// If the left mouse button is pressed, the rectangle is initialized as a rectangle with the upper left coordinate of the mouse and the width and height of the rectangle are all zero.
// And start drawing flag is true, left button does not press the sliding mouse will not start drawing.

    case cv::EVENT_LBUTTONDOWN:
        data->isDrawing = true;
        data->box = cv::Rect2d(x, y, 0, 0);
        break;

case 2

The second case, that is, the second action, mouse sliding event: EVENT_MOUSEMOVE.

// If the mouse starts to slide, update the width and height of the rectangle.
// Use the coordinate X of the mouse when sliding to subtract the initial x from the width of the rectangle.
// The coordinate y minus the initial y of the rectangle is the width of the rectangle.
// For example, if the mouse moves five pixels horizontally to the left, the width is 5px.
// The mouse moves down 10 pixels vertically, and the rectangle is 10 px high.

case cv::EVENT_MOUSEMOVE:
    if (data->isDrawing)
    {
        data->box.width = x - data->box.x;
        data->box.height = y - data->box.y;
    }
    break;

case 3

// cleaning up the selected bounding box
// Ignore the above English sentence.
// The last action here is to raise (release) the left mouse button.
// If the width of the rectangle is less than 0, in conjunction with the coordinate system orientation of OpenCV as mentioned above,
// It shows that the mouse slides from right to left when it slides, so the starting point of the original left mouse button is pressed at this time.
// It's no longer the top left corner of the rectangle, so you need to subtract the width of the rectangle from the original x.
// That's the x coordinate of the upper left corner of the rectangle. Since the width is negative at this time, subtraction is indicated by a plus sign below.
// Then multiply by - 1 to change the width from negative to positive.
// The following height is negatively identical.

// The reason for using two if instead of if...else... is implicit if the width is not negative.
// Then the final width is the width obtained by subtracting the initial upper left coordinate from the coordinate when the mouse is released.

case cv::EVENT_LBUTTONUP:
    data->isDrawing = false;
    if (data->box.width < 0)
    {
        data->box.x += data->box.width;
        data->box.width *= -1;
    }
    if (data->box.height < 0)
    {
        data->box.y += data->box.height;
        data->box.height *= -1;
    }
    break;
}

 

 

Reference resources:

  1. https://www.jianshu.com/p/2fc4278c1f98
  2. https://www.cnblogs.com/cvwyh/p/10318524.html
  3. https://blog.csdn.net/sss_369/article/details/84845042

 

 

 

Topics: OpenCV less