Search code examples
pythonimagenumpymatplotlibtiff

How to read a 32-bit integer image using matplotlib?


I need to read a single-channel 32-bit integer TIFF image from disk using Python 2 to perform some image analysis. I tried image.imread from matplotlib but I was unable to get the code to work because data were read as 4-channel 8-bit integer image:

>>> import numpy as np
>>> import matplotlib.image as mpimg
>>> img = mpimg.imread('my_image.tif')
>>> img.shape
(52, 80, 4)
>>> img[0:2, 0:2]
array([[[255, 255, 255, 255],
        [255, 255, 255, 255]],

       [[255, 255, 255, 255],
        [255, 255, 255, 255]]], dtype=uint8)

QUESTION: Is it possible to read a single-channel 32-bit integer image using matplotlib?

I'm aware there are alternative ways to read such an image in Python, for example using Image.open from PIL:

>>> from PIL import Image
>>> img = np.asarray(Image.open('my_image.tif'))
>>> img.dtype
dtype('int32')
>>> img.shape
(52, 80)
>>> img[0:2, 0:2]
array([[8745, 8917],
       [8918, 9479]])

Another possibility would be using io.imread from scikit-learn:

>>> from skimage import io
>>> img = io.imread('my_image.tif')

Yet another approach is to utilize the imread function from OpenCV. But in this case data have to be casted to 32-bit integer:

>>> import cv2
>>> img = cv2.imread('my_image.tif', -1)
>>> img[0:2, 0:2]
array([[  1.22543551e-41,   1.24953784e-41],
       [  1.24967797e-41,   1.32829081e-41]], dtype=float32)
>>> img.dtype = np.int32
>>> img[0:2, 0:2]
array([[8745, 8917],
       [8918, 9479]])

Solution

  • According to this tutorial, there's no way to read a 32-bit integer image using matplotlib:

    Matplotlib plotting can handle float32 and uint8, but image reading/writing for any format other than PNG is limited to uint8 data.

    For reference, I found out one more workaround based on ndimage.imread from SciPy:

    from scipy import ndimage
    img = ndimage.imread('my_image.tif', mode='I')
    

    The approach based on tifffile (suggested by @Warren Weckesser) also works fine:

    from tifffile import TiffFile
    
    with TiffFile('my_image.tif') as tif:
        img = tif.asarray()