opencv学习笔记之二 矩阵的维和通道

by 麦香鱼香麦

一、五个常见的数据类型:

1.CvPoint  

CvPoint
二维坐标系下的点,类型为整型 

CvPoint2D32f  //二维空间中的点

CvPoint3D32f  //三维空间中的点

typedef struct CvPoint
{
	//默认左上为基点
	int x; /* X坐标, 通常以0为基点 */
	int y; /* y坐标, 通常以0为基点 */
}
CvPoint;

/* 构造函数 */
inline CvPoint cvPoint( int x, int y );  //内联函数,表示图像中的点坐标
/* 从 CvPoint2D32f类型转换得来 */
inline CvPoint cvPointFrom32f( CvPoint2D32f point )

2.CvSize

CvSize 
矩形框大小,以像素为精度 

CvSize2D32f   //浮点型


typedef struct CvSize
{
int width; /* 矩形宽 */
int height; /* 矩形高 */
}
CvSize;


/* 构造函数 */
inline CvSize cvSize( int width, int height );//返回图像的尺寸。

IplImage* img;
	img = cvLoadImage("D:\\PERSONAL\\VC++\\OpenCV\\image\\red.jpg");
	cvNamedWindow("pikaqiu");

	CvPoint pt1;
	pt1.x = 1; pt1.y = 1;
	CvPoint pt2;
	pt2.x = 100; pt2.y = 100;

//	CvRect rect;
//	cvRect(pt1.x,pt1.y,15,15);

//	CvScalar cvScalar(
	cvRectangle(img,pt1,pt2,CV_RGB(0,0,0));
	cvShowImage("pikaqiu",img);

	cvWaitKey(0);
	cvReleaseImage(&img);
	cvDestroyWindow("pikaqiu");


3.CvRect  

CvRect
矩形框的偏移和大小   可以用来表示图像的部分区域   具体用法待后续学习

typedef struct CvRect
{
int x; /* 方形的最左角的x-坐标 */
int y; /* 方形的最上或者最下角的y-坐标 */
int width; /* 宽 */
int height; /* 高 */
}
CvRect;
/* 构造函数*/
inline CvRect cvRect( int x, int y, int width, int height );

4.CvScalar

可以用来表示B、G、R和alpha(表示透明度)

CvScalar
可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器

typedef struct CvScalar
{
double val[4]
}
CvScalar;


/* 构造函数1:用val0初始化val[0]用val1初始化val[1], 以此类推*/
inline CvScalar cvScalar( double val0, double val1=0,double val2=0, double val3=0 );


/* 构造函数2:用val0123初始化所有val[0]...val[3] */
inline CvScalar cvScalarAll( double val0123 );


/* 构造函数3:用val0初始化val[0],用0初始化val[1],val[2],val[3] */
inline CvScalar cvRealScalar( double val0 );

5.CvArr->CvMat->IplImage

使得接口函数更加通用。

by 麦香鱼香麦

二、矩阵元素的访问方式

方式一 :第一种是调用cvGetReal_1D/2D/3D……//一维二维三维矩阵


//=========       二维矩阵,单通道。

int _tmain(int argc, _TCHAR* argv[])
{
	float data[18]={
		1, 2,3,4,5,6,
		7, 8,9,10,11,12,
		13,14,14,16,17,18
	};
	CvMat mat;
	//初始化矩阵
	cvInitMatHeader(&mat,3,6,CV_32FC1,data);//CV_32FC1:4字节,单通道。3行6列。
	//方式一访问 通过cvGetReal
	for(int y = 0 ; y < mat.rows ; y++)
	{
		for(int x = 0 ; x < mat.cols ; x++ )
		{
			float value = (float)cvGetReal2D(&mat,y,x);//二维的数组 注意是先 y 后 x
			printf("%f  ",value);
		}
		printf("\n");
	}
	return 0;
}

缺点:如果矩阵的元素很多,调用子程序需要不断地入栈出栈,影响效率。


//=========       二维矩阵,双通道每个元素中有两个值(X1,X2)

example1: 利用单通道显示  同样的显示效果

……
cvInitMatHeader(&mat,3,3,CV_32FC1,data);//CV_32FC1:4字节,单通道。3行6列。
……
	for(int y = 0 ; y < mat.rows ; y++)
	{
		for(int x = 0 ; x < mat.cols ; x++ )
		{
			float value[2];
			value[0] = (float)cvGetReal2D(&mat,y,x);
			value[1] = (float)cvGetReal2D(&mat,y,++x);
			printf("(%f,%f) ",value[0],value[1]);
		}
		printf("\n");
	}

注释

/* value = arr(idx0,idx1,...) */
CVAPI(CvScalar) cvGet1D( const CvArr* arr, int idx0 );
CVAPI(CvScalar) cvGet2D( const CvArr* arr, int idx0, int idx1 );
CVAPI(CvScalar) cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );
CVAPI(CvScalar) cvGetND( const CvArr* arr, const int* idx );

/* for 1-channel arrays */
CVAPI(double) cvGetReal1D( const CvArr* arr, int idx0 );
CVAPI(double) cvGetReal2D( const CvArr* arr, int idx0, int idx1 );
CVAPI(double) cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 );
CVAPI(double) cvGetRealND( const CvArr* arr, const int* idx );


example2:  利用双通道

注意cvInitMatHeader() 中的参数3,3(三行三列)   以及   CV_32F2  表示双通道

……
cvInitMatHeader(&mat,3,3,CV_32FC2,data);// CV_32FC1:4字节,双通道。3行3列。
……
for(int y = 0 ; y < mat.rows ; y++)
	{
		for(int x = 0 ; x < mat.cols ; x++ )
		{
			CvScalar value = cvGet2D(&mat,y,x);
			printf("(%f,%f) ",value.val[0],value.val[1]);
		}
		printf("\n");
	}

//=========       多维矩阵

//多维度的
    //int size[3]={2,2,2}; //x y z 三个坐标值的取值范围1/0
	//CvMatND mat_nd;
	//cvInitMatNDHeader(&mat_nd,3,size,CV_32FC1,data);//3维 /CV_32FC1:4字节,单通道。


方式二 : 使用指针来访问

//========       二维一通道(类似B)

CvMat mat;
		//方式二:通过指针访问
	        //初始化矩阵
	cvInitMatHeader(&mat,3,6,CV_32FC1,data);//CV_32FC1:4字节,单通道。3行6列。
	int nchannals = 1; //修改矩阵的通道值
	       //mat.data.ptr//数据块的起始地址
	for(int y = 0 ; y < mat.rows ; y++)
	{
		float* p_float = (float*)(mat.data.ptr + y*mat.step); //ptr是 unsigened char*

		for(int x = 0 ; x < mat.cols ; x++ )
		{
			float value = *(p_float + x*nchannals);
			printf("%f  ",value);
		}
		printf("\n");
	}
修改矩阵的通道值时,要注意初始化函数 cvInitMatHeader()  中的一致。

指针的加加减减,改变的数据类型的字节数   2(char/unsigned char [sizeof(XXX)])  4(int)


/========       二维双通道(B,G)

CvMat mat;
		//方式二:通过指针访问
	//初始化矩阵
	cvInitMatHeader(&mat,3,3,CV_32FC2,data);//CV_32FC1:4字节,单通道。3行6列。
	int nchannals = 2; //修改矩阵的通道值
		//mat.data.ptr//数据块的起始地址
	for(int y = 0 ; y < mat.rows ; y++)
	{
		偏移到第 y 行
		float* p_float = (float*)(mat.data.ptr + y*mat.step); //ptr是 unsigened char*

		for(int x = 0 ; x < mat.cols ; x++ )
		{
		    	float value[2];
			value[0] = *(p_float + x*nchannals);
			value[1] = *(p_float + x*nchannals + 1);
			
			printf("(%f,%f) ",value[0],value[1]);
		}
		printf("\n");
	}


要注意指针偏移的位置,每步是单位的 sizeof(XXX) 。

在需要将矩阵当做形参传递到子程序中去时,最好使用指针。

by 麦香鱼香麦


你可能感兴趣的:(opencv学习笔记之二 矩阵的维和通道)