Подтвердить что ты не робот

Python: чтение и запись TIFF 16-битных, трехканальных, цветных изображений

Есть ли у кого-нибудь метод импорта 16-битного канала, трехканального TIFF-изображения в Python?

Мне еще предстоит найти метод, который сохранит 16-битную глубину на канал при работе с форматом TIFF. Я надеюсь, что у некоторой полезной души будет решение.

Вот список того, что я пробовал до сих пор без успеха и результатов:

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

Пока единственным решением, которое я нашел, является преобразование изображения в PNG с ImageMagick. Тогда стандарт болота matplotlib.pyplot.imread без проблем читает PNG файл.

Еще одна проблема, которую я имею, заключается в том, чтобы сохранить любые массивы numpy в виде 16-битных PNG файлов, которые до сих пор не были простыми.

4b9b3361

Ответ 1

Он имеет ограниченную функциональность, особенно когда речь заходит о записи на диски без RGB-изображений, но модуль Christoph Gohlke tifffile читается в 3 канальные 16-битные TIFF без проблем, я только что протестировал его:

>>> import tifffile as tiff
>>> a = tiff.imread('Untitled-1.tif')
>>> a.shape
(100L, 100L, 3L)
>>> a.dtype
dtype('uint16')

И Photoshop читает, не жалуясь на то, что я получаю:

>>> tiff.imsave('new.tiff', a)

Ответ 2

Ответ @Jaime работает.

В то же время мне удалось решить проблему, используя cv2.imread в OpenCV.

По умолчанию cv2.imread преобразует 16-битное трехканальное изображение в a.tif в 8 бит, как показано в вопросе.

cv2.imread принимает флаг после имени файла (cv2.imread(filename[, flags])), который указывает тип цвета загруженного изображения cf. документация:

  • 0 возвращает трехканальное цветное изображение. Это приводит к преобразованию в 8 бит, как показано выше.
  • 0 возвращает изображение в оттенках серого. Также приводит к преобразованию в 8 бит.
  • < 0 возвращает изображение как есть. Этот будет возвращать 16-битное изображение.

Итак, следующее изображение будет читаться без преобразования:

>>> im = cv2.imread('a.tif', -1)
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)

Обратите внимание, что OpenCV возвращает каналы R, G и B в обратном порядке, поэтому im[:,:,0] является каналом B, im[:,:,1] канал G и im[:,:,2] является каналом R.

Я также обнаружил, что cv2.imwrite может писать 16-битные трехканальные файлы TIFF.

>>> cv2.imwrite('out.tif', im)

Проверка глубины бит с помощью 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
  ....

Ответ 3

Я нашел дополнительную альтернативу двум описанным выше методам.

Пакет scikit-image также может читать 16-битные трехканальные файлы TIFF, используя как tifffile.py, так и FreeImage, и указывая их как плагин для использования.

В то время как чтение с использованием tifffile.py возможно выполняется более просто, как показано @Jaime, я думал, что покажу, как он используется вместе с scikit-image в случае, если кто-то захочет сделать это таким образом.

Для тех, кто использует Ubuntu, FreeImage доступен как libfreeimage3 с помощью apt.

Если используется опция плагина tifffile.py, tifffile.py необходимо скопировать в каталог skimage/io/_plugins (f.ex. на Ubuntu полный путь в моем случае был /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)

Запись файлов TIFF:

>>> skimage.io.imsave('b.tif', im, plugin='tifffile')
>>> skimage.io.imsave('c.tif', im, plugin='freeimage')

Проверка битдапа как b.tif, так и c.tif с помощью ImageMagick показывает, что каждый канал на обоих изображениях 16 бит.

Ответ 4

Для меня предыдущие альтернативы не работали. Я успешно использовал gdal для чтения 16-битных изображений объемом 1 ГБ.

Вы можете открыть изображение примерно так:

from osgeo import gdal
import numpy as np
ds = gdal.Open("name.tif")
channel = np.array(ds.GetRasterBand(1).ReadAsArray())

Существует список поддерживаемого дайвера, который вы можете использовать для записи данных.

Ответ 5

Я рекомендую использовать привязки Python к OpenImageIO, это стандарт для работы с различными форматами изображений в домене vfx (которые обычно 16/32-битные).

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")