opencv 矩阵的存取


简单的方法

利用CV_MAT_ELEM()宏存取矩阵元素

elemtype CV_MAT_ELEM( mat, elemtype, row, col )  

mat: 传入矩阵

elemtype: 待提取的元素类型

row: 行

col: 列

//矩阵的取
void accessMat(void)
{
	float vals[]={0.32, 1.55, 2.24, 6.54};

	CvMat mat=cvMat(2, 2, CV_32FC1, vals);

	for (int i=0; i<mat.width; i++)//列
	{
		for (int j=0; j<mat.height; j++)//行
		{
			float elem=CV_MAT_ELEM(mat, float, j, i);
			cout<<elem<<" ";
		}
		cout<<endl;
	}
}
opencv 矩阵的存取_第1张图片


//矩阵的存取
void accessMat(void)
{
	float vals[]={0.32, 1.55, 2.24, 6.54};

	CvMat mat=cvMat(2, 2, CV_32FC1, vals);

	for (int i=0; i<mat.width; i++)//列
	{
		for (int j=0; j<mat.height; j++)//行
		{
			CV_MAT_ELEM(mat, float, j, i)=0.0111;//存
			float elem=CV_MAT_ELEM(mat, float, j, i);//取
			cout<<elem<<" ";
		}
		cout<<endl;
	}
}

opencv 矩阵的存取_第2张图片


类似宏

CV_MAT_ELEM_PTR( mat, row, col )

mat:传入矩阵

row:待返回元素的行

col:待返回元素的列

该宏和CV_MAT_ELEM()宏最重要的区别是后者在指针解引用之前将其转化为指定的类型。

如果需要同时读取数据和设置数据,可以直接调用CV_MAT_ELEM_PTR(),但在这种情况下,必须自己将指针转化为恰当的类型

			*((float *)CV_MAT_ELEM_PTR(mat, j, i))=0.0111;//存
			float *elem=(float *)CV_MAT_ELEM_PTR(mat, j, i);//取

缺点:

这些宏在每次调用的时候都重新计算指针。这意味着要查找指向矩阵基本元素数据区的指针、计算目标数据在矩阵中的相对地址,然后将相对位置与基本位置相加,所以即使这些宏容易使用,但也不是存取矩阵的最佳方法。在计划顺序访问矩阵中的所有元素时,这种方法的缺点尤为突出。


####################################################


麻烦的方法

在“简单的方法中”讨论的两个宏仅仅适用于访问1维或2维的数组,OpenCV提供了处理多维数组的机制


指针访问矩阵结构 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

);

//矩阵的取
void accessMat(void)
{
	float vals[]={0.32, 1.55, 2.24, 6.54};

	CvMat mat=cvMat(2, 2, CV_32FC1, vals);

	for (int i=0; i<mat.width; i++)//列
	{
		for (int j=0; j<mat.height; j++)//行
		{
			float *elem=(float *)cvPtr2D(&mat, j, i);//取
			cout<<*elem<<" ";
		}
		cout<<endl;
	}
}

opencv 矩阵的存取_第3张图片


//矩阵的存取
void accessMat(void)
{
	float vals[]={0.32, 1.55, 2.24, 6.54};

	CvMat mat=cvMat(2, 2, CV_32FC1, vals);

	for (int i=0; i<mat.width; i++)//列
	{
		for (int j=0; j<mat.height; j++)//行
		{
			*((float *)cvPtr2D(&mat, j, i)) = 0.11;//存
			float *elem=(float *)cvPtr2D(&mat, j, i);//取
			cout<<*elem<<" ";
		}
		cout<<endl;
	}
}

opencv 矩阵的存取_第4张图片


第一个参数表示为矩阵指针,紧跟其后的参数表示索引的整数值,最后一个是可选的参数,它表示输出值的类型。

对于cvPtrND()来说,第二个参数是一个指向一个整型数组的指针,这个数组中包含索引的合适数字。


如果仅仅是读取函数,可用另一个函数族cvGet*D


CvMat 和 IplImage元素函数

double cvGetReal1D(const CvArr* arr, int idx0);

double cvGetReal2D(const CvArr* arr, int idx0, int idx1);

double cvGetReal3D(const CvArr* arr, int idx0, int idx1, int idx2);

double cvGetRealND(const CvArr* arr, int* idx);


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

CvScalar cvGet2D(const CVArr* arr, int idx0, int idx1);

CvScalar cvGet3D(const CvArr* arr, int idx0, int idx1, int idx2);

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


cvGet*D中有四个函数返回的是整型的,另外四个的返回值是CvScalar类型的。这意味着在使用这些函数的时候,会有很大的空间浪费。所以,只是在你认为用这些函数比较方便和高效率的时候才用到它们,否则,最好用cvPtr*D

(个人使用,目前看来,在存取IplImage类型的变量时 CvScalar类型还是很方便的)


cvSet*D和cvGet*D多少有些类似,它通过一次函数调用为一个矩阵或图像中的元素设置值,函数cvSetReal*D()函数和cvSet*D()可以用来设置矩阵或图像中元素的数值

为CvMat或者IplImage元素设定值的函数

void cvSetReal1D(CvArr* arr, int idx0, double value);

void cvSetReal2D(CvArr* arr, int idx0, int idx1, double value);

void cvSetReal3D(CvArr* arr, int idx0, int idx1, int idx2, double value);

void cvSetRealND(CvArr* arr, int* idx, double value);


void cvSet1D(CvArr* arr, int idx0, CvScalar value);

void cvSet2D(CvArr* arr, int idx0, int idx1, CvScalar value);

void cvSet3D(CvArr* arr, int idx0, int idx1, int idx2, CvScalar value);

void cvSetND(CvArr* arr, int* idx, CvScalar value);


cvmSet()和cvmGet()这两个函数用于处理浮点数单通道矩阵,so easy!!!

double cvmGet(const CvMat* mat, int row, int col);

void cvmSet(CvMat* mat, int row, int col, double value);


//矩阵的存取
void accessMat(void)
{
	float vals[]={0.32, 1.55, 2.24, 6.54};

	CvMat mat=cvMat(2, 2, CV_32FC1, vals);

	for (int i=0; i<mat.width; i++)//列
	{
		for (int j=0; j<mat.height; j++)//行
		{
			cvmSet(&mat, j, i, 0.11);
			//*((float *)cvPtr2D(&mat, j, i)) = 0.11;//存
			//float *elem=(float *)cvPtr2D(&mat, j, i);//取
			float elem=cvmGet(&mat, j, i);
			cout<<elem<<" ";
		}
		cout<<endl;
	}
}

opencv 矩阵的存取_第5张图片


#############################################################3


恰当的方法 !!!

如果打算对数组中的每一个元素执行一些操作,使用自己的指针是尤为重要的(假设没有可以为你执行任务的OpenCV函数)


累加一个三通道矩阵中的所有元素












你可能感兴趣的:(opencv)