Remove OpenCV image size limitation - python

I am loading in a very large image (60,000 x 80,000 pixels) and am exceeding the max pixels I can load:
cv2.error: OpenCV(4.2.0) /Users/travis/build/skvark/opencv-python/opencv/modules/imgcodecs/src/loadsave.cpp:75:
error: (-215:Assertion failed) pixels <= CV_IO_MAX_IMAGE_PIXELS in function 'validateInputImageSize'
From what I have found this is referring to the limitation imposed on line 65
Ideally I'd change that to deal with at least 5 gigapixel images
#define CV_IO_MAX_IMAGE_PIXELS (1<<33)
I have seen some workarounds for this (OpenCV image size limit) but those don't seem to address the problem which is an arbitrary definition (I'm working off a high performance server with 700gb ram so compute not an issue).
My issue is that I have no idea where this file is. The error points me towards this "travis" directory which doesn't exist locally for me and in my local environment the c++ files aren't available.
Any idea on where to look to find the c++ library?

You have to modify the openCV source files and then compile it your own.
EDIT: You can also modify environment variables
export CV_IO_MAX_IMAGE_PIXELS=1099511627776

For my problem I should have specified it was a .tif file (NOTE most large images will be in this file format anyway). In which case a very easy way to load it in to a numpy array (so it can then work with OpenCV) is with the package tifffile.
pip install tifffile as tifi
This will install it in your python environment.
import tifffile as tifi
img = tifi.imread("VeryLargeFile.tif")
From here you can use it as you would with any numpy array and it is fully compatible with OpenCV etc.

Adding the following to your program should fix the issue in python opencv.
import os
os.environ["OPENCV_IO_MAX_IMAGE_PIXELS"] = str(pow(2,40))
import cv2

Related

Convert a .jpg image to rgb in micropython?

I am trying to create a program on the Raspberry Pi Pico W that downloads a jpg image and displays a very pixilated version of the image on an addressable led matrix. I have decided to attempt to use micro python as my coding language for this project since I have already completed a similar project in the full python language. Since I am downloading the images from an online source I am stuck using the '.jpg' format at a fixed size.
I have been running into some difficulties processing the image. To run on the addressable LEDs (Neopixel) I want to collect the rgb data from each individual pixel of the .jpg and add them to a list.
Working on python I know that the PIL/Pillow library is a great solution to this problem.
from PIL import Image
image = Image.open('256256.jpg',formats=None)
print(image)
from numpy import asarray
data = asarray(image)
Unfortunately the RP2040 doesn't seem have enough storage space to handle the module.
I need to find a way to decode the image using the modules readily available to micro python.
I have attempted to reverse engineer the PIL open feature but haven't had any luck so far.
Thank you in advance!

Strange behavior in pyvips, impossible to write some images

I'm currently trying to make pyvips work for a project where I need to manipulate images of a "big but still sensible" size, between 1920x1080 and 40000x40000.
The installation worked well, but these particular 2 lines sometime work, sometime don't.
img = pyvips.Image.new_from_file('global_maps/MapBigBig.png')
img.write_to_file('global_maps/MapTest.png')
It seems that for the biggest images, I get the following error message when writing back the image (the loading works fine):
pyvips.error.Error: unable to call VipsForeignSavePngFile
pngload: arithmetic overflow
vips2png: unable to write to target global_maps/MapFishermansRowHexTest.png
I say it seems, because the following lines work perfectly well (with a size of 100 000 x 100 000, far bigger than the problematic images):
size = 100000
test = pyvips.Image.black(size, size, bands=3)
test.write_to_file('global_maps/Test.png')
I could not find an answer anywhere, do you have any idea what I'm doing wrong ?
EDIT:
Here is a link to an image that does not work (it weights 102 Mo).
This image was created using pyvips and a 40 time smaller image, this way:
img = pyvips.Image.new_from_file('global_maps/MapNormal.png')
out = img.resize(40, kernel='linear')
out.write_to_file('global_maps/MapBigBig.png')
And it can be read using paint3D or gimp.
I found your error message in libspng:
https://github.com/randy408/libspng/blob/master/spng/spng.c#L5989
It looks like it's being triggered if the decompressed image size would go over your process pointer size. If I try a 32-bit libvips on Windows I see:
$ ~/w32/vips-dev-8.12/bin/vips.exe copy MapFishermansRowHexBigBig.png x2.png
pngload: arithmetic overflow
vips2png: unable to write to target x2.png
But a 64-bit libvips on Windows works fine:
$ ~/vips-dev-8.12/bin/vips.exe copy MapFishermansRowHexBigBig.png x.png
$
So I think switching to a 64-bit libvips build would probably fix your problem. You'll need a 64-bit python too, of course.
I also think this is probably a libspng bug (or misfeature?) since you can read >4gb images on a 32-bit machine as long as you don't try to read them all in one go (libvips reads in chunks, so it should be fine). I'll open an issue on the libspng repo.

Using composePanorama in Stitcher class with OpenCV-Python bindings

I'm trying to estimate transform for some images and stitch them using stitcher.estimateTransform() and stitcher.composePanorama() in python. After estimating transform, composePanorama gives the error as below:
pano is not a numpy array, neither a scalar
I tried to convert NumPy Array into a Mat object using cv2.fromarray(left), but it only works for cv, not cv2. Therefore how can I convert this numpy to MAT array in cv2. I don't find any examples of using composePanorama with python bindings. Any solution for this error or example of using stitcher.estimateTransform() with OpenCV-Python bindings would be appreciated.
Note: Although Stitching class in OpenCV-Python bindings is not complete (beacuse of auto-generated bindings), help(cv2.createStitcher()) demonstrates that it contains composePanorama() and estimateTransform().
Note: I can use stitcher.stitch() without any problems, but using stitcher.stitch() does not help me, because I'm trying to not calculate the transform for each iteration in the main loop.
My simple code :
leftStream = cv2.VideoCapture(0)
rightStream = cv2.VideoCapture(1)
left = leftStream.read()[1]
right = rightStream.read()[1]
st = cv2.createStitcher(False)
st.estimateTransform([left, right])
st.composePanorama([left, right])
To use stitcher.estimateTransform() and stitcher.composePanorama() you will need to
Download opencv https://github.com/opencv/opencv
navigate to opencv-master/modules/stitching/include/opencv2/stitching.hpp
add CV_WRAP in front of any methods you want to be able to call in Python. In this case those would be estimateTransform and composePanorama
Then to build the python module:
cd ~/opencv
mkdir build
cd build
cmake ../
make
sudo make install
Then move the module to your virtual environment from wherever it was installed to. In my case that was /usr/local/lib/python3.7/site-packages/cv2.
See https://www.pyimagesearch.com/2018/08/17/install-opencv-4-on-macos/ and https://docs.opencv.org/4.1.0/da/d49/tutorial_py_bindings_basics.html and https://docs.opencv.org/4.1.1/da/df6/tutorial_py_table_of_contents_setup.html for more info.
I have the same problem. From what I can see, composePanorama has two overloads.
CV_WRAP Status composePanorama(OutputArray pano);
Status composePanorama(InputArrayOfArrays images, OutputArray pano);
It's the second overload that we need, as the pano is an output parameter, which in Python is given as a return value. Unfortunately, the second overload is not marked by CV_WRAP which would make it available to the Python bindings. So the only solutions I can see are:
Use an alternative stitching implementation
Go through the C++ code of the missing composePanorama implementation and reimplement it yourself in Python
Register an issue on the Open CV Github and wait for an update
Build Open CV yourself from source and mark the function as CV_WRAP (I'm not sure it is actually as simple as that)
Work in C++ instead of Python
Although I'll be very happy if someone else can post an answer showing how to achieve this in Python without going through the complex tasks above.

importing python modules - ImageChops

I'm looking for a good way to analyze image similarity, using python.
I'm NOT looking for a way to establish whether two images are identical. I'm just looking for a way to establish the similarity between two images (e.g., if two images are very similar they could be given a "grade" of 9/10; if they are completely unalike, they'll be given a very low index, such as 2/10).
From some reading that I've done, the module ImageChops has been suggested - however, I haven't been able to find a way to download it.
If anyone knows how to download it, or has a suggestion for other effective solutions, I'd greatly appreciate their advice!
Thanks in advance!
ImageChops is a module from PIL(Pillow). To use the ImageChops function you need to pip install Pillow OR easy_install Pillow OR download the src & extract the src then from CMD CD to the extracted folder & run python setup.py install.
To use the ImageChops you can do this from PIL import ImageChops
you can read the document section
some basic usage example http://effbot.org/imagingbook/imagechops.htm
To check the difference between 2 images:
import Image
from PIL import ImageChops
im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")
diff = ImageChops.difference(im2, im1)
there's a compare images script, but its not a PIL; its on scipy module
You may also check this script here
ImageChops is an module belong to Python Image Library(PIL). Just note that there is no image similarity algorithm (except pixel-wise) built-in in ImageChops, instead, it is a tool you used to write your own algorithm. There is a greate article here:
How can I quantify difference between two images?
The ImageChops module contains a number of arithmetical image operations, called channel operations (“chops”). These can be used for various purposes, including special effects, image compositions, algorithmic painting, and more.
http://effbot.org/imagingbook/imagechops.htm
you can download the Python Image Library here.
http://www.pythonware.com/products/pil/
There are precompiled package for windows user too.
http://www.lfd.uci.edu/~gohlke/pythonlibs/

Python: Manipulating a 16-bit .tiff image in PIL &/or pygame: convert to 8-bit somehow?

Hello all,
I am working on a program which determines the average colony size of yeast from a photograph, and it is working fine with the .bmp images I tested it on. The program uses pygame, and might use PIL later.
However, the camera/software combo we use in my lab will only save 16-bit grayscale tiff's, and pygame does not seem to be able to recognize 16-bit tiff's, only 8-bit. I have been reading up for the last few hours on easy ways around this, but even the Python Imaging Library does not seem to be able to work with 16-bit .tiff's, I've tried and I get "IOError: cannot identify image file".
import Image
img = Image.open("01 WT mm.tif")
My ultimate goal is to have this program be user-friendly and easy to install, so I'm trying to avoid adding additional modules or requiring people to install ImageMagick or something.
Does anyone know a simple workaround to this problem using freeware or pure python? I don't know too much about images: bit-depth manipulation is out of my scope. But I am fairly sure that I don't need all 16 bits, and that probably only around 8 actually have real data anyway. In fact, I once used ImageMagick to try to convert them, and this resulted in an all-white image: I've since read that I should use the command "-auto-levels" because the data does not actually encompass the 16-bit range.
I greatly appreciate your help, and apologize for my lack of knowledge.
P.S.: Does anyone have any tips on how to make my Python program easy for non-programmers to install? Is there a way, for example, to somehow bundle it with Python and pygame so it's only one install? Can this be done for both Windows and Mac? Thank you.
EDIT: I tried to open it in GIMP, and got 3 errors:
1) Incorrect count for field "DateTime" (27, expecting 20); tag trimmed
2) Sorry, can not handle images with 12-bit samples
3) Unsupported layout, no RGBA loader
What does this mean and how do I fit it?
py2exe is the way to go for packaging up your application if you are on a windows system.
Regarding the 16bit tiff issue:
This example http://ubuntuforums.org/showthread.php?t=1483265 shows how to convert for display using PIL.
Now for the unasked portion question: When doing image analysis, you want to maintain the highest dynamic range possible for as long as possible in your image manipulations - you lose less information that way. As you may or may not be aware, PIL provides you with many filters/transforms that would allow you enhance the contrast of an image, even out light levels, or perform edge detection. A future direction you might want to consider is displaying the original image (scaled to 8 bit of course) along side a scaled image that has been processed for edge detection.
Check out http://code.google.com/p/pyimp/wiki/screenshots for some more examples and sample code.
I would look at pylibtiff, which has a pure python tiff reader.
For bundling, your best bet is probably py2exe and py2app.
This is actually a 2 part question:
1) 16 bit image data mangling for Python - I usually use GDAL + Numpy. This might be a bit too much for your requirements, you can use PIL + Numpy instead.
2) Release engineering Python apps can get messy. Depending on how complex your app is you can get away with py2deb, py2app and py2exe. Learning distutils will help too.

Categories