Selecting regions
Many computer vision applications require to focus interest inside local regions of the images. In that case, it is a very useful user tool to select the desired regions of interest (ROI). In the drawRs
example, we show how to select, with the mouse, rectangular regions in the image to locally increase the contrast inside these regions (as shown in the following screenshot). For better control over region selection, we implement a click-and-drag behavior to reshape the rectangular boundary of each region.
For the sake of simplicity, only the code corresponding to the function callback for mouse events is shown, since the rest is quite similar in the previous examples. The code is as follows:
void cbMouse(int event, int x, int y, int flags, void* userdata) { static Point p1, p2; // Static vars hold values between calls static bool p2set = false; if (event == EVENT_LBUTTONDOWN) { // Left mouse button pressed p1 = Point(x, y); // Set orig. point p2set = false; } else if (event == EVENT_MOUSEMOVE && flags == EVENT_FLAG_LBUTTON) { if (x >orig_img.size().width) // Check out of bounds x = orig_img.size().width; else if (x < 0) x = 0; if (y >orig_img.size().height) // Check out of bounds y = orig_img.size().height; else if (y < 0) y = 0; p2 = Point(x, y); // Set final point p2set = true; orig_img.copyTo(tmp_img); // Copy orig. to temp. image rectangle(tmp_img, p1, p2, Scalar(0, 0, 255)); imshow(IN_WIN, tmp_img); // Draw temporal image with rect. } else if (event == EVENT_LBUTTONUP && p2set) { Mat submat = orig_img(Rect(p1, p2)); // Set region submat.convertTo(submat, -1, 2.0); // Compute contrast rectangle(orig_img, p1, p2, Scalar(0, 0, 255)); imshow(IN_WIN, orig_img); // Show image } return; }
The callback function declares static
its local variables, so they maintain their values between calls. The variables, p1
and p2
, store the points for defining the rectangular region of interest, and p2set
holds the Boolean (bool
) value that indicates if point p2
is set. When p2set
is true
, a new selected region can be drawn and its new values computed.
The mouse callback function handles the following events:
EVENT_LBUTTONDOWN
: This button is also called left button down. The initial position (p1
) is set toPoint(x, y)
where the event occurs. Also, thep2set
variable is set tofalse
.EVENT_MOUSEMOVE && EVENT_FLAG_LBUTTON
: Move the mouse with the left button down. First, the boundaries should be checked so that we can correct coordinates and avoid errors just in case the final point is out of the window. Then, the temporalp2
point is set to the final position of the mouse andp2set
is set totrue
. Finally, a temporal image is shown in the window with the rectangle drawn on it.EVENT_LBUTTONUP
: This button is also called left button up and is valid only ifp2set
istrue
.The final region is selected. Then a subarray can be pointed in the original image for further computation. After that, a rectangle around the final region is drawn in the original image and the result is shown into the application window.
Next, we take a closer look at the code:
Size Mat::size() const:
Returns the matrix size(Size(cols, rows))
: This function is used to get the bounds of the image (orig_img
) as follows:if (x > orig_img.size().width) // Check out bounds x = orig_img.size().width; else if (x < 0) x = 0; if (y > orig_img.size().height) // Check out bounds y = orig_img.size().height;
Since
Mat::size()
returns aSize
object, we can access its memberswidth
andheight
to obtain the greatest values forx
andy
in the image (orig_img
) and compare those with the coordinates where the mouse event take place.void Mat::copyTo(OutputArray m) const
: This method copies the matrix to another one, reallocating new size and type if it is needed. Before copying, the following method invokes:m.create(this->size(), this->type());
In the example, the following method is employed to make a temporal copy of the original image:
orig_img.copyTo(tmp_img); // Copy orig. to temp. image
The rectangle that defines the selected region is drawn over this temporal image.
void rectangle(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
: This function draws a rectangle defined by pointspt1
andpt2
over the image (img
) with the specifiedcolor
,thickness
, andlineType
. In the code example, this function is used twice. First, to draw a red (Scalar(0, 0, 255)
) rectangle on the temporal image (tmp_img
) around the selected area, and then to draw the boundaries of the final selected region in the original image (orig_img
):rectangle(tmp_img, p1, p2, Scalar(0, 0 ,255)); //… rectangle(orig_img, p1, p2, Scalar(0, 0, 255));
Mat::Mat(const Mat& m, const Rect& roi)
: The constructor takes a submatrix ofm
limited by the rectangle (roi
) that represents a region of interest in the image stored inm
. This constructor is applied, in the code example, to get the rectangular region whose contrast has to be converted:Mat submat = orig_img(Rect(p1, p2));// Set subarray on orig. image