web-dev-qa-db-ja.com

Python:TIFF 16ビット、3チャンネル、カラーイメージの読み取りと書き込み

Pythonでチャンネルあたり16ビット、3チャンネルのTIFFイメージをインポートする方法はありますか?

TIFF形式を扱うときに、チャネルごとに16ビットの深さを保持する方法をまだ見つけていません。役に立つ魂が解決することを願っています。

ここに、成功せずに今まで試した結果と結果のリストを示します。

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

これまでのところ、私が見つけた唯一の解決策は、ImageMagickで画像をPNGに変換することです。その後、沼地の標準matplotlib.pyplot.imreadは、PNGファイルを問題なく読み取ります。

私が抱えている別の問題は、numpy配列を16ビットPNGファイルとして保存することです。

25
Lars Chr

特にRGB以外のディスクイメージへの書き戻しに関しては機能が制限されていますが、 Christoph Gohlkeのtifffile module 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)
30
Jaime

@ Jaime による答えは機能します。

その間、OpenCVで _cv2.imread_ を使用して問題を解決することもできました。

デフォルトでは、_cv2.imread_は、質問に示すように、_a.tif_の16ビットの3チャネルイメージを8ビットに変換します。

_cv2.imread_は、ファイル名(cv2.imread(filename[, flags]))の後にフラグを受け入れます。このフラグは、読み込まれた画像のカラータイプを指定しますcf. ドキュメント

  1. > 0は、3チャンネルのカラー画像を返します。これにより、上記のように8ビットに変換されます。
  2. はグレースケール画像を返します。また、8ビットに変換されます。
  3. <0は、イメージをそのまま返します。 Thisは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ビットの3チャネル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
  ....
_
22
Lars Chr

上記の2つの方法の追加の代替手段を見つけました。

scikit-image パッケージは、tifffile.pyとFreeImageの両方を使用し、それらを使用するプラグインとして指定して、16ビットの3チャネルTIFFファイルを読み取ることもできます。

tifffile.pyを使用した読み取りは、おそらく @ Jaime で示される方法でより簡単に行われますが、誰かがそれをやりたい場合にscikit-imageとともに使用する方法を示すと思いましたこの方法。

Ubuntuを使用している場合、FreeImageはaptを使用してlibfreeimage3として利用できます。

tifffile.pyプラグインオプションを使用する場合、tifffile.pyをskimage/io/_pluginsディレクトリにコピーする必要があります(f.ex.私の場合のフルパスは/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')

ImageMagickを使用してb.tifc.tifの両方のビット深度を確認すると、両方の画像の各チャンネルが16ビットであることがわかります。

10
Lars Chr

私にとって、以前の選択肢は機能しませんでした。 1 GBの16ビット画像の読み取りに gdal を使用しました。

次のような画像を開くことができます:

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

サポートされているダイバー のリストがあり、データの書き込みに使用できます。

4
G M

OpenImageIOへのpythonバインディングを使用することをお勧めします。これは、vfxドメイン(通常は16/32ビット)のさまざまな画像形式を処理するための標準です。

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