一、矩阵的创建
矩阵有多种创建 方法,也就是说定义个一个矩阵变量有多种办法:
(1)最常见的方法是用cvCreateMat() ,它由两个原函数组成,cvCreateMatHeader () 和 cvCreateData () 。
//Create a new rows by cols matrix of type 'type'. // CvMat* cvCreateMat( int rows, int cols, int type );
type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>. 例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵. 例程: CvMat* M = cvCreateMat(4,4,CV_32FC1); 创建一个4X4的矩阵,矩阵的元素的数据类型时float(不是double型!!) cvCreateMat
Creates a matrix header and allocates the matrix data.
创建一个矩阵头并且为矩阵数据分配内存空间
CvMat* cvCreateMat(
int rows,
int cols,
int type);
rows Number of rows in the matrix//矩阵的行数
cols Number of columns in the matrix//矩阵的列数
type The type of the matrix elements in the form CV <bit depth><S|U|F>C<number of
channels>, where S=signed, U=unsigned, F=float. For example, CV 8UC1 means the
elements are 8-bit unsigned and the there is 1 channel, and CV 32SC2 means the elements
are 32-bit signed and there are 2 channels.
cvCreateMat实际上就是以下形式的一种简洁形式
This is the concise form for:
CvMat* M = cvCreateMatHeader(4, 4, CV_32FC1); cvCreateData(M); //以上两个语句完全等价于以下语句 CvMat* M = cvCreateMat(4, 4, CV_32FC1);
(2)cvCreateMatHeader() 函数创建CvMat结构,不为数据分配内存,而cvCreateData ()函数只负责数据的内存分配。有时,只需要函数cvCreateMatHeader (),因为已因其他理由分配了存储空间,或因为还不准备分配存储空间。
cvCreateMatHeader
Creates a matrix header but does not allocate the matrix data.
//创建一个矩阵头但是不为矩阵数据分配内存空间
CvMat* cvCreateMatHeader (
int rows,
int cols,
int type);
rows Number of rows in the matrix
cols Number of columns in the matrix
type Type of the matrix elements, see cvCreateMat
The function allocates a new matrix header and returns a pointer to it. The matrix data can
then be allocated using cvCreateData or set explicitly to user-allocated data via cvSetData.
cvCreateData
Allocates array data//为数组分配内存空间
void cvCreateData(CvArr* arr);
arr Array header//arr是数组头
The function allocates image, matrix or multi-dimensional array data. Note that in the case
of matrix types OpenCV allocation functions are used and in the case of IplImage they are used
unless CV TURN ON IPL COMPATIBILITY was called. In the latter case IPL functions are used
to allocate the data.
//该函数为图像、矩阵或者多维数组分配内存空间。请注意,当arr是矩阵的时候调用opencv内存分配函数,当arr是图像的时候,除非使用 CV TURN ON IPL COMPATIBILITY也是 调用opencv内存分配函数。后者(就是arr是图像的时候)调用IPL函数进行数据内存的分配。
//Create only matrix header without allocating data // CvMat* cvCreateMatHeader( int rows, int cols, int type );
(3)是用函数cvCloneMat (CvMat*) ,它依据一个现有矩阵创建一个新的矩阵。
//Allocate a new matrix just like the matrix 'mat'. // CvMat* cvCloneMat( const cvMat* mat );
CvMat* M1 = cvCreateMat(4,4,CV_32FC1); CvMat* M2; M2=cvCloneMat(M1);
cvCloneMat
Creates a full matrix copy.//创建一个既有矩阵数据头又有矩阵数据内存空间的矩阵
CvMat* cvCloneMat(const CvMat* mat);
mat Matrix to be copied
Creates a full copy of a matrix and returns a pointer to the copy.
(4)直接定义
//当然该方法不常用,并经熟悉opencv就会知道里面处处是指针,所以一般用 cvCreateMat()
CvMat mb ;
(5)当创建的矩阵不再需要时,可以调用函数cvReleaseMat(CvMat*) 释放它。
注意 :由上面(4)创建的矩阵不需要调用 cvReleaseMat(CvMat*) 释放它。
// Free the matrix 'mat', both header and data. // void cvReleaseMat( CvMat** mat );
二、矩阵的赋值(初始化)
(1)cvInitMatHeader和已有数据进行初始化
//Initialize header on existiong CvMat structure // CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type, void* data = NULL, int step = CV_AUTOSTEP );
//定为double是不行的,浮点型的话只支持float!! float arr[] = { 1,2,3, 4,5,6, }; //1.利用已有数据进行初始化 CvMat ma; cvInitMatHeader( &ma,2,3,CV_32FC1,arr,CV_AUTOSTEP );
This function is often used to process raw data with OpenCV matrix functions. For example, the following code computes the matrix product of two matrices, stored as ordinary arrays: double a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; double b[] = { 1,2,3,4,5, 6,7,8,9,10,11,12 }; double c[9]; CvMat Ma, Mb, Mc ; cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a); cvInitMatHeader(&Mb, 4, 3, CV_64FC1, b); cvInitMatHeader(&Mc, 3, 3, CV_64FC1, c); cvMatMulAdd(&Ma, &Mb, 0, &Mc); // the c array now contains the product of a (3x4) and b (4x3)
(2)利用CvMat构造函数进行初始化。
cvMat
Initializes matrix header (lightweight variant).
CvMat cvMat(
int rows,
int cols,
int type,
void* data=NULL);
rows Number of rows in the matrix
cols Number of columns in the matrix
type Type of the matrix elements - see cvCreateMat
data Optional data pointer assigned to the matrix header
Initializes a matrix header and assigns data to it. The matrix is filled row-wise (the first cols
elements of data form the first row of the matrix, etc.)
This function is a fast inline substitution for cvInitMatHeader. Namely, it is equivalent to:
CvMat mat;
cvInitMatHeader(&mat, rows, cols, type, data, CV_AUTOSTEP);
//定为double是不行的,浮点型的话只支持float!! float arr[] = { 1,2,3, 4,5,6, }; //2.cvInitHeader与cvMat原理几乎都是一样的,只是函数原型不太一样 CvMat mb ; mb = cvMat(2,3,CV_32FC1,arr);
三、实战
#include "cv.h" #include "cxcore.h" #include <stdio.h> //打印矩阵的元素 //参考了《学习opencv》一书的例3-9 void print_mat( const CvMat* mat,const int row ,const int col ) { int i ; int j ; //用指针实现了对矩阵元素的访问 for ( i = 0 ; i < row ; i++ ) { /*uchar* ptr = (uchar*)(mat->data.ptr + i * mat->step);*/ //用uchar就是错的 float* ptr = (float*)( mat->data.ptr + i * mat->step ) ; for ( j = 0 ; j < col ; j++ ) { printf("/t%f",ptr[j]);//用*ptr++也可以 } printf("/n"); } printf("/n/n"); } // int main() { //定为double是不行的,浮点型的话只支持float!! float arr[] = { 1,2,3, 4,5,6, }; //1.利用已有数据进行初始化 CvMat ma; cvInitMatHeader( &ma,2,3,CV_32FC1,arr,CV_AUTOSTEP ); //2.cvInitHeader与cvMat原理几乎都是一样的,只是函数原型不太一样 CvMat mb ; mb = cvMat(2,3,CV_32FC1,arr); //3.cvCreateMat返回一个矩阵指针 CvMat* mc = cvCreateMat( 2,2,CV_32FC1 ); //cvmGet(...)、cvmSet(...)只对浮点型单通道数据有效 cvmSet(mc,0,0,1); cvmSet(mc,0,1,2); cvmSet(mc,1,0,3); cvmSet(mc,1,1,4); CvMat* md = cvCreateMat( 3,4,CV_64FC1 ); int i ; int j ; int n = 0 ; //用指针实现了对矩阵元素的访问 for ( i = 0 ; i < 3 ; i++ ) { float* ptr = (float*)( md->data.ptr + i * md->step ) ; for ( j = 0 ; j < 4 ; j++ ) { ptr[j] = ++n ; } printf("/n"); } print_mat( &ma,2,3 ); print_mat( &mb,2,3 ); print_mat( mc,2,2 ); print_mat( md ,3,4); cvReleaseMat(&mc); cvReleaseMat(&md); return 0 ; }
运行结果:
opencv@ubuntu:~/桌面/opencv$ gcc `pkg-config opencv --libs --cflags opencv` -g mat.c -o mat opencv@ubuntu:~/桌面/opencv$ ./mat 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 1.000000 2.000000 3.000000 4.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000 11.000000 12.000000
一个一个字码实在不是容易,怕误人子弟还要参考英文reference。转载请注明出处http://blog.csdn.net/moc062066/archive/2011/06/15/6546612.aspx 。谢谢!!