OpenCV学习之矩阵操作

1. 矩阵创建

矩阵创建有多种方法,我们可以用cvCreateMat创建一个矩阵,该函数返回指向这个矩阵的指针,函数原型如下:

CvMat* cvCreateMat( int height, int width, int type );

该方法既分配了矩阵头空间,也分配了数据空间。这个方法是最常用的方法。

我们也可以使用cvCreateMatHeader函数只创建一个矩阵头,该函数返回指向这个矩阵的指针,函数原型如下:

CvMat* cvCreateMatHeader( int rows, int cols, int type );

注意这里只为矩阵头分配了空间,没有为矩阵的数据域分配空间。

你可以去看一下OpenCV的源代码,cvCreateMat包含了两步,一是头创建,二是数据域创建,函数源码如下:

CV_IMPL CvMat*
cvCreateMat( int height, int width, int type )
{
    CvMat* arr = cvCreateMatHeader( height, width, type );
    cvCreateData( arr );

    return arr;
}

也可以使用cvInitMatHeader方法初始化一个矩阵头,注意这里只对矩阵头进行初始化,既不分配矩阵头空间,也不分配数据域空间,函数原型如下:

CvMat* cvInitMatHeader( CvMat* arr, int rows, int cols, int type, void* data, int step );


2. 矩阵释放

矩阵释放使用cvReleaseMat函数,函数原型如下:

void cvReleaseMat( CvMat** array );


3. 矩阵数据的访问

Learning OpenCV介绍了三种方法:

(1)简单的方法

得到矩阵的一个元素最简单的方法是利用宏CV_MAT_ELEM,该宏有四个参数,传入矩阵,待提取的元素类型,行和列。例如:

float element_3_2 = CV_MAT_ELEM(*mat, float, 3, 2);

设置矩阵的一个值可以使用宏CV_MAT_ELEM_PTR,例如:

float element_3_2 = 7.7;

*((float *)CV_MAT_ELEM_PTR(*mat, 3, 2)) = element_3_2;

注意这些宏每次调用时都重新计算指针,在计划顺序访问矩阵中的所有元素时,缺点尤为突出,这些宏只适合简单访问矩阵中的某个元素。


(2)复杂的方法

如果仅仅读取数据,使用cvGet*D函数族,cvGet*D函数族有:

CvScalar cvGet1D( const CvArr* arr, int idx );

CvScalar cvGet2D( const CvArr* arr, int y, int x );

CvScalar cvGet3D( const CvArr* arr, int z, int y, int x );

CvScalar cvGetND( const CvArr* arr, const int* idx );


cvPtr*D函数族

cvPtr*D函数族有:

uchar* cvPtr1D( const CvArr* arr, int idx, int* _type );

uchar* cvPtr2D( const CvArr* arr, int y, int x, int* _type );

uchar* cvPtr3D( const CvArr* arr, int z, int y, int x, int* _type );

uchar* cvPtrND( const CvArr* arr, const int* idx, int* _type, int create_node, unsigned* precalc_hashval );

这些函数返回要访问元素的指针,我们可以利用这个指针进行一些算数运算后访问矩阵的其它元素。


(3)恰当的方法

恰当的方法就是利用矩阵的数据域指针自定义访问矩阵。例如累加三通道矩阵中所有的元素:

float sum(const CvMat* mat)
{
    float s = 0.0f;
    for (int row = 0; row < mat->rows; row++) {
        const float *ptr = (const float *)(mat->data.ptr + row * mat->step);
        for (col = 0; col < mat->cols; col++) {
            s += *ptr++;
        }
    }
    return (s);
}

posted @ 2012-04-10 17:16  移动应用开发  阅读(1404)  评论(0编辑  收藏  举报