多维矩阵的结构分析:
例子:
- #include "cv.h"
- #include "highgui.h"
- #include <stdio.h>
- #include <ctype.h>
- #include <string>
- void main()
- {
- int size[]={2,3,4};
- CvMatND *myND=cvCreateMatND(3,size,CV_8SC1);
- printf("1 size=%d step=%d/n",myND->dim[0]);
- printf("2 size=%d step=%d/n",myND->dim[1]);
- printf("3 size=%d step=%d/n",myND->dim[2]);
- }
结果:
- 1 size=2 step=12
- 2 size=3 step=4
- 3 size=4 step=1
经过OpenCV源代码分析:
(1)在cvCreateMatND函数中先后又调用了cvCreateMatNDHeader和cvCreateData函数。
源码:
- CV_IMPL CvMatND*
- cvCreateMatND( int dims, const int* sizes, int type )
- {
- CvMatND* arr = 0;
- CV_FUNCNAME( "cvCreateMatND" );
- __BEGIN__;
- CV_CALL( arr = cvCreateMatNDHeader( dims, sizes, type ));
- CV_CALL( cvCreateData( arr ));
- __END__;
- if( cvGetErrStatus() < 0 )
- cvReleaseMatND( &arr );
- return arr;
- }
(2)在cvCreateMatNDHeader中,首先为CvMatND结构体分配了内存,然后接着调用了cvInitMatNDHeader函数。
源码:
- CV_IMPL CvMatND*
- cvCreateMatNDHeader( int dims, const int* sizes, int type )
- {
- CvMatND* arr = 0;
- CV_FUNCNAME( "cvCreateMatNDHeader" );
- __BEGIN__;
- if( dims <= 0 || dims > CV_MAX_DIM )
- CV_ERROR( CV_StsOutOfRange,
- "non-positive or too large number of dimensions" );
- CV_CALL( arr = (CvMatND*)cvAlloc( sizeof(*arr) ));
- CV_CALL( cvInitMatNDHeader( arr, dims, sizes, type, 0 ));
- arr->hdr_refcount = 1;
- __END__;
- if( cvGetErrStatus() < 0 )
- cvReleaseMatND( &arr );
- return arr;
- }
(3)在cvInitMatNDHeader中,其初始化了结构体CvMatND的各个成员变量。
源码:
- CV_IMPL CvMatND*
- cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes,
- int type, void* data )
- {
- CvMatND* result = 0;
- CV_FUNCNAME( "cvInitMatNDHeader" );
- __BEGIN__;
- type = CV_MAT_TYPE(type);
- int i;
- int64 step = CV_ELEM_SIZE(type);
- if( !mat )
- CV_ERROR( CV_StsNullPtr, "NULL matrix header pointer" );
- if( step == 0 )
- CV_ERROR( CV_StsUnsupportedFormat, "invalid array data type" );
- if( !sizes )
- CV_ERROR( CV_StsNullPtr, "NULL <sizes> pointer" );
- if( dims <= 0 || dims > CV_MAX_DIM )
- CV_ERROR( CV_StsOutOfRange,
- "non-positive or too large number of dimensions" );
- for( i = dims - 1; i >= 0; i-- )
- {
- if( sizes[i] <= 0 )
- CV_ERROR( CV_StsBadSize, "one of dimesion sizes is non-positive" );
- mat->dim[i].size = sizes[i];
- if( step > INT_MAX )
- CV_ERROR( CV_StsOutOfRange, "The array is too big" );
- mat->dim[i].step = (int)step;
- step *= sizes[i];
- }
- mat->type = CV_MATND_MAGIC_VAL | (step <= INT_MAX ? CV_MAT_CONT_FLAG : 0) | type;
- mat->dims = dims;
- mat->data.ptr = (uchar*)data;
- mat->refcount = 0;
- mat->hdr_refcount = 0;
- result = mat;
- __END__;
- if( cvGetErrStatus() < 0 && mat )
- {
- mat->type = 0;
- mat->data.ptr = 0;
- }
- return result;
- }
- (4)cvCrateData源码如下所示
- 源码:
-
- CV_IMPL void
- cvCreateData( CvArr* arr )
- {
- CV_FUNCNAME( "cvCreateData" );
- __BEGIN__;
- if( CV_IS_MAT_HDR( arr ))
- {
- size_t step, total_size;
- CvMat* mat = (CvMat*)arr;
- step = mat->step;
- if( mat->data.ptr != 0 )
- CV_ERROR( CV_StsError, "Data is already allocated" );
- if( step == 0 )
- step = CV_ELEM_SIZE(mat->type)*mat->cols;
- total_size = step*mat->rows + sizeof(int) + CV_MALLOC_ALIGN;
- CV_CALL( mat->refcount = (int*)cvAlloc( (size_t)total_size ));
- mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
- *mat->refcount = 1;
- }
- else if( CV_IS_IMAGE_HDR(arr))
- {
- IplImage* img = (IplImage*)arr;
- if( img->imageData != 0 )
- CV_ERROR( CV_StsError, "Data is already allocated" );
- if( !CvIPL.allocateData )
- {
- CV_CALL( img->imageData = img->imageDataOrigin =
- (char*)cvAlloc( (size_t)img->imageSize ));
- }
- else
- {
- int depth = img->depth;
- int width = img->width;
- if( img->depth == IPL_DEPTH_32F || img->nChannels == 64 )
- {
- img->width *= img->depth == IPL_DEPTH_32F ? sizeof(float) : sizeof(double);
- img->depth = IPL_DEPTH_8U;
- }
- CvIPL.allocateData( img, 0, 0 );
- img->width = width;
- img->depth = depth;
- }
- }
- else if( CV_IS_MATND_HDR( arr ))
- {
- CvMatND* mat = (CvMatND*)arr;
- int i;
- size_t total_size = CV_ELEM_SIZE(mat->type);
- if( mat->data.ptr != 0 )
- CV_ERROR( CV_StsError, "Data is already allocated" );
- if( CV_IS_MAT_CONT( mat->type ))
- {
- total_size = (size_t)mat->dim[0].size*(mat->dim[0].step != 0 ?
- mat->dim[0].step : total_size);
- }
- else
- {
- for( i = mat->dims - 1; i >= 0; i-- )
- {
- size_t size = (size_t)mat->dim[i].step*mat->dim[i].size;
- if( total_size < size )
- total_size = size;
- }
- }
- CV_CALL( mat->refcount = (int*)cvAlloc( total_size +
- sizeof(int) + CV_MALLOC_ALIGN ));
- mat->data.ptr = (uchar*)cvAlignPtr( mat->refcount + 1, CV_MALLOC_ALIGN );
- *mat->refcount = 1;
- }
- else
- {
- CV_ERROR( CV_StsBadArg, "unrecognized or unsupported array type" );
- }
- __END__;
- }