aihot  2017-05-13 18:05:33  OpenCV |   查看评论   

CvMat* mat = cvCreateMat(5,5,CV_32FC1);
float element = CV_MAT_ELEM(*mat,float,3,2);
以下是一个例子:
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
//为矩阵元素赋值
CV_MAT_ELEM( *mat, float, 0, 0 ) = 1.f;
CV_MAT_ELEM( *mat, float, 0, 1 ) = 2.f;
CV_MAT_ELEM( *mat, float, 0, 2 ) = 3.f;
CV_MAT_ELEM( *mat, float, 1, 0 ) = 4.f;
CV_MAT_ELEM( *mat, float, 1, 1 ) = 5.f;
CV_MAT_ELEM( *mat, float, 1, 2 ) = 6.f;
CV_MAT_ELEM( *mat, float, 2, 0 ) = 7.f;
CV_MAT_ELEM( *mat, float, 2, 1 ) = 8.f;
CV_MAT_ELEM( *mat, float, 2, 2 ) = 9.f;
//获得矩阵元素的值
float element = CV_MAT_ELEM(*mat,float,2,2);
printf("%f/n",element);
}

CV_MAT_ELEM宏实际上会调用CV_MAT_ELEM_PTR(matrix,row,col)宏来完成任务。CV_MAT_ELEM_PTR()宏的参数是矩阵的指针,行,列。
CV_MAT_ELEM()宏和CV_MAT_ELEM_PTR()宏的区别是,在调用CV_MAT_ELEM时,指向矩阵元素的指针的数据类型已经依据输入参数中的元素类型而
做了强制转换。,以下是使用CV_MAT_ELEM_PTR()来设置元素的值:

#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
float element_0_2 = 7.7f;
*((float*)CV_MAT_ELEM_PTR( *mat, 0, 2 ) ) = element_0_2;

//获得矩阵元素的值
float element = CV_MAT_ELEM(*mat,float,0,2);
printf("%f/n",element);
}

以上使用矩阵中元素的方式很方便,但不幸的是,该宏在每次调用时,都会重新计算指针的位置。这意味着,先查找矩阵数据区中第0个元素的位置,然后,根据参数中的行和列,计算所需要的元素的地址偏移量,然后将地址偏移量与第0个元素的地址相加,获得所需要的元素的地址。
所以,以上的方式虽然很容易使用,但是却不是获得矩阵元素的最好方式。特别是当你要顺序遍历整个矩阵中所有元素时,这种每次对地址的重复计算就更加显得不合理。

困难的方式

以上两个宏只适合获得一维或二维的矩阵(数组)元素,OpenCV提供了处理多维矩阵(数组)的方式。实际上你可以不受限制地使用N维。
当访问这样一种N维矩阵中元素时,你需要使用一个系列的函数,叫做cvPtr*D,*代表1,2,3,4....,例如,cvPtr1D(),cvPtr2D(),cvPtr3D(),以及cvPtrND().以下为此系列函数的定义:

cvPtr*D函数用于返回指向某数组元素的指针

uchar* cvPtr1D( const CvArr* arr, int idx0, int* type=NULL );
uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type=NULL );
uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL );
uchar* cvPtrND( const CvArr* arr, int* idx, int* type=NULL, int create_node=1, unsigned* precalc_hashval=NULL );

arr
输入数组(矩阵).
idx0
元素下标的第一个以0为基准的成员
idx1
元素下标的第二个以0为基准的成员
idx2
元素下标的第三个以0为基准的成员
idx
数组元素下标
type
可选的,表示输出参数的数据类型
create_node
可选的,为稀疏矩阵输入的参数。如果这个参数非零就意味着被需要的元素如果不存在就会被创建。
precalc_hashval
可选的,为稀疏矩阵设置的输入参数。如果这个指针非NULL,函数不会重新计算节点的HASH值,而是从指定位置获取。这种方法有利于提高智能组合数据的操作
函数cvPtr*D 返回指向特殊数组元素的指针。数组维数应该与传递给函数的下标数相匹配,它可以被用于顺序存取的1D,2D或nD密集数组
函数也可以用于稀疏数组,并且如果被需要的节点不存在函数可以创建这个节点并设置为0
就像其它获取数组元素的函数 (cvGet[Real]*D, cvSet[Real]*D)如果元素的下标超出了范围就会产生错误


很明显,如果是一维数组(矩阵),那就可以使用cvPtr1D,用参数idx0来指向要获得的第idx0个元素,返回值为指向该元素的指针,如果是二维数组(矩阵),就可以使用cvPtr2D,用idx0,idx1来指向相应的元素。
如果是N维数组,则int* idx参数指向对N维数组中某元素定位用的下标序列。
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0
//为矩阵元素赋值
CV_MAT_ELEM( *mat, float, 0, 0 ) = 1.f;
CV_MAT_ELEM( *mat, float, 0, 1 ) = 2.f;
CV_MAT_ELEM( *mat, float, 0, 2 ) = 3.f;
CV_MAT_ELEM( *mat, float, 1, 0 ) = 4.f;
CV_MAT_ELEM( *mat, float, 1, 1 ) = 5.f;
CV_MAT_ELEM( *mat, float, 1, 2 ) = 6.f;
CV_MAT_ELEM( *mat, float, 2, 0 ) = 7.f;
CV_MAT_ELEM( *mat, float, 2, 1 ) = 8.f;
CV_MAT_ELEM( *mat, float, 2, 2 ) = 9.f;
//获得矩阵元素(0,2)的值
float *p = (float*)cvPtr2D(mat, 0, 2);
printf("%f/n",*p);
}


我们使用cvPtr*D()函数的一个理由是,通过此函数,我们可以用指针指向矩阵中的某元素,并使用指针运算符,来设置该元素的值,或者,用指针运算来移动指针,指向从起始位置开始的矩阵中的其他元素。例如,我们可以用以下方式遍历矩阵中的元素:
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);//将矩阵置0

//获得矩阵元素(0,0)的指针
float *p = (float*)cvPtr2D(mat, 0, 0);
//为矩阵赋值
for(int i = 0; i < 9; i++)
{
*p = (float)i;
p++;
}

//打印矩阵的值
p = (float*)cvPtr2D(mat, 0, 0);

for(i = 0; i < 9; i++)
{
printf("%f/t",*p);
p++;
if((i+1) % 3 == 0)
printf("/n");
}

}
 

除特别注明外,本站所有文章均为 赢咖4注册 原创,转载请注明出处来自openCV矩阵操作

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]