I try to read a TIFF file with pillow/PIL (7.2.0) in Python (3.8.3), e.g. this image.
The resulting file seems to be corrupted:
from PIL import Image
import numpy as np
myimage = Image.open('moon.tif')
myimage.mode
# 'L'
myimage.format
# 'TIFF'
myimage.size
# (358, 537)
# so far all good, but:
np.array(myimage)
# shows only zeros in the array, likewise
np.array(myimage).sum()
# 0
It doesn't seem to be a problem of the conversion to numpy array only, since if I save it to a jpg (myimage.save('moon.jpg')) the resulting jpg image has the appropriate dimensions but is all black, too.
Where did I do wrong or is it a bug?
I am not an expert in coding but i had same problem and found the TIFF file has 4 layers. R, G ,B and Alpha. When you convert it using PIL it is black.
try to view the image as plt.imshow(myimage[:, :, 0])
you could also remove the Alpha layer by saving the read image ( i used plt.imread('image')) and then saving it as image=image[:,:,3]. Now its a RGB image.
I don't know if i answered your question, but i felt this info might be of help.
I want to see the number of channels for thermal images, RGB images, grayscale images and binary images.
So I write this program:
import cv2
import numpy
img = cv2.imread("B2DBy.jpg")
print('No of Channel is: ' + str(img.ndim))
cv2.imshow("Channel", img)
cv2.waitKey()
But it gives the same three channel results for all types of images? I've read this question but it gives an error:
img = cv2.imread("B2DBy.jpg", CV_LOAD_IMAGE_UNCHANGED)
NameError: name 'CV_LOAD_IMAGE_UNCHANGED' is not defined
So my question is: Is it is the right way to see the number of channels? Or, somehow, I entered three channel images all the time and thus it gives three channel output?
My inputs:
The correct parameter in your cv2.imread should be:
img = cv2.imread('path/to/your/image', cv2.IMREAD_UNCHANGED)
Let's have a look at your images now. I use ImageJ's Show Info... command as well as the following Python code with OpenCV and Pillow:
import cv2
from PIL import Image
img_pil = Image.open('path/to/your/image')
print('Pillow: ', img_pil.mode, img_pil.size)
img = cv2.imread('path/to/your/image', cv2.IMREAD_UNCHANGED)
print('OpenCV: ', img.shape)
First image (depth map)
Pillow: RGB (640, 512)
OpenCV: (512, 640, 3)
ImageJ also says, that's a RGB image. So, most likely, your depth map was just saved as a RGB png.
Second image (dog)
Pillow: RGB (332, 300)
OpenCV: (300, 332, 3)
Interestingly, ImageJ says, that's an grayscale jpg! I assume, OpenCV and Pillow just don't support grayscale jpg, although there seems to be a grayscale jpg format.
Third image (sign)
Pillow: 1 (200, 140)
OpenCV: (140, 200)
Both, Pillow and OpenCV say, that's a grayscale image, which is also supported by ImageJ. Furthermore, Pillow uses mode '1' here, which is reflected by the dithered look of the image.
Fourth image (colours)
Pillow: RGB (500, 333)
OpenCV: (333, 500, 3)
That's just some RGB image; ImageJ also says this.
Conclusion
Yes, most likely, most of your images may just be RGB images. Nevertheless, using cv2.IMREAD_UNCHANGED at least will properly identify grayscale png files. It's questionable, if grayscale jpg files are properly supported.
Hope that helps!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
OpenCV: 4.2.0
Pillow: 7.0.0
----------------------------------------
If image is grayscale you will need to set a flag, tuple returned contains only number of rows and columns.
So it is a good method to check if loaded image is grayscale or color image.
image = cv2.imread('gray.jpg', cv2.IMREAD_GRAYSCALE)
image.shape
If len(img.shape) gives you three, third element gives you number of channels.
I'm not sure if it'll work, but documentation says this:
cv.LoadImage(filename, iscolor=flag) with flags given. There's a flag "<0" that stands for "Return the loaded image as is (with alpha channel)".
I would try this:
img = cv2.imread("B2DBy.jpg",iscolor=<0)
or this
img = cv2.imread("B2DBy.jpg",iscolor=CV_LOAD_IMAGE_ANYDEPTH)
Everytime I open an GeoTIFF image of a orthophoto in python (tried PIL, matplotlib, scipy, openCV) the image screws up. Some corners are beeing cropped , however the image remains its original shape. If I manually convert the tif to for instance a png in Photoshop and load it, it does work correctly. So it seems like PIL has some trouble handling tif files with objects that not fill the entire canvas. Does anyone have a solution for this problem?
Part of original Image:
After opening:
It would have been really nice if you put the link of the figure that you are using (if it's free). I downloaded a sample GeoTIFF image from here, and I used gdal to open it.
The shape of the geotiff.ReadAsArray() is (3, 1024, 2048) so I convert it to (1024, 2048, 3) (RGB) and open it with imshow:
import gdal
gdal.UseExceptions()
import matplotlib.pyplot as plt
import numpy as np
geotiff = gdal.Open('/home/vafanda/Downloads/test.tif')
geotiff_arr= geotiff.ReadAsArray()
print np.shape(geotiff_arr)
geotiff_shifted = np.rollaxis(geotiff_arr,0,3)
print "Dimension converted to: "
print np.shape(geotiff_shifted)
plt.imshow(geotiff_shifted)
plt.show()
result:
I need to show a background to a matplotlib plot using ax.imshow(). The background images that I will be using are GIF-images. Despite having PIL installed, the following code results in an error complaining that the Python Image Library (PIL) is not installed (which it is):
from pylab import imread
im_file = open("test.gif")
im_obj = imread(im_file)
Reading the image using PIL directly works better:
from PIL import Image
import numpy
img = Image.open("test.gif")
img_arr = asarray(img.getdata(), dtype=numpy.uint8)
However, when reshaping the array, the following code does not work:
img_arr = img_arr.reshape(img.size[0], img.size[1], 3) #Note the number 3
The reason is that the actual color information is contained in a color table accessed through img.getcolors() or img.getpalette().
Converting all the images to PNG or another suitable format that results in RGB images when opening them with imread() or Image.open() is not an option. I could convert the images when needed using PIL but I consider that solution ugly. So the question is as follows: Is there a simple and fast (the images are 5000 x 5000 pixels) way to convert the GIF images to RGB (in RAM) so that I can display them using imshow()?
You need to convert the GIF to RGB first:
img = Image.open("test.gif").convert('RGB')
See this question: Get pixel's RGB using PIL
I need a python method to open and import TIFF images into numpy arrays so I can analyze and modify the pixel data and then save them as TIFFs again. (They are basically light intensity maps in greyscale, representing the respective values per pixel)
I couldn't find any documentation on PIL methods concerning TIFF. I tried to figure it out, but only got "bad mode" or "file type not supported" errors.
What do I need to use here?
First, I downloaded a test TIFF image from this page called a_image.tif. Then I opened with PIL like this:
>>> 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:
>>> 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>
I use matplotlib for reading TIFF files:
import matplotlib.pyplot as plt
I = plt.imread(tiff_file)
and I will be of type 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.
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)
Link
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()
PyLibTiff worked better for me than PIL, which as of January 2023 still doesn't support color images with more than 8 bits per color.
from libtiff import TIFF
tif = TIFF.open('filename.tif') # open tiff file in read mode
# read an image in the current 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)
You can install PyLibTiff with
pip3 install numpy libtiff
The readme of PyLibTiff also mentions the tifffile library but I haven't tried it.
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.
from skimage import io
import matplotlib.pyplot as plt
# read the image stack
img = io.imread('a_image.tif')
# show the image
plt.imshow(img,cmap='gray')
plt.axis('off')
# save the image
plt.savefig('output.tif', transparent=True, dpi=300, bbox_inches="tight", pad_inches=0.0)
You can also use pytiff of which I am 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.
There is a nice package called tifffile which makes working with .tif or .tiff files very easy.
Install package with pip
pip install tifffile
Now, to read .tif/.tiff file in numpy array format:
from tifffile import tifffile
image = tifffile.imread('path/to/your/image')
# type(image) = numpy.ndarray
If you want to save a numpy array as a .tif/.tiff file:
tifffile.imwrite('my_image.tif', my_numpy_data, photometric='rgb')
or
tifffile.imsave('my_image.tif', my_numpy_data)
You can read more about this package here.
Using cv2
import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)
if you want save tiff encoding with geoTiff. You can use rasterio package
a simple code:
import rasterio
out = np.random.randint(low=10, high=20, size=(360, 720)).astype('float64')
new_dataset = rasterio.open('test.tiff', 'w', driver='GTiff',
height=out.shape[0], width=out.shape[1],
count=1, dtype=str(out.dtype),
)
new_dataset.write(out, 1)
new_dataset.close()
for more detail about numpy 2 GEOTiff .you can click this: https://gis.stackexchange.com/questions/279953/numpy-array-to-gtiff-using-rasterio-without-source-raster
I recommend using the python bindings to OpenImageIO, it's the standard for dealing with various image formats in the vfx world. I've ovten found it more reliable in reading various compression types compared to PIL.
import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")
Another method of reading tiff files is using tensorflow api
import tensorflow_io as tfio
image = tf.io.read_file(image_path)
tf_image = tfio.experimental.image.decode_tiff(image)
print(tf_image.shape)
Output:
(512, 512, 4)
tensorflow documentation can be found here
For this module to work, a python package called tensorflow-io has to installed.
Athough I couldn't find a way to look at the output tensor (after converting to nd.array), as the output image had 4 channels. I tried to convert using cv2.cvtcolor() with the flag cv2.COLOR_BGRA2BGR after looking at this post but still wasn't able to view the image.
no answers to this question did not work for me. so i found another way to view tif/tiff files:
import rasterio
from matplotlib import pyplot as plt
src = rasterio.open("ch4.tif")
plt.imshow(src.read(1), cmap='gray')
the code above will help you to view the tif files. also check below to be sure:
type(src.read(1)) #see that src.read(1) is a numpy array
src.read(1) #prints the matrix