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-1—cvPointXXX(), 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.
Figure 3-1. Even though OpenCV is implemented in C, the structures used in OpenCV have an object-oriented design; in effect, IplImage is derived from CvMat, which is derived from CvArr
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.