Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very large image not supported (area > 2^32) #10211

Closed
FlorentTomi opened this issue Dec 1, 2017 · 15 comments
Closed

Very large image not supported (area > 2^32) #10211

FlorentTomi opened this issue Dec 1, 2017 · 15 comments
Labels
future This issue can't be fixed during restrictions of the compatibility requirements priority: low RFC

Comments

@FlorentTomi
Copy link

FlorentTomi commented Dec 1, 2017

  • OpenCV => 3.3.1
  • Operating system => Windows 10 Pro (64bit)

Related forum link
http://answers.opencv.org/question/178840/very-very-large-image-causes-issues-with-function-int-type-related/

Detailed description
Large images with an area greater than 2^32 cause crashes or do not work in some functions.
A simple example is the cv::threshold method with Triangle method flag:
The operation size.width *= size.height; is done (in file imgproc/src/thresh.cpp, line 1099), but in the case of large images, this overflows the "small" integer int.

Moreover, images with area greater than 2^30 cannot be opened (see imgcodecs/src/loadsave.cpp, line 65). As a workaround, I just modified the mentioned line with #define CV_IO_MAX_IMAGE_PIXELS((uint64)1 << 40, but this can't be a long term fix.

Suggestions
Maybe using other types (like int64 or size_t) for size-related (or maybe index-related) code may be a good idea.
Maybe this can be activated via a preprocessor directive.

@FlorentTomi
Copy link
Author

I'm planning to "fix" this issue for my job (as it is an urgent matter).
What should be the good "OpenCV-way" of doing this ?

@kinchungwong
Copy link
Contributor

It will be impossible to fix across the entire OpenCV library.

OpenCV can be seen as having several layers of "business value".

Among them, one of the layer is the definition of cv::Mat and cv::Mat_<T> (and also the related cv::Matx_<T, M, N>). This specifies a common multi-dimensional array type for in-memory objects, and is used for all communication purposes between the API functions of OpenCV.

Another of the layer is the vast collection of image processing functions. All of them operate on cv::Mat or cv::Mat_<T>.

The issue of assuming that memory address operations don't involve offsets (sizes, lengths, differences) more than 32-bit affects all layers. So, even if you fix the issue in cv::Mat_<T> and cv::Mat, all of the image processing functions will still fail. Therefore you will have to fix the image processing functions one by one.

Thus, if it is a job necessity, then the first priority is to identify a minimum subset of OpenCV API that needs to be fixed, and then reimplement those functionalities by taking the code from OpenCV and modify it, or to completely reimplement the functionalities.

A typical approach is to use tiling. This involve defining your own large matrix data type, say your_cv::BigMat_<T> which mirrors cv::Mat_<T> except that large matrix dimensions and pointer offsets are supported. Then, define functions which perform copying and pasting sub-rectangles between your BigMat and OpenCV Mat. These copy and paste operations can only operate sub-rectangles smaller than the OpenCV size limit.

Years ago I had implemented a tiling approach to workaround a limitation in OpenCV function called cv::remap which is used for image rotation. That API function contains SSE2 instructions which had a limit of 32768 bytes per row of pixel. The approach involves copying and pasting sub-rectangles while staying within OpenCV limit. The code is https://gist.github.com/kinchungwong/141bfa2d996cb5ae8f42

OpenCV has not yet adopted a library-wide framework for very large matrices or tiled matrices yet. Usually, it is up to the users of OpenCV to implement such framework.

@ihhub
Copy link

ihhub commented Dec 3, 2017

I faced the same problem long time ago (my images were 10+ GB). @K-Shinotsuka is correct about tiling idea if you face such limitation in size. Moreover you can enhance his idea by just assigning pointers from your big image/class into cv::mat objects without copy pasting your large memory area. But then you have to write a wrapper/framework to perform the same operation on multiple tiles.

@FlorentTomi
Copy link
Author

I think tiling may be a good idea, but will this idea still work on "whole-image" algorithm (like the ones who needs the full histogram of the image, ie. automatic thresholding) ?

Even if I implement this idea for myself, I honestly think others will fall in the same "trap" as me. I don't remember seeing any clue that OpenCV could not handle such images.
Maybe more documentation is needed ?

@ntomita
Copy link

ntomita commented Feb 8, 2018

As far as I know any version above (or equal to) 3.3.1 doesn't load very large image. I downgraded to 3.3.0.10 and it works.

@FlorentTomi
Copy link
Author

@ntomita Thanks for the info.
However, the reading of the image is the "minor" issue. Problem is that, even if you can read it, some (most ?) of the algorithm won't work for various reasons (e.g. using int32 to store areas).

@ntomita
Copy link

ntomita commented Feb 9, 2018

@FlorentTomi I see, that's why newer version has assertion statements to void the unintentional crash. Definitely the data type need to be updated so it can handle large images, which are "large" at this time but for next 5 years I believe people, including scientists, wouldn't think those are large as technology updates.

@hrnr
Copy link
Contributor

hrnr commented Apr 23, 2018

Is there a plan to address this in OpenCV 4.0, @vpisarev ? IHMO this could go as evolution proposal too.

Starting with converting cv::Mat to use size_t everywhere and then we could fix bug-by-bug all the other places using ints.

@vpisarev
Copy link
Contributor

done! see #11505

@jxu
Copy link
Contributor

jxu commented Jun 7, 2019

Is it done? I tried to open a 49800 x 39401 image and these restrictions are still here

static const size_t CV_IO_MAX_IMAGE_PIXELS = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PIXELS", 1 << 30);

@jxu
Copy link
Contributor

jxu commented Jun 14, 2019

To work with large files (at your own risk) you can modify environment variables CV_IO_MAX_IMAGE_WIDTH, CV_IO_MAX_IMAGE_HEIGHT, OPENCV_IO_MAX_IMAGE_PIXELS by doing for example

export CV_IO_MAX_IMAGE_PIXELS=1099511627776

Thaks to @alalek for pointing this out to me.

@egorpugin
Copy link
Contributor

What about an ability to change this from inside the program?
Those vars are globals and adding putenv in main does not help (only in global var).

@jtoa2
Copy link

jtoa2 commented May 25, 2020

i'm also trying to modify these variables from within a jupyter notebook running on a remote server, i've tried

%env os.environ["OPENCV_IO_MAX_IMAGE_PIXELS"] = pow(2,90).str()
import cv2

without success

@egorpugin
Copy link
Contributor

@jtoa2
There must be strange format like 10000MB, 50KB.
And also there's a bug with such formats.
#17352

@lferreiraMD
Copy link

@jtoa2 Didn't work for me either. Neither did setting the environment variable directly on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
future This issue can't be fixed during restrictions of the compatibility requirements priority: low RFC
Projects
None yet
Development

Successfully merging a pull request may close this issue.