Chapter 2. Something We Look At – Graphical User Interfaces

In this chapter, we will cover the main user interface capabilities included with the OpenCV library. We will start with the user interface functions included in the highgui module. Then, we will deal with the insertion of objects (such as text and geometrical shapes) on the displayed windows to point out some specific characteristics on images. Finally, the chapter addresses the new Qt functions included in OpenCV to enrich the user experience.

Using OpenCV's highgui module

The highgui module has been designed to provide an easy way to visualize the results and try the functionality of developed applications with OpenCV. As we saw in the previous chapter, this module supplies functions to perform the following operations:

  • Reading images and videos from files and live cameras (imread) through a VideoCapture object.
  • Writing images and videos from memory to disk (imwrite) through a VideoWriter object.
  • Creating a window that can display images and video frames (namedWindow and imshow).
  • Fetching and handling events when a key is pressed (waitKey).

Of course, the module contains more functions to enhance the user interaction with the software applications. Some of them will be explained in this chapter. In the following tbContrast code example, we can read an image file and two windows are created: the first one shows the original image and the other is the resulting image after increasing or decreasing the contrast to the original image applying a quite simple scaling operation. The following example shows how to create a trackbar in the window to easily change the contrast factor (scale) in the image. Let's see the code:

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char* argv[]) {
    const char in_win[]="Orig. image";
    const char out_win[]="Image converted...(no saved)";
    int TBvalContrast=50; // Initial value of the TrackBar
    Mat out_img;

    if (argc != 2) {
        cout << "Usage: <cmd><input image_file>" << endl;
        return -1;
    }
    Mat in_img = imread(argv[1]); // Open and read the image
    if (in_img.empty()) {
        cout << "Error!!! Image cannot be loaded..." << endl;
        return -1;
    }
    namedWindow(in_win); // Creates window for orig. image
    moveWindow(in_win, 0, 0); // Move window to pos. (0, 0)
    imshow(in_win, in_img); // Shows original image
    namedWindow(out_win);
    createTrackbar("Contrast", out_win, &TBvalContrast, 100);
    cout << "Press Esc key to exit..." << endl;
    while (true) {
    in_img.convertTo(out_img, -1, TBvalContrast/50.0);
        imshow(out_win, out_img);
        if (waitKey(50) == 27) // If Esc key pressed breaks
            break;
    }
    return 0;
}

The following screenshot shows the original image (fruits.jpg) and the same image with increased contrast obtained with the tbContrast application.

Using OpenCV's highgui module

Original image and the image with increased contrast

Note

To avoid repetition in the examples, only the remarkable new portions of code are explained.

The code explanation is given as follows:

  • void moveWindow(const string& winname, int x, int y): This function moves the window to the specified screen (x, y) position being the origin point (0, 0) at the upper-left corner. When a window is created and displayed, its default position is at the center of the screen. That behavior is quite convenient if only one window is displayed. However, if several windows have to be shown, they are overlapped and should be moved in order to see their content. In the example, this function is used as follows:
    moveWindow(in_win,0,0);

    Now, the window that shows the original image is moved, after its creation, to the upper-left corner (origin) of the screen while the converted imaged is located at its default position (center of the screen).

  • intcreateTrackbar(const string&trackbarname, const string&winname, int*value, intrange, TrackbarCallbackonChange=0, void*userdata=0): This function creates a trackbar (a slider) attached to the window with the specified name and range. The position of the slider is synchronized with the value variable. Moreover, it is possible to implement a callback function for being called after the slider moves. In this call, a pointer to the user data is passed as argument. In our code, this function is used as follows:
    createTrackbar("Contrast", out_win, &TBvalContrast, 100);

    Note

    A callback is a function passed as an argument to another function. The callback function is passed as a pointer to the code, which is executed when an expected event occurs.

    In this code, the trackbar is called "Contrast" without a callback function linked to it. Initially, the slider is located at the middle (50) of the full range (100). This range allows a maximum scale factor of 2.0 (100/50).

  • void Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 ) const: This function converts an array to another data type with an optional scaling. If rtype is negative, the output matrix will have the same type as the input. The applied scaling applied formula is as follows:
    m(x, y) = alfa(*this)(x, y) + beta,
    

    In this code, a final implicit cast (saturate_cast<>) is applied to avoid possible overflows. In the tbContrast example, this function is used inside an infinite loop:

    while (true) {
        in_img.convertTo(out_img, -1, TBvalContrast/50.0);
        imshow(out_win, out_img);
        if (waitKey(50) == 27) // If Esc key pressed breaks
            break;
    }

In the previous chapter, we saw code examples that can create an implicit infinite loop waiting for a pressed key with the function call waitKey (without arguments). The events on the application main window (for example, trackbars, mouse, and so on) are caught and handled inside of that loop. On the contrary, in this example, we create an infinite loop with a while statement applying the contrast change with the convertTo function with a scale factor from 0.0 (slider at 0) to 2.0 (slider at 100). The infinite loop breaks when the Esc key (ASCII code 27) is pressed. The implemented contrast method is quite simple because the new values for the pixels are calculated by multiplying the original value by a factor greater than 1.0 to increase contrast and a factor smaller than 1.0 to decrease contrast. In this method, when a pixel value exceeds 255 (in any channel), a rounding (saturate cast) has to be done.

Note

In the next chapter, we will explain a more sophisticated algorithm to improve the image contrast using the image histogram equalization.

Then, in the tbContrastCallB example, we show the same functionality, but using a trackbarcallback function that is called every time the slider is moved. Note that the events are handled when the waitKey function is called. The application ends if you press any key. The code is as follows:

//… (omitted for brevity)
#define IN_WIN "Orig. image"
#define OUT_WIN "Image converted...(no saved)"
Mat in_img, out_img;

// CallBack function for contrast TrackBar
void updateContrast(int TBvalContrast, void *userData=0) {

    in_img.convertTo(out_img, -1, TBvalContrast/50.0);
    imshow(OUT_WIN, out_img);
    return;
}

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

    int TBvalContrast=50; // Value of the TrackBar

    // (omitted for simplicity)
    in_img = imread(argv[1]); // Open and read the image
    // (omitted for simplicity)
    in_img.copyTo(out_img); // Copy orig. image to final img
    namedWindow(IN_WIN); // Creates window for orig. image
    moveWindow(IN_WIN, 0, 0); // Move window to pos. (0, 0)
    imshow(IN_WIN, in_img); // Shows original image
    namedWindow(OUT_WIN); // Creates window for converted image
    createTrackbar("Contrast", OUT_WIN, &TBvalContrast, 100,
                   updateContrast);
    imshow(OUT_WIN, out_img); // Shows converted image
    cout << "Press any key to exit..." << endl;
    waitKey();
    return 0;
}

In this example, a void pointer to the updatedContrast function is passed as argument to the createTrackbar function:

createTrackbar("Contrast", OUT_WIN, &TBvalContrast, 100,
updateContrast);

The callback function gets as its first argument the value of the slider in the trackbar and a void pointer to other user data. The new pixels values for the image will be calculated in this function.

Note

In this example (and subsequent ones), some portions of code are not shown for brevity because the omitted code is the same as that in previous examples.

Using a callback function cause a few changes in this new code because the accessible data inside this function has to be defined with global scope. Then, more complexity is avoided on the datatypes passed to the callback function as follows:

  • Windows names are defined symbols (for example, #define IN_WIN). In the previous example (tbContrast), the window names are stored in local variables (strings).
  • In this case, the Mat variables for the original (in_img) and converted (out_img) images are declared as global variables.

Tip

Sometimes in this book, the sample code uses global variables for simplicity. Be extremely cautious with global variables since they can be changed anywhere in the code.

The two different implementations shown in the previous example produce the same results. However, it should be noted that after using a callback function, the resulting application (tbContrastCallB) is more efficient because the math operations for the image conversion only take place at the change of the trackbar slide (when the callback is executed). In the first version (tbContrast), the convertTo function is called inside the while loop even if the TBvalContrast variable doesn't change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset