Chapter 3. Getting to Know OpenCV

OpenCV has several primitive data types. These data types are not primitive from the point of view of C, but they are all simple structures, and we will regard them as atomic. You can examine details of the structures described in what follows (as well as other structures) in the cxtypes.h header file, which is in the …/OpenCV/cxcore/include directory of the OpenCV install.

The simplest of these types is CvPoint. CvPoint is a simple structure with two integer members, x and y. CvPoint has two siblings: CvPoint2D32f and CvPoint3D32f. The former has the same two members x and y, which are both floating-point numbers. The latter also contains a third element, z.

CvSize is more like a cousin to CvPoint. Its members are width and height, which are both integers. If you want floating-point numbers, use CvSize's cousin CvSize2D32f.

CvRect is another child of CvPoint and CvSize; it contains four members: x, y, width, and height. (In case you were worried, this child was adopted.)

Last but not least is CvScalar, which is a set of four double-precision numbers. When memory is not an issue, CvScalar is often used to represent one, two, or three real numbers (in these cases, the unneeded components are simply ignored). CvScalar has a single member val, which is a pointer to an array containing the four double-precision floating-point numbers.

All of these data types have constructor methods with names like cvSize() (generally[14] the constructor has the same name as the structure type but with the first character not capitalized). Remember that this is C and not C++, so these "constructors" are just inline functions that take a list of arguments and return the desired structure with the values set appropriately.

The inline constructors for the data types listed in Table 3-1cvPointXXX(), cvSize(), cvRect(), and cvScalar()—are extremely useful because they make your code not only easier to write but also easier to read. Suppose you wanted to draw a white rectangle between (5, 10) and (20, 30); you could simply call:

cvRectangle(
  myImg,
  cvPoint(5,10),
  cvPoint(20,30),
  cvScalar(255,255,255)
);

cvScalar() is a special case: it has three constructors. The first, called cvScalar(), takes one, two, three, or four arguments and assigns those arguments to the corresponding elements of val[]. The second constructor is cvRealScalar(); it takes one argument, which it assigns to val[0] while setting the other entries to 0. The final variant is cvScalarAll(), which takes a single argument but sets all four elements of val[] to that same argument.

Figure 3-1 shows the class or structure hierarchy of the three image types. When using OpenCV, you will repeatedly encounter the IplImage data type. You have already seen it many times in the previous chapter. IplImage is the basic structure used to encode what we generally call "images". These images may be grayscale, color, four-channel (RGB+alpha), and each channel may contain any of several types of integer or floating-point numbers. Hence, this type is more general than the ubiquitous three-channel 8-bit RGB image that immediately comes to mind.[15]

OpenCV provides a vast arsenal of useful operators that act on these images, including tools to resize images, extract individual channels, find the largest or smallest value of a particular channel, add two images, threshold an image, and so on. In this chapter we will examine these sorts of operators carefully.

Before we can discuss images in detail, we need to look at another data type: CvMat, the OpenCV matrix structure. Though OpenCV is implemented entirely in C, the relationship between CvMat and IplImage is akin to inheritance in C++. For all intents and purposes, an IplImage can be thought of as being derived from CvMat. Therefore, it is best to understand the (would-be) base class before attempting to understand the added complexities of the derived class. A third class, called CvArr, can be thought of as an abstract base class from which CvMat is itself derived. You will often see CvArr (or, more accurately, CvArr*) in function prototypes. When it appears, it is acceptable to pass CvMat* or IplImage* to the routine.



[14] We say "generally" here because there are a few oddballs. In particular, we have cvScalarAll(double) and cvRealScalar(double); the former returns a CvScalar with all four values set to the argument, while the latter returns a CvScalar with the first value set and the other values 0.

[15] If you are especially picky, you can say that OpenCV is a design, implemented in C, that is not only object-oriented but also template-oriented.