Working with TIFFs (import, export) in Python using numpy

Multi tool use
Working with TIFFs (import, export) in Python using numpy
I need a python routine that can open and import TIFF images into numpy arrays, so I can analyze and modify the contained data and afterwards save them as TIFFs again. (They are basically light intensity maps in greyscale, representing the respective values per pixel)
I tried to find something, but there is no documentation on PIL methods concerning TIFF. I tried to figure it out, but only got bad mode/ file type not supported errors.
What do I need to use here?
6 Answers
6
First, I downloaded a test TIFF image from this page called a_image.tif
. Then I opened with PIL like this:
a_image.tif
>>> from PIL import Image
>>> im = Image.open('a_image.tif')
>>> im.show()
This showed the rainbow image. To convert to a numpy array, it's as simple as:
>>> import numpy
>>> imarray = numpy.array(im)
We can see that the size of the image and the shape of the array match up:
>>> imarray.shape
(44, 330)
>>> im.size
(330, 44)
And the array contains uint8
values:
uint8
>>> imarray
array([[ 0, 1, 2, ..., 244, 245, 246],
[ 0, 1, 2, ..., 244, 245, 246],
[ 0, 1, 2, ..., 244, 245, 246],
...,
[ 0, 1, 2, ..., 244, 245, 246],
[ 0, 1, 2, ..., 244, 245, 246],
[ 0, 1, 2, ..., 244, 245, 246]], dtype=uint8)
Once you're done modifying the array, you can turn it back into a PIL image like this:
>>> Image.fromarray(imarray)
<Image.Image image mode=L size=330x44 at 0x2786518>
Looking at the source of fromarray, it doesn't look like it handles unsigned 16-bit arrays.
– jterrace
Sep 28 '11 at 13:32
I use matplotlib for reading TIFF files:
import matplotlib.pyplot as plt
I = plt.imread(tiff_file)
and I
will be of type ndarray
.
I
ndarray
According to the documentation though it is actually PIL that works behind the scenes when handling TIFFs as matplotlib only reads PNGs natively, but this has been working fine for me.
There's also a plt.imsave
function for saving.
plt.imsave
This is by far the easiest way to work with TIFFs! Tried a dozen ways and all this was the ticket. Upvote for sure!
– zachd1_618
Oct 29 '12 at 6:55
how about the viewing part?
– Monica Heddneck
Jan 26 at 1:18
You could also use GDAL to do this. I realize that it is a geospatial toolkit, but nothing requires you to have a cartographic product.
Link to precompiled GDAL binaries for windows (assuming windows here)
http://www.gisinternals.com/sdk/
To access the array:
from osgeo import gdal
dataset = gdal.Open("path/to/dataset.tiff", gdal.GA_ReadOnly)
for x in range(1, dataset.RasterCount + 1):
band = dataset.GetRasterBand(x)
array = band.ReadAsArray()
is the above code for a single TIF or multipage TIF? I'd like to use gdal to load 16 bit tiff stacks into nparrays.
– user391339
May 29 '15 at 6:37
This should read in either the input data type or move everything to numpy's float64. You can add an
.astype(sometype)
call to the end of the ReadAsArray()
call to cast. Not sure if this makes a copy (just have not tested).– Jzl5325
Jun 2 '15 at 22:09
.astype(sometype)
ReadAsArray()
@Chikinn From Review: stackoverflow.com/review/suggested-edits/17962780
xrange
is no typo, xrange
is the python 2 version of range
. I accepted this edit because python 3 is still being actively improved while python 2 is not.– abccd
Nov 16 '17 at 6:18
xrange
xrange
range
pylibtiff worked better for me than PIL (which doesn't support color images with more than 8 bits per color).
from libtiff import TIFF
tif = TIFF.open('filename.tif', mode='r')
# read an image in the currect TIFF directory as a numpy array
image = tif.read_image()
# read all images in a TIFF file:
for image in tif.iter_images():
pass
tif = TIFF.open('filename.tif', mode='w')
tif.write_image(image)
If you're on python3 you can't pip3 install libtiff
. Instead, manually install with
pip3 install libtiff
git clone git@github.com:pearu/pylibtiff.git
python3 setup.py install
the readme of pylibtiff also mentions tifffile.py, but I haven't tried it.
This is very good. By now, tifffile is included in SciKit skimage.external.tifffile but it can also be imported as a module if you download tifffile.py from Mr. Christoph Gohlke
– Zloy Smiertniy
Jan 15 at 15:30
You can also use pytiff of which I'm the author.
import pytiff
with pytiff.Tiff("filename.tif") as handle:
part = handle[100:200, 200:400]
# multipage tif
with pytiff.Tiff("multipage.tif") as handle:
for page in handle:
part = page[100:200, 200:400]
It's a fairly small module and may not have as many features as other modules, but it supports tiled tiffs and bigtiff, so you can read parts of large images.
In case of image stacks, I find it easier to use scikit-image
to read, and matplotlib
to show or save. I have handled 16-bit TIFF image stacks with the following code.
scikit-image
matplotlib
from skimage import io
import matplotlib.pyplot as plt
# read the image stack
img = io.imread('a_image.tif')
# show the image
plt.imshow(mol,cmap='gray')
plt.axis('off')
# save the image
plt.savefig('output.tif', transparent=True, dpi=300, bbox_inches="tight", pad_inches=0.0)
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
i am having troubles with data types. works fine for some, f.e. if i have numpy.int16 numbers in my array, but for numpy.uint16 image.fromarray yields: "TypeError: Cannot handle this data type"
– Jakob
Sep 28 '11 at 9:42