Building Computer Vision Projects with OpenCV 4 and C++
上QQ阅读APP看书,第一时间看更新

Basic graphical user interface with OpenCV

We are going to create a basic user interface with OpenCV. The OpenCV user interface allows us to create windows, add images to it, and move, resize, and destroy it. The user interface is in OpenCV's highui module. In the following code, we are going to learn how to create and show two images by pressing a key to display multiple windows with the image moving in the window on our desktop.

Don't worry about reading the full code; we are going to explain it in small chunks:

#include <iostream> 
#include <string> 
#include <sstream> 
using namespace std; 
 
// OpenCV includes 
#include <opencv2/core.hpp> 
#include <opencv2/highgui.hpp> 
using namespace cv; 
 
int main(int argc, const char** argv) 
{ 
   // Read images 
   Mat lena= imread("../lena.jpg"); 
# Checking if Lena image has been loaded
if (!lena.data) {
cout << "Lena image missing!" << enld;
return -1;
} Mat photo= imread("../photo.jpg");
# Checking if Lena image has been loaded
if (!photo.data) {
cout << "Lena image missing!" << enld;
return -1;
} // Create windows namedWindow("Lena", WINDOW_NORMAL); namedWindow("Photo", WINDOW_AUTOSIZE); // Move window moveWindow("Lena", 10, 10); moveWindow("Photo", 520, 10); // show images imshow("Lena", lena); imshow("Photo", photo); // Resize window, only non autosize resizeWindow("Lena", 512, 512); // wait for any key press waitKey(0); // Destroy the windows destroyWindow("Lena"); destroyWindow("Photo"); // Create 10 windows for(int i =0; i< 10; i++) { ostringstream ss; ss << "Photo" << i; namedWindow(ss.str()); moveWindow(ss.str(), 20*i, 20*i); imshow(ss.str(), photo); } waitKey(0); // Destroy all windows destroyAllWindows(); return 0; }

Let's understand the code:

  1. The first task we have to do in order to facilitate a graphical user interface is to import OpenCV's highui module:
#include <opencv2/highgui.hpp> 
  1. Now that we are prepared to create our new windows, we have to load some images:
// Read images 
Mat lena= imread("../lena.jpg"); 
Mat photo= imread("../photo.jpg"); 
  1. To create the windows, we use the namedWindow function. This function has two parameters; the first is a constant string with the window's name, and the second is the flags that we require. This second parameter is optional:
namedWindow("Lena", WINDOW_NORMAL); 
namedWindow("Photo", WINDOW_AUTOSIZE);
  1. In our case, we create two windows: the first is called Lena, and the second is called Photo.

There are three flags by default for Qt and native:

    • WINDOW_NORMAL: This flag allows the user to resize the window
    • WINDOW_AUTOSIZE: If this flag is set, the window size is automatically adjusted to fit the display image and it is not possible to resize the window
    • WINDOW_OPENGL: This flag enables the OpenGL support

Qt has a number of additional flags:

    • WINDOW_FREERATIO or WINDOW_KEEPRATIO: If WINDOW_FREERATIO is set, the image is adjusted with no respect for its ratio. If WINDOW_FREERATIO is set, the image is adjusted with respect to its ratio.
    • WINDOW_GUI_NORMAL or WINDOW_GUI_EXPANDED: The first flag facilitates a basic interface without the status bar and the toolbar. The second flag facilitates the most advanced graphical user interface, with the status bar and the toolbar.
If we compile OpenCV with Qt, all the windows that we create are, by default, in the expanded interface, but we can use native interfaces and more basic ones adding the CV_GUI_NORMAL flag.   By default, the flags are WINDOW_AUTOSIZEWINDOW_KEEPRATIO, and WINDOW_GUI_EXPANDED.
  1. When we create multiple windows, they are superimposed, but we can move the windows to any area of our desktop using the moveWindow function, as follows:
// Move window 
moveWindow("Lena", 10, 10); 
moveWindow("Photo", 520, 10); 
  1. In our code, we move the Lena window 10 pixels to the left, and 10 pixels up, and the Photo window 520 pixels to the left, and 10 pixels up:
// show images 
imshow("Lena", lena); 
imshow("Photo", photo);  
// Resize window, only non autosize 
resizeWindow("Lena", 512, 512);

  1. After showing the images that we loaded previously using the imshow function, we resize the Lena window to 512 pixels, calling the resizeWindow function. This function has three parameters: the window name, width, and height.
The specific window size is for the image area. Toolbars are not counted. Only windows without the  WINDOW_AUTOSIZE flag enabled can be resized.
  1. After waiting for a key press with the waitKey function, we are going to remove or delete our windows using the destroyWindow function, where the name of the window is the only parameter required:
waitKey(0); 
 
// Destroy the windows 
destroyWindow("Lena"); 
destroyWindow("Photo"); 
  1. OpenCV has a function to remove all windows that we create in only one call. The function is called destroyAllWindows. To demonstrate how this works, we create 10 windows in our sample and await a key press. When the user presses any key, it destroys all the windows:

 // Create 10 windows 
for(int i =0; i< 10; i++) 
{ 
   ostringstream ss; 
   ss << "Photo" << i; 
   namedWindow(ss.str()); 
   moveWindow(ss.str(), 20*i, 20*i); 
   imshow(ss.str(), photo); 
} 
 
waitKey(0); 
// Destroy all windows 
destroyAllWindows(); 

In any event, OpenCV handles the destruction of all windows automatically when the application is terminated, and it is not necessary to call this function at the end of our application.

The result of all this code can be seen in the following images across two steps. First, it shows two windows:

After pressing any key, the application continues and draws several windows changing their positions:

With a few lines of code, we are able to create and manipulate windows and show images. We are now ready to facilitate user interaction with images and add user interface controls.