opencv中CvMat存储方式

2014年10月2日 由 Creater 留言 »

先看CvMat数据结构,很简单的C结构体结构。

typedef struct CvMat
{
    int type;
    int step;

    /* for internal use only */
    int* refcount;
    int hdr_refcount;

    union
    {
        uchar* ptr;
        short* s;
        int* i;
        float* fl;
        double* db;
    } data;

#ifdef __cplusplus
    union
    {
        int rows;
        int height;
    };

    union
    {
        int cols;
        int width;
    };
#else
    int rows;
    int cols;
#endif
}
CvMat;

(先解释下通道:描述一个像素点,如果是灰度,那么只需要一个数值来描述它,就是单通道。如果一个像素点,有RGB三种颜色来描述它,就是三通道。还有可能加了个阿尔法值的四通道。)

实际中经常碰到的是多维对象的多维矩阵,比如常见的彩色图像,多数为三通道(3原色构成)的二维(平面)矩阵,即每个像素点是由1X3的小矩阵组成的,对于单通道来说就是一个显而易见的二维矩阵,当为多通道时该如何存储呢?假设矩阵有N个三通道像素,记为(Xi,Yi,Zi),一般觉得有如下四种可能的方式:

  • 1.N行1列,3通道
  • 1

  • 2.1行N列,3通道
  • 2

  • 3.N行3列,1通道
  • 3

  • 4.3行N列,1通道
  • 4

由于数据是按光栅扫描顺序存储的,需要符合以下两个原则:

(1)元素从左到右,从上到下存储;

(2)多通道时是交错存储的,交错的意思是每个点包含所有通道,而不是先存储完所有的第一个通道,再存储第二个通道。

下图为显像管的扫描,情形类似:

5

所以,CvMat中的存储方式为如下的交错保存方式:

6

如果需要访问指定位置的元素,其定点位置即偏移量由如下公式得出:

Offset = row * numCols * numChannels + col * numChannels + Channel

row和col代表行号和列号,Channel带包通道号,numChannels代表通道数,numCols代表矩阵列数。

CvMat结构体中有个成员变量step,它表示矩阵一行的字节数,即 step = numCols*numChannels,那么可以通过如下的公式拉力得出每行的头指针,并访问各个通道。

ptr = (uchar*)(cvMat.data.ptr + row * cvMat.step);
*(ptr+3*col)//b
*(ptr+3*col+1)//g
*(ptr+3*col+2)//r
广告位

发表评论

你必须 登陆 方可发表评论.