book - python image manipulation
Python: lectura y escritura de imágenes TIFF de 16 bits, tres canales, color (4)
He encontrado una alternativa adicional a los dos métodos anteriores.
El paquete scikit-image también puede leer archivos TIFF de 16 bits y tres canales utilizando tifffile.py
y FreeImage y especificándolos como el complemento que se utilizará.
Si bien la lectura con tifffile.py
se hace más sencillamente de la manera mostrada por , pensé que mostraría cómo se usa junto con scikit-image en caso de que alguien quiera hacerlo de esta manera.
Para cualquier persona que use Ubuntu, FreeImage está disponible como libfreeimage3
usando apt
.
Si se utiliza la opción de complemento tifffile.py, se debe copiar tifffile.py en el directorio skimage / io / _plugins (f.ex. en Ubuntu, la ruta completa en mi caso era /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)
Escribiendo archivos TIFF:
>>> skimage.io.imsave(''b.tif'', im, plugin=''tifffile'')
>>> skimage.io.imsave(''c.tif'', im, plugin=''freeimage'')
La comprobación de la b.tif
c.tif
b.tif
y c.tif
mediante ImageMagick muestra que cada canal en ambas imágenes es de 16 bits.
¿Alguien tiene un método para importar una imagen TIFF de 16 bits por canal y 3 canales en Python?
Todavía tengo que encontrar un método que conserve la profundidad de 16 bits por canal al tratar con el formato TIFF. Espero que alguna alma útil tenga una solución.
Aquí hay una lista de lo que he intentado hasta ahora sin éxito y los resultados:
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
Hasta ahora, la única solución que he encontrado es convertir la imagen a PNG con ImageMagick. Luego, el bog estándar matplotlib.pyplot.imread
lee el archivo PNG sin ningún problema.
Otro problema que tengo es guardar las matrices numpy como archivos PNG de 16 bits que hasta ahora tampoco han sido sencillos.
La respuesta de funciona.
Mientras tanto, también logré resolver el problema utilizando cv2.imread
en OpenCV.
Por defecto, cv2.imread
convertirá una imagen de 16 bits, tres canales en a.tif
a 8 bits, como se muestra en la pregunta.
cv2.imread
acepta un indicador después del nombre de archivo ( cv2.imread(filename[, flags])
) que especifica el tipo de color de la imagen cargada cf. la documentation :
- > 0 devuelve una imagen en color de 3 canales. Esto resulta en la conversión a 8 bits como se muestra arriba.
- 0 devuelve una imagen en escala de grises. También resulta en la conversión a 8 bits.
- <0 devuelve la imagen como está. Esto devolverá una imagen de 16 bits.
Entonces lo siguiente leerá la imagen sin conversión:
>>> im = cv2.imread(''a.tif'', -1)
>>> im.dtype
dtype(''uint16'')
>>> im.shape
(288, 384, 3)
Tenga en cuenta que OpenCV devuelve los canales R, G y B en orden inverso, por lo que im[:,:,0]
es el canal B, im[:,:,1]
el canal G e im[:,:,2]
es el Canal r
También encontré que cv2.imwrite
puede escribir archivos TIFF de 16 bits, tres canales.
>>> cv2.imwrite(''out.tif'', im)
Comprobando la profundidad de la broca con 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
....
Para mí las alternativas anteriores no funcionaron. He utilizado gdal éxito para leer imágenes de 16 bits de 1 GB.
Puedes abrir una imagen con algo como esto:
from osgeo import gdal
import numpy as np
ds = gdal.Open("name.tif")
channel = np.array(ds.GetRasterBand(1).ReadAsArray())
Hay una lista de gdal que puede usar para escribir los datos.
Tiene una funcionalidad limitada, especialmente cuando se trata de escribir de nuevo en el disco imágenes no RGB, pero el módulo tifffile
Christoph Gohlke lee en tifffile
de 3 canales de 16 bits sin problemas, simplemente lo probé:
>>> import tifffile as tiff
>>> a = tiff.imread(''Untitled-1.tif'')
>>> a.shape
(100L, 100L, 3L)
>>> a.dtype
dtype(''uint16'')
Y Photoshop lee sin quejarse de lo que obtengo al hacer:
>>> tiff.imsave(''new.tiff'', a)