IplImage数据结构
在使用OpenCV时,将会反复的遇到IplImage这个数据类型。IplImage是用来编码我们通常所讲的“图象”的基本的数据结构。
有了前边所学的内容,就可以很容易的讨论IplIage的数据结构。在本质上是隐藏了额外成员的CvMat对象,这些额外的成员使矩阵可以解释为图象。这个结构最早被定义为Intel图形处理库(Intel’s Image Processing Library, IPL)的一部分。IplImage结构准确的定义如3-10所示。
例3-10,IplImage头结构:
typedef struct _IplImage
{
int nSize; /* sizeof(IplImage) */
int ID; /* version (=0)*/
int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */
int alphaChannel; /* Ignored by OpenCV */
int depth; /* Pixel depth in bits*/
char colorModel[4]; /* Ignored by OpenCV */
char channelSeq[4]; /* ditto */
int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels.
cvCreateImage can only create interleaved images */
int origin; /* 0 - top-left origin,
1 - bottom-left origin (Windows bitmaps style). */
int align; /* Alignment of image rows(4 or 8).
OpenCV ignores it and uses widthStep instead. */
int width; /* Image width in pixels. */
int height; /* Image height in pixels. */
struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */
struct _IplImage *maskROI; /* Must be NULL. */
void *imageId; /* Must be NULL. */
struct _IplTileInfo *tileInfo; /* Must be NULL. */
int imageSize; /* Image data size in bytes
(==image->height*image->widthStep in case of interleaved data)*/
char *imageData; /* Pointer to aligned image data. */
int widthStep; /* Size of aligned image row in bytes. */
int BorderMode[4]; /* Ignored by OpenCV. */
int BorderConst[4]; /* Ditto. */
char *imageDataOrigin; /* Pointer to very origin of image data (not necessarily aligned)
needed for correct deallocation */
}IplImage;
我们将会介绍一些变量的功能,其中一些是没有价值的,但很多对于理解OpenCV怎么解释和处理图象是很重要的(Some are trivial, but many are very important to understanding how OpenCV interprets and works with images.)。
首先是无处不在的“width”和“height”,接下来的“depth”和“nChannels”是至关重要的。ipl.h中定义了一组变量“depth”可取的值,很不幸的是这些值和在矩阵中使用的那些值不同。对于图象,我们更趋向于把深度和通道分别处理(然而在矩阵中趋于同时处理)。“depth”可能的值罗列在表格3-2中。
表格3-2,OpenCV的图象类型:
宏 图像像素类型
IPL_DEPTH_8U 8位无符号整型
IPL_DEPTH_8S 8位有符号整型
IPL_DEPTH_16S 16位有符号整型
IPL_DEPTH_32S 32位有符号整型
IPL_DEPTH_32F 32位单精度浮点型
IPL_DEPTH_64F 64位双精度浮点型
nChannel的可能的值为1、2、3或4。
接下来两个重要的成员是“origin”和“dataOrder”。origin变量取值IPL_ORIGIN_TL或IPL_ORIGIN_BL,分别对应于原点坐标分别在图象的左上角或左下角。很多计算机视觉例程的错误都来源于缺乏原点标准(上和下的标准)。特殊的,它取决于图象的来源,操作系统、编码器、存储格式都会影响原点的坐标。例如当你想要在一副图象上边象限的脸部取样时,你可能只取到了下边象限的衬衫。最好在第一次使用图象时,你可以操作一副图象,看画出的结果是否和想象的一致,通过这种方法来彻底的检查你的系统(It is best to check the system the first time through by drawing where you think you are operating on an image patch)。
dataOrder:指定了数据的包装方式, IPL_DATA_ORDER_PIXEL表示交叉存取颜色通道(OpenCV只支持这种方式),像素存储顺序为BGR BGR BGR ... BGR;IPL_DATA_ORDER_PLANE表示通道聚集在一起构成一个图象的面(Plane),这些面是逐个相连的,像素存储顺序为RRR...R GGG...G BBB...B。。
WidthStep:包含了行偏移的字节数(和之前讨论的CvMat中step参数相似)。只有变量width不足以计算距离,为了达到更快的处理图象的目的,每一行可能会以一定数目的字节数对齐(内存对齐)。因此两行之间可能会存在一些空隙。
imageData:包含了第一行数形数据的指针。
RIO(region of interest):是一个特殊的重要的感兴趣的区域,它实际上是一个另外的IPL/IPP结构IplROI。它的定义如下(在cxtype.h中有定义):
typedef struct _IplROI
{
int coi; /* Channel of Interest,
0 - no COI (all channels are selected), 1 - 0th channel is selected ...*/
int xOffset;
int yOffset;
int width;
int height;
}IplROI;
ROI背后的理念是,一旦它被设定,通常会对整个图象进行处理的函数就只处理ROI指示的区域。如果ROI被设定了,几乎所有的OpenCV函数都会使用它。如果COI被设定为非零值,表示一些操作就只在指定的通道上起作用。很不幸的是,大部分OpenCV函数都会忽略这个参数。