6

I'm trying to pass a huge Mat image (98304x51968) between openCV and itk using the ITK to openCV Bridge. I have an error :

Insufficient memory (OverFlow for imageSize) in cvIniyImageHeader, file opencv\modules\core\src\array.cpp line 2961.

Does this mean that opencv has a limit on the size of images?

9
  • 1
    The error message indicates more running out of memory than some OpenCV limit. What is your amout of RAM? Note that your image has almost 5 gigapixels. How many bits per pixel it uses? Commented Jul 24, 2018 at 8:02
  • 2
    8 pixels and i have 156 GB, so it's not a RAM problem. I find a topic that talk about similar problem : github.com/opencv/opencv/pull/7507 Commented Jul 24, 2018 at 8:26
  • If on Linux or macOS, try running ulimit -a to see if you have restrictions on memory you may allocate. Commented Jul 24, 2018 at 9:03
  • It's windows, so i dont think so. Commented Jul 24, 2018 at 9:07
  • OpenCV has image size limits, but your error is still an "insufficuent memory". Can you try to malloc the same amount of memory manually instead? Should be close to 39 GB if you really have 8 channels per pixel. Maybe your RAM is split between CPUs or fragmented or sth. Commented Jul 24, 2018 at 10:14

2 Answers 2

2

Good news, since this pull request: handle huge matrices correctly #11505, you should be able to do something like this (code taken from the test):

Mat m(65000, 40000, CV_8U); ASSERT_FALSE(m.isContinuous()); uint64 i, n = (uint64)m.rows*m.cols; for( i = 0; i < n; i++ ) m.data[i] = (uchar)(i & 255); cv::threshold(m, m, 127, 255, cv::THRESH_BINARY); int nz = cv::countNonZero(m); // FIXIT 'int' is not enough here (overflow is possible with other inputs) ASSERT_EQ((uint64)nz, n / 2); 

Since countNonZero() returns an int, overflow is possible. This means that you should be able to create huge matrix but not all OpenCV function can handle correctly huge matrix.


Regarding your issue, this is the code for ITKImageToCVMat in v5.0a02:

template<typename TInputImageType> cv::Mat OpenCVImageBridge::ITKImageToCVMat(const TInputImageType* in, bool force3Channels) { // Extra copy, but necessary to prevent memory leaks IplImage* temp = ITKImageToIplImage<TInputImageType>(in, force3Channels); cv::Mat out = cv::cvarrToMat( temp, true ); cvReleaseImage(&temp); return out; } 

As you can see, IplImage image is still used and should be the source of your error. Your best option currently should be to do the conversion yourself. Maybe something like (I don't know ITK, same input and output type, one channel):

typename ImageType::RegionType region = in->GetLargestPossibleRegion(); typename ImageType::SizeType size = region.GetSize(); unsigned int w = static_cast< unsigned int >( size[0] ); unsigned int h = static_cast< unsigned int >( size[1] ); Mat m(h, w, CV_8UC1, in->GetBufferPointer()); 

No copy is involved here. If you want to copy, you can do:

Mat m_copy = m.clone(); 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Catree. Indeed, i did it myself and it worked.
2

There seems to be a signed int (typically 32 bit) limitation in IplImage: From the named .cpp file here's the code snippet that leads to the error:

const int64 imageSize_tmp = (int64)image->widthStep*(int64)image->height; image->imageSize = (int)imageSize_tmp; if( (int64)image->imageSize != imageSize_tmp ) CV_Error( CV_StsNoMem, "Overflow for imageSize" ); 

Which looks like (without checking) image->imageSize is a 32 bit signed int and this part of the code will detect and handle overflows. According to your posted link in the comments, the IplImage "bug" might got fixed (I didn't check that), so MAYBE you can remove this overflow detection step in the OpenCV code for newer IplImage versions, but that's just a guess and has to be confirmed. You'll have to check the type of image->imageSize. If it is a 64 bit type, you can probably change the openCV code to support Mats bigger than 2147483647 bytes.

EDIT: REMARK: I checked the code in OpenCV 3.4 but the code line was the right one, so probably in Version 4.0 there's no change yet.

If your are sure that the IplImage limitation got fixed, you can try this:

const int64 imageSize_tmp = (int64)image->widthStep*(int64)image->height; image->imageSize = imageSize_tmp; // imageSize isn't 32 bit signed int anymore! //if( (int64)image->imageSize != imageSize_tmp ) // no overflow detection necessary anymore // CV_Error( CV_StsNoMem, "Overflow for imageSize" ); // no overflow detection necessary anymore 

but better make sure that IplImage's imageSize is 64 bit now ;)

UPDATE: The linked fix in https://github.com/opencv/opencv/pull/7507/commits/a89aa8c90a625c78e40f4288d145996d9cda3599 ADDED the overflow detection, so PROBABLY IplImage still has the 32 bit int imageSize limitation! Be careful here!

3 Comments

int is so much faster typed than size_t :D
You can do this now (see) with Mat: Mat m; m.create(65000, 40000, CV_8U);. IplImage should not be used at all in modern OpenCV (>= 2.4).
probably IplImages are created internally when OpenCV is used with IPP support?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.