Python: lire et écrire TIFF 16 bits, trois canaux, images couleur
Je n'ai pas encore trouvé de méthode qui préserve la profondeur de 16 bits par canal en traitant avec le format TIFF. J'espère qu'une âme utile trouvera une solution.
<!-Voici une liste de ce que j'ai essayé jusqu'à présent sans succès et les résultats:import numpy as np
import PIL.Image as Image
import libtiff
import cv2
im = Image.open('a.tif')
# IOError: cannot identify image file
tif = libtiff.TIFF.open('a.tif')
im = tif.read_image()
# im only contains one of the three channels. im.dtype is uint16 as desired.
im = []
for i in tif.iter_images():
# still only returns one channel
im = np.array(cv2.imread('a.tif'))
# im.dtype is uint8 and not uint16 as desired.
# specifying dtype as uint16 does not correct this
<!-Jusqu'à présent, la seule solution que j'ai trouvée est de convertir L'image en PNG avec ImageMagick. Alors la norme des tourbières matplotlib.pyplot.imread
lit le fichier PNG sans aucun problème.
un autre problème que j'ai est d'enregistrer n'importe quels tableaux vides en tant que fichiers PNG 16 bits qui jusqu'à présent n'a pas été simple non plus.
4 réponses
il a des fonctionnalités limitées, surtout quand il s'agit d'écrire à nouveau sur le disque images non RGB, mais Christoph Gohlke tifffile
module lit-3 canaux 16 bits Tiff avec pas de problèmes, je l'ai juste testé:
>>> import tifffile as tiff
>>> a = tiff.imread('Untitled-1.tif')
>>> a.shape
(100L, 100L, 3L)
>>> a.dtype
dtype('uint16')
et Photoshop lit sans se plaindre ce que j'obtiens de faire:
>>> tiff.imsave('new.tiff', a)
La réponse par @Jaime fonctionne.
en même temps j'ai réussi à résoudre le problème en utilisant cv2.imread
in OpenCV.
Par défaut cv2.imread
convertira une image 16 bits, trois canaux en a.tif
à 8 bits, comme indiqué dans la question.
cv2.imread
accepte un drapeau après le nom du fichier ( cv2.imread(filename[, flags])
) qui spécifie le type de couleur de l'image chargée cf. le documentation:
- > 0 renvoie une image couleur à 3 canaux. Il en résulte une conversion en 8 bits comme indiqué ci-dessus.
- 0 renvoie une image à l'échelle de gris. Il en résulte également une conversion en 8 bits.
- <0 renvoie l'image telle quelle. renvoie une image 16 bits.
ainsi ce qui suit Lira l'image sans conversion:
>>> im = cv2.imread('a.tif', -1)
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)
notez Qu'OpenCV renvoie les canaux R, G et B dans l'ordre inverse donc im[:,:,0]
est le canal B, im[:,:,1]
le G canal et im[:,:,2]
est la chaîne R.
j'ai aussi trouvé que cv2.imwrite
peut écrire 16 bits,trois fichiers TIFF.
>>> cv2.imwrite('out.tif', im)
vérification de la profondeur de bits avec ImageMagick:
$ identify -verbose out.tif
Format: TIFF (Tagged Image File Format)
Class: DirectClass
Geometry: 384x288+0+0
Resolution: 72x72
Print size: 5.33333x4
Units: PixelsPerInch
Type: TrueColor
Base type: TrueColor
Endianess: MSB
Colorspace: sRGB
Depth: 16-bit
Channel depth:
red: 16-bit
green: 16-bit
blue: 16-bit
....
j'ai trouvé une alternative supplémentaire aux deux méthodes ci-dessus.
scikit-image paquet peut aussi lire 16 bits, trois fichiers TIFF utilisant les deux tifffile.py
et FreeImage et les spécifier comme le plugin à utiliser.
en lisant en utilisant tifffile.py
est probablement fait plus simplement de la manière montrée par @Jaime, j'ai pensé que je voudrais montrer comment il est utilisé avec scikit-image au cas où quelqu'un veut le faire dans ce manière.
Pour toute personne utilisant Ubuntu, FreeImage est disponible sous la forme libfreeimage3
en utilisant apt
.
Si le tifffile.py
l'option plugin est utilisée tifffile.py doit être copié dans le répertoire skimage/io/_plugins (F. ex. sur Ubuntu le chemin complet dans mon cas était /usr/local/lib/python2.7/dist-packages/skimage/io/_plugins/
).
>>> import skimage.io
>>> im = skimage.io.imread('a.tif', plugin='tifffile')
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)
>>> im = skimage.io.imread('a.tif', plugin='freeimage')
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)
l'Écriture de fichiers TIFF:
>>> skimage.io.imsave('b.tif', im, plugin='tifffile')
>>> skimage.io.imsave('c.tif', im, plugin='freeimage')
vérification du bitdepth des deux b.tif
et c.tif
utiliser ImageMagick montre que chaque canal dans les deux images est de 16 bits.
pour moi les alternatives précédentes n'ont pas fonctionné. J'ai utilisé gdal succès pour la lecture d'images 16bit de 1 Go.
Vous pouvez ouvrir une image avec quelque chose comme ceci:
from osgeo import gdal
import numpy as np
ds = gdal.Open("name.tif")
channel = np.array(ds.GetRasterBand(1).ReadAsArray())
Il y a une liste de prise en charge plongeur que vous pouvez utiliser pour écrire les données.