OpenCV Essentials
上QQ阅读APP看书,第一时间看更新

Text and drawing

In the previous section, we used a simple user interface to get input values by a trackbar. However, in many applications, the user has to point locations and regions on the image and mark them with text labels. For this purpose, the highgui module provides a set of drawing functions along with mouse event handling.

The drawThings code example shows an easy application to mark positions on an input image. The positions are marked with a red circle and a black text label next to it. The following screenshot displays the window with the input image and the marked positions on it. To mark each position on the image, the user uses has to click the left mouse button over it. In other application, the marked position could be the obtained points or regions from an algorithm applied to the input image.

Next, we show the example code where some pieces of code have been omitted for simplicity, since they are duplicated in other previous examples:

    // (omitted for simplicity)
#define IN_WIN "Drawing..."

Mat img;

// CallBack Function for mouse events
void cbMouse(int event, int x, int y, int flags, void* userdata) {

static int imark=0;
    char textm[] = "mark999";

    if (event == EVENT_LBUTTONDOWN) { // Left mouse button pressed
circle(img, Point(x, y), 4, Scalar(0,0,255), 2);
imark++;// Increment the number of marks
sprintf(textm, "mark %d", imark);// Set the mark text
putText(img, textm, Point(x+6, y), FONT_HERSHEY_PLAIN,
 1, Scalar(0,0,0),2);
imshow(IN_WIN, img); // Show final image
    }
    return;
}

int main(int argc, char* argv[]) {

    // (omitted for brevity)    
    img = imread(argv[1]); //open and read the image
    // (omitted for brevity)
    namedWindow(IN_WIN);
 setMouseCallback(IN_WIN, cbMouse, NULL);
    imshow(IN_WIN, img);
    cout << "Pres any key to exit..." << endl;
    waitKey();
    return 0;
}

The code explanation is given as follows:

  • void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0): This function sets an event mouse handler for the specified window. In this function, the second argument is the callback function executed whenever a mouse event occurs. The final argument is a void pointer to the data passed as argument to that function. In our code, this function is used as follows:
    setMouseCallback(IN_WIN, cbMouse, NULL);

    In this case, rather than use a global variable for the name of the window, a defined symbol with global scope has been preferred (IN_WIN).

    Text and drawing

    Image with circles and text on it

    The mouse handler itself is declared as follows:

    void cbMouse(int event, int x, int y, int flags, void* userdata)

    Here, event indicates the mouse event type, x and y are the coordinates for the location of the event at the window, and flags is the specific condition whenever an event occurs. In this example, the unique captured mouse event is the left mouse click (EVENT_LBUTTONDOWN).

    The following enumerations define the events and flags handled in the mouse callback functions:

    enum{
      EVENT_MOUSEMOVE      =0,
        EVENT_LBUTTONDOWN    =1,
        EVENT_RBUTTONDOWN    =2,
        EVENT_MBUTTONDOWN    =3,
        EVENT_LBUTTONUP      =4,
        EVENT_RBUTTONUP      =5,
        EVENT_MBUTTONUP      =6,
        EVENT_LBUTTONDBLCLK  =7,
        EVENT_RBUTTONDBLCLK  =8,
        EVENT_MBUTTONDBLCLK  =9};
    
    enum {
        EVENT_FLAG_LBUTTON   =1,
        EVENT_FLAG_RBUTTON   =2,
        EVENT_FLAG_MBUTTON   =4,
        EVENT_FLAG_CTRLKEY   =8,
        EVENT_FLAG_SHIFTKEY  =16,
        EVENT_FLAG_ALTKEY    =32};
  • void circle(Mat& img, Point center, int radius, const Scalar& color, int thickness=1, int lineType=8, int shift=0): This function draws a circle over the image with the specified radius (in pixels) and color at the position marked by its center. Moreover, a thickness value for the line and other additional parameters can be set. The usage of this function in the example is as follows:
    circle(img, Point(x, y), 4, Scalar(0,0,255), 2);

    The center of the circle is the point where the mouse is clicked. The radius has 4 pixels and the color is pure red (Scalar(0, 0, 255)) with a line thickness of 2 pixels.

    Note

    Remember that OpenCV uses a BGR color scheme and the Scalar class is used to represent the three (or four if opacity channel is considered) channels of each pixel with greater values for a brighter one (or more opaque).

    Other drawing functions included in the highgui module allow us to draw ellipses, lines, rectangles, and polygons.

  • void putText(Mat& image, const string& text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=8, bool bottomLeftOrigin=false): This function draws a text string in the image at the specified position (org) with the properties set by the arguments fontFace, fontScale, color, thickness, and lineType. It is possible to set the coordinates origin at the bottom-left corner with the last argument (bottomLeftOrigin). In the example, this function is used as follows:
    imark++; // Increment the number of marks
    sprintf(textm, "mark %d", imark); // Set the mark text
    putText(img, textm, Point(x+6, y), FONT_HERSHEY_PLAIN,
    1.0, Scalar(0,0,0),2);

    In the drawThings example, we draw a text "mark" followed by an increasing number that points out the mark order. To store the mark order, we used a static variable (imark) that maintains its value between the calls. The putText function draws the text at the location where the mouse click occurs with a 6-pixels shift on x axis. The font face is specified by the flag FONT_HERSHEY_PLAIN and is drawn without scale (1.0), black color (Scalar(0, 0, 0)), and 2 pixels thickness.

    The available flags for the font face are defined by the enumeration:

    enum{
        FONT_HERSHEY_SIMPLEX = 0,
        FONT_HERSHEY_PLAIN = 1,
        FONT_HERSHEY_DUPLEX = 2,
        FONT_HERSHEY_COMPLEX = 3,
        FONT_HERSHEY_TRIPLEX = 4,
        FONT_HERSHEY_COMPLEX_SMALL = 5,
        FONT_HERSHEY_SCRIPT_SIMPLEX = 6,
        FONT_HERSHEY_SCRIPT_COMPLEX = 7,
        FONT_ITALIC = 16};