In Chapter 3, Creating a Comprehensive Qt+OpenCV Project, we learned about the basic rules of creating a comprehensive and sustainable application that can look appealing, support multiple languages, and be easily extendable by using the plugins system in Qt. We're now going to expand our knowledge base regarding the foundations of a computer vision application even more by learning about the classes and structures responsible for handling computer vision data types. Learning about the basic structures and data types required by both the OpenCV and Qt frameworks is the first step in understanding how the underlying computer vision functions that process them perform when executed in an application. OpenCV is a computer vision framework that aims for speed and performance. Qt on the other hand, is a growing application development framework with a massive number of classes and capabilities. That's why they both need a well-defined set of classes and structures to...
You're reading from Computer Vision with OpenCV 3 and Qt5
In the previous chapters, you experienced using the Mat
class of the OpenCV framework very briefly, but we're going to dig a little bit deeper now. The Mat
class, which borrows its name from the matrix, is an n-dimensional array capable of storing and handling different mathematical data types in single or multiple channels. To simplify this further, let's take a look at what an image is in terms of computer vision. An in computer vision is a matrix (therefore a two-dimensional array) of pixels, with a specified width (number of columns in the matrix) and height (number of rows in the matrix). Furthermore, a pixel in a grayscale image can be represented with a single number (therefore a single channel), with a minimum value (usually 0) representing the black and a maximum value (usually 255, which is the highest number possible with one byte) representing the white, and all values in between corresponding to different gray intensities accordingly. Look at the following...
Now that we learned all about the Mat
class in OpenCV, we can move on to learn to read images and fill a Mat
class with an image to further process it. As you have seen briefly in the previous chapters, the imread
function can be used to read images from the disk. Here's an example:
Mat image = imread("c:/dev/test.jpg", IMREAD_GRAYSCALE | IMREAD_IGNORE_ORIENTATION);
imread
simply takes a C++ std::string
class as the first parameter and an ImreadModes
flag as the second parameter. If for any reason the image cannot be read, then it returns an empty Mat
class (data == NULL
), otherwise, it returns a Mat
class filled with the image pixels with the type and color specified in the second parameter. Depending on the availability of some image types in the platform, imread
can read the following image types:
- Windows bitmaps:
\*.bmp
,\*.dib
- JPEG files:
\*.jpeg
,\*.jpg
,\*.jpe
- JPEG 2000 files:
\*.jp2
- Portable Network Graphics:
\*.png
- WebP:
\*.webp
- Portable image format...
The imwrite
function in OpenCV can be used to write images into files on disk. It uses the extension of the filename to decide the format of the image. To customize the compression rate and similar settings in an imwrite
function, you need to use ImwriteFlags
, ImwritePNGFlags
, and so on. Here's a simple example demonstrating to write an image into a JPG file with a progressive set on and a relatively low quality (higher compression rate):
std::vector<int> params; params.push_back(IMWRITE_JPEG_QUALITY); params.push_back(20); params.push_back(IMWRITE_JPEG_PROGRESSIVE); params.push_back(1); // 1 = true, 0 = false imwrite("c:/dev/output.jpg", image, params);
You can omit the params
altogether if you want to use the default settings and simply write:
imwrite("c:/dev/output.jpg", image, params);
See the imread
function in the previous section for the same list of supported file types in the imwrite
function.
Apart from imwrite
,...
OpenCV a single and extremely easy-to-use class called VideoCapture
for reading videos (or image sequences) from files saved on disk, or from capture devices, cameras, or a network video stream (for instance an RTSP address on the internet). You can simply use the open
function to try a video from any of the mentioned source types and use the read
function to grab video frames into images. Here's an example:
VideoCapture video; video.open("c:/dev/test.avi"); if(video.isOpened()) { Mat frame; while(true) { if(video.read(frame)) { // Process the frame ... } else { break; } } } video.release();
If you want to load an image sequence, you simply need to replace the filename with the file path pattern. For instance, image_%02d.png
will read images with filenames like image_00.png
, image_01.png
, image_02.png
...
The HighGUI module in OpenCV is responsible for quick and simple GUIs. We already used one of the widely used functions within this module, imshow
, to quickly display images in Chapter 3, Creating a Comprehensive Qt+OpenCV Project, of this book. But, as we are going to learn about Qt and a more sophisticated framework for dealing with GUI creation, we are going to skip this module completely and move on to Qt subjects. However, just before that, it's worth quoting the introduction of the HighGUI module in the OpenCV documentation:
"While OpenCV was designed for use in full-scale applications and can be used within functionally rich UI frameworks (such as Qt\*, WinForms\*, or Cocoa\*) or without any UI at all, sometimes there it is required to try functionality quickly and visualize the results. This is what the HighGUI module has been designed for."
As you'll learn later on in this chapter, we'll also stop using the imshow
function and stick to Qt capabilities...
Qt uses several different classes to work image data, videos, cameras, and computer vision subjects. In this section, we are going to learn about them and also learn how to link between OpenCV and Qt classes, for a more flexible computer vision application development experience.
Perhaps the most important computer vision-related class in Qt, QImage
is the main Qt class for handling image data and it provides pixel-level access to images, along with many other functions for working with image data. We are going to cover the most important subset of its and functionalities, especially the ones important when working with OpenCV
.
QImage
contains many different constructors which allow the creation of a QImage
from files or raw image data, or an empty image to work with and manipulate its pixels. We can create an empty QImage
class with a given size and format, as seen in the following example:
QImage image(320, 240, QImage::Format_RGB888)...
This chapter was an important milestone since it introduced the concepts required for linking OpenCV and Qt frameworks together. In this chapter, we learned all about the Mat
class and its variants. We learned about the new Transparent API in OpenCV and how using the UMat
class can improve the performance of our computer vision applications. We also learned about reading and writing images and videos, and also capturing video frames from cameras and network-based video feeds. Later, we moved on to learning about the Qt capabilities and classes that are related to computer vision and working with images. The QImage
class in Qt, which is the equivalent of the Mat
class in OpenCV
, was introduced in this chapter. We also learned about the QPixmap
and QPainter
classes, and several other Qt classes. While doing just that, we also learned how to create a custom Qt widget and use the QPainter
class to draw on a QImage
class. Finally, we ended the chapter with an introduction to Qt classes...