矩阵和图像的使用与操作是掌握OpenCV(C语言版)的基本功能。本节主要介绍OpenCV中C语言版(OpenCV2.0以下)的矩阵使用方法。
OpenCV有一个矩阵操作的C语言接口,另外也有一些C++语言的矩阵操作接口,通常C++语言接口更方便,且同样有效。在OpenCV中,向量被当成是行或列为1的矩阵,并且矩阵在内存中的存储方式是按行存储,且每行按4字节对齐。
分配矩阵的函数原型为:
CvMat* cvCreateMat(int rows, in cols,int type);其中,type表示矩阵元素的类型,可以用形式表达为 CV_<bit_depth>(C|U|F)C<number_of_channels>. 如:CvMat* cMat = cvCreateMat(3,5,CV_32FC1);
释放矩阵的函数原型为:
void cvReleaseMat(CvMat**);如: CvMat* cMat = cvCreateMat(3,5,CV_32FC1);
cvReleaseMat(&cMat);
复制矩阵的函数原型为:
CvMat* cvCloneMat(CvMat*);
如:CvMat* cMat = cvCreateMat(3,5,CV_32FC1);
CvMat* cMat1;
cMat1 = cvCloneMat(cMat);
按如下方法初始化矩阵。
double data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; CvMat cMat = cvMat(3,4,CV_64FC1,data);或者
CvMat cMat; cvInitMatHeader(&cMat, 3, 4, CV_64FC1,data);
若访问一个浮点数矩阵的第i行第j列元素,可采用以下几种方式。
下列元素M(i, j)进行数据赋值和读取。
cvmSet(M,i,j, 2,0); //set M(i,j) cMat = cvmGet(M,i,j); //get M(i,j)
以32元素对齐方式存储的元素进行数据赋值。
CvMat* cMat = cvCreateMat(3,4, CV_32FC1); int n = cMat ->cols; float * data = cMat ->data.fl; data[i*n+j] = 5.0;
对以某种对齐方式存储的元素进行数据赋值。
CvMat* cMat = CvCreateMat(3,4,CV_32FC1); int step = cMat->step/sizeof(float); float *data = cMat ->data.fl; (data+i*step)[j] = 5.0;
对已初始化的矩阵a进行数据赋值
double a[10]; CvMat cMat = cvMat(2,4,CV_64FC1,a); a[i*4+j] = 5.0; //cMat(i,j) = 5.0
对矩阵和向量的操作分为几种类型.即:矩阵与矩阵之间的操作,矩阵元素之间的操作,向量乘法操作,单个矩阵操作,非齐次线性系统的求解操作,对称矩阵操作和奇齐值分解操作。在此给出矩阵操作的实例。体会如何进行矩阵操作,参考代码如下所示:
// Testing: Sort 2d points in top-to-bottom left-to-right order. void cvMatTest::Test_SeqSort() { CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* seq = cvCreateSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage ); int i; printf("\n=== Test sequence sorting ==="); for( i = 0; i < 10; i++ ){ CvPoint pt; pt.x = rand() % 1000; pt.y = rand() % 1000; cvSeqPush( seq, &pt ); } printf("\nOriginal point set:\n"); for( i = 0; i < seq->total; i++ ){ CvPoint* pt = (CvPoint*)cvGetSeqElem( seq, i ); printf( "(%d,%d)\n", pt->x, pt->y ); } cvSeqSort( seq, cmp_func, 0 /* userdata is not used here */ ); /* print out the sorted sequence */ printf("\nAfter sorting:\n"); for( i = 0; i < seq->total; i++ ){ CvPoint* pt = (CvPoint*)cvGetSeqElem( seq, i ); printf( "(%d,%d)\n", pt->x, pt->y ); } cvClearSeq( seq ); // Sequence clearing should be done before storage clearing cvReleaseMemStorage( &storage ); }
测试输出结果:
/* Generate normally distributed random numbers. Fill random numbers to arr, of a normal distribution with mean zero and variance one. seed is the random generator seed. Array arr should be pre-allocated before calling this function */ void cvMatTest::GenRandn(CvMat* arr, int seed) { // let's noisy_screen be the floating-point 2d array that is to be "crapped" CvRandState rng; // modify RNG to make it produce normally distributed values rng.state = cvRNG(0xffffffff); cvRandInit( &rng, 0, 1, // use dummy parameters now and adjust them further seed, // use input seed here CV_RAND_NORMAL // specify uniform type ); // fill random numbers to arr, with mean zero and variance one cvRandArr( &rng.state, arr, CV_RAND_NORMAL, cvRealScalar(0), // average intensity cvRealScalar(1) // deviation of the intensity ); // RNG state does not need to be deallocated } void cvMatTest::Test_Rand(){ CvMat* a = cvCreateMat( 10, 6, CV_32F ); int i; printf("\n=== Test generating random matrix ==="); for(i=0;i<5;i++){ cvMatTest::GenRandn(a, i); PrintMat(a); } cvReleaseMat(&a); }测试输出结果:
// test 1-d and 2-d dct transform void cvMatTest::Test_DCT(){ float data[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; CvMat a; a = cvMat(2,4,CV_32FC1,data); printf("\n=== Test DCT ==="); printf("\nOriginal matrix = "); PrintMat(&a); cvDCT(&a, &a, CV_DXT_FORWARD); printf("\n2-D DCT = "); PrintMat(&a); cvDCT(&a, &a, CV_DXT_INVERSE); printf("\n2-D IDCT = "); PrintMat(&a); }
测试输出结果:
// Test matrix multiply void cvMatTest::Test_Multiply(){ double a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; double b[] = { 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12 }; double c[9]; CvMat Ma, Mb, Mc; printf("\n=== Test multiply ==="); cvInitMatHeader( &Ma, 3, 4, CV_64FC1, a, CV_AUTOSTEP ); cvInitMatHeader( &Mb, 4, 3, CV_64FC1, b, CV_AUTOSTEP ); cvInitMatHeader( &Mc, 3, 3, CV_64FC1, c, CV_AUTOSTEP ); cvMatMulAdd( &Ma, &Mb, 0, &Mc ); PrintMat(&Ma); PrintMat(&Mb); PrintMat(&Mc); return; } // Get raw data from data buffer and pass them to a matrix void cvMatTest::Test_cvGetRawData(){ float* data; int step; float a[] = {1, 2, 3, 4, -5, 6, 7, 8, 9, -10, -11, 12 }; CvMat array; CvSize size; int x, y; printf("\n=== Test get raw data ==="); cvInitMatHeader( &array, 3, 4, CV_32FC1, a, CV_AUTOSTEP ); cvGetRawData( &array, (uchar**)&data, &step, &size ); step /= sizeof(data[0]); printf("\nCvMat = "); PrintMat(&array); printf("\nData = "); for( y = 0; y < size.height; y++, data += step ){ printf("\n"); for( x = 0; x < size.width; x++ ) { data[x] = (float)fabs(data[x]); printf("%8.2f",data[x]); } } printf("\n"); return; }测试输出结果:
关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博客和新浪微博songzi_tea.