Python и 16 бит Tiff
как преобразовать и сохранить 16-битный одноканальный TIF в Python?
Я могу загрузить 16 и 32-битное изображение без проблем и увидеть, что 32-битное изображение-mode F
и 16-битное изображение-mode I;16S
:
import Image
i32 = Image.open('32.tif')
i16 = Image.open('16.tif')
i32
# <TiffImagePlugin.TiffImageFile image mode=F size=2000x1600 at 0x1098E5518>
i16
# <TiffImagePlugin.TiffImageFile image mode=I;16S size=2000x1600 at 0x1098B6DD0>
но у меня возникли проблемы с работой с 16-битным изображением. Если я хочу сохранить либо как PNG, я не могу сделать это напрямую:
i32.save('foo.png')
# IOError: cannot write mode F as PNG
i16.save('foo.png')
# ValueError: unrecognized mode
если я конвертирую 32-битное изображение, я могу сохранить его:
i32.convert('L').save('foo.png')
но та же команда не работает с 16-битным изображением:
i16.convert('L').save('foo.png')
# ValueError: unrecognized mode
4 ответов
для преобразования без потерь из 16-битных оттенков серого TIFF в PNG используйте PythonMagick:
from PythonMagick import Image
Image('pinei_2002300_1525_modis_ch02.tif').write("foo.png")
наткнулся на этот поток, пытаясь сохранить 16-битные изображения TIFF с PIL / numpy.
версии: python 2.7.1-numpy 1.6.1-PIL 1.1.7
вот быстрый тест, который я написал. uint16 numpy array - > преобразован в string - > преобразован в PIL-образ типа 'I; 16' - > сохранен как 16-битный TIFF.
Открытие изображения в ImageJ показывает правильный горизонтальный градиентный шаблон, а тип изображения - " бит на пиксель: 16 (без подписи)'
import Image
import numpy
data = numpy.zeros((1024,1024),numpy.uint16)
h,w = data.shape
for i in range(h):
data[i,:] = numpy.arange(w)
im = Image.fromstring('I;16',(w,h),data.tostring())
im.save('test_16bit.tif')
edit: начиная с 1.1.7, PIL не поддерживает запись сжатых файлов, но pylibtiff делает (сжатие lzw). Таким образом, код становится (проверено с pylibtiff 0.3):
import Image
import numpy
from libtiff import TIFFimage
data = numpy.zeros((1024,1024),numpy.uint16)
h,w = data.shape
for i in range(w):
data[:,i] = numpy.arange(h)
tiff = TIFFimage(data, description='')
tiff.write_file('test_16bit.tif', compression='lzw')
#flush the file to disk:
del tiff
обратите внимание: тестовый код изменен для создания вертикального градиента в противном случае, сжатие не достигнуто (см. предупреждение: pylibtiff в настоящее время поддерживает чтение и запись изображений, которые хранятся с помощью полос TIFF).
вы, похоже, наткнулись на ошибку PIL или угловой случай, который не был реализован.
вот решение:
i16.mode = 'I'
i16.point(lambda i:i*(1./256)).convert('L').save('foo.png')
преобразование ImageJ TIFF в JPEG с PIL 4.1+
im = numpy.array(Image.open('my.tiff'))
image = Image.fromarray(im / numpy.amax(im) * 255)
image.save('my.jpg')