矩阵的使用与操作

引言

矩阵和图像的使用与操作是掌握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 );
}

测试输出结果:

矩阵的使用与操作_第1张图片

生成随机数实例

/*
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);
}
测试输出结果:

矩阵的使用与操作_第2张图片矩阵的使用与操作_第3张图片

计算DCT变换实例

// 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);
}

测试输出结果:

矩阵的使用与操作_第4张图片

测试矩阵乘法和将缓存数据填入CvMat数组中实

// 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;
}
测试输出结果:

矩阵的使用与操作_第5张图片


关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博客和新浪微博songzi_tea.

你可能感兴趣的:(opencv,访问矩阵元素,分配与释放矩阵,矩阵和向量操作)