最近项目需要,学习学习OpenCV库。由于需要处理的图片较大,对其进行缩放时,总是出错。师弟说是由于OpenCV不能加载尺寸超过10000像素的图片。于是在OpenCV中文站查到,OpenCV在highgui的image.cpp文件中定义了下面这个max_img_size:
/*const unsigned max_img_size = 10000;*/ 注释掉
if( (bpp != 8 && bpp != 24 && bpp != 32) ||
/*(unsigned)w >= max_img_size || (unsigned)h >= max_img_size ||*/ 注释掉
(origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL))
{
assert(0); // most probably, it is a programming error
return false;
}
...
注释掉之后,重新编译highgui。现在能打开10000多点的了,但是还是有问题,调试定位到cxcore的cxarray.cpp中的cvCreateImage函数中:
// create IplImage header and allocate underlying data
CV_IMPL IplImage *
cvCreateImage( CvSize size, int depth, int channels )
{
IplImage *img = 0;
CV_FUNCNAME( "cvCreateImage" );
__BEGIN__;
CV_CALL( img = cvCreateImageHeader( size, depth, channels ));
assert( img );
CV_CALL( cvCreateData( img )); // 报错
__END__;
if( cvGetErrStatus() < 0 )
cvReleaseImage( &img );
return img;
}
再进去:
// Allocates underlying array data
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__;
}
下面是cxalloc.cpp中的cvAlloc:
CV_IMPL void* cvAlloc( size_t size )
{
void* ptr = 0;
CV_FUNCNAME( "cvAlloc" );
__BEGIN__;
if( (size_t)size > CV_MAX_ALLOC_SIZE ) // 限制
CV_ERROR( CV_StsOutOfRange,
"Negative or too large argument of cvAlloc function" );
ptr = p_cvAlloc( size, p_cvAllocUserData ); // 报错
if( !ptr )
CV_ERROR( CV_StsNoMem, "Out of memory" );
__END__;
return ptr;
}
按照zbf661 推荐的注释掉限制条件之后,重新编译,打开尺寸为28012*18251的图像,还是有问题,但是zbf661 的测试代码可行:
IPlImage * img = cvCreateImage( cvSize ( 20000 , 20000 ) , 8 , 3 );
cvZero( img ) ;
cvShowImage( "bigimage" ,img ) ;
chai2010 推荐大尺寸图片用GDAL扩展库,看看去!