📘

(Python) OpenCV ver4.0以降でtifイメージを読み込み・書き出す方法

2024/06/29に公開

はじめに

画像処理を行うためのPython APIとしてOpenCV(ver.4.0以降)を使用している中で, tif画像の読み出し/書き出しのトラブルシューティングに関するネット情報が少ないと思いました. そこで, 備忘録も兼ねてスタックイメージの読み込み/書き出しの方針について残そうと思います.

実行環境

category ソフトウェア==version
OS Windows 10 Home
PC Dell Latitude
language Python==3.9.1
API opencv-python==.4.8.0

tifイメージ(フレーム数=1)を読み出し,1枚を書き出す

前提:予め任意のフォルダ'inputs'と'output'を作成しておきます. そして, フォルダ中に1つのtifイメージファイルを保存しておきます.
処理:イメージの読み取り, 表示、出力を行うサンプルコードは以下のようになりました.
(デモとして, ImageJ[1]に収録されているsample examplesの1つである『flybrain.tif』をお借りしました.)

Single_In_Single_Out
import cv2 as cv

#path for the data
path ='inputs/FlyBrain.tif'
#read the color_image(-1: Unchanged, 0:Grayscaled)
img = cv.imread(path, -1)

#get data_character
#print(img.shape) >>(512, 512, 3)
#print(img.dtype) >>(uint8, uint16, or float32)
#print(len(img))  >>(512)

#show the image
cv.imshow('FlyBrain (viewer)', img)
#when key == 0 is pushed, show_window is closed
cv.waitKey(0)
cv.destroyAllWindows()

#write the image
cv.imwrite('outputs/FlyBrain_out01.jpg', img)
print('The image was saved !')

保存されたイメージを見てみると以下のようになりました(tifの代わりにjpgを添付します)

  • tifイメージデータ形状:(256,256,3), tifイメージデータ型:uint8

imread関数, imwrite関数では,引数として1枚のイメージファイルを求められます. そのため, これらの関数だけでは, 2枚目, 5枚目など任意のイメージを選択的に書き出したり, 任意なフレーム枚数だけ書き出すといった処理は難しいと思われます.

tifスタックイメージを読み出し, 個別のフレームイメージを書き出す

方針:OpenCVの公式ドキュメントによればスタックイメ―ジの読み込みには"cv2.imreadmulti()"関数が用意されているらしいので使ってみます.
前提:outputs内にサブフォルダ'separated_img'を作成しておきます.
処理:tifスタックイメージを読み込みグレースケール変換した後に一枚ずつ別個に保存するサンプルコードは以下のようになります.

Multi_In_Multi_Out
import cv2 as cv

#path for the data
path ='inputs/flybrain.tif'
#read the colored-stack_image
Multi_img = []
ret, Multi_img = cv.imreadmulti(mats=Multi_img, filename=path, flags=cv.IMREAD_UNCHANGED)

#convert from tuple to list
Multi_img = list(Multi_img)

cv.imshow('flyBrain (Viewer)', Multi_img[29])
cv.waitKey(0)
cv.destroyAllWindows()

#loop for grayscale process
for i in range(len(Multi_img)):
    Multi_img[i] = cv.cvtColor(Multi_img[i], cv.COLOR_BGR2GRAY)
    #write the single image files separately
    cv.imwrite('outputs/separated_img/flybrain_No.'+str(i)+'.tif', Multi_img[i])

print('all separated images were saved')
print('separated frame counts: ', len(Multi_img))

tifスタックイメージを読み出し, 単一のスタックイメージを書き出す

方針:スタックイメージの書き出しには関数"imwritemulti()"が用意されているらしいので使ってみます.
前提:outputs内にサブフォルダ'stacked_img'作成します.
処理:個々のフレームイメージをグレースケール変換した後に, 単一のスタックイメージとして保存するサンプルコードは以下のようになります.

Multi_In_Single_Out
import cv2 as cv

#path for the data
path ='inputs/flybrain.tif'
#read the color_image
Multi_img = []
ret, Multi_img = cv.imreadmulti(mats=Multi_img, filename=path, flags=cv.IMREAD_UNCHANGED)

#convert from tuple to list
Multi_img = list(Multi_img)

cv.imshow('flyBrain (Viewer)', Multi_img[29])
cv.waitKey(0)
cv.destroyAllWindows()

# It's new from below
stack_img = []
for i in range(len(Multi_img)):
    Multi_img[i] = cv.cvtColor(Multi_img[i], cv.COLOR_BGR2GRAY)
    stack_img.append(Multi_img[i])

print('stacked frame counts: ', len(stack_img))
#write the multi-stacked image file
cv.imwritemulti('outputs/stacked_img/stacked_flybrain.tif', stack_img)
print('all separated images were saved')

保存したtifスタックイメージをgif形式で書き出した結果は以下の通りになりました.
(わかりやすくするために, フレームラベル文字のみ後付けしました.)

最後に

要約すると, スタックイメージの読み込み/書き出しは以下のような関数ペアで達成できます.

目的 使用できる関数ペア
1枚のイメージを読み込み, 単一イメージを書き出す cv2.imread(), cv2.imwrite()
n枚のイメージを読み込み, イメージを別個に書き出す cv2.imreadmulti(), cv2.imwrite()
n枚のイメージを読み込み, 単一イメージを書き出す cv2.imreadmulti(),cv2.imwritemulti()

本記事で取り上げたグレースケール変換処理の部分は, 用途に応じて他の処理(二値化・膨張/収縮・アフィン変換)や物体検出のアルゴリズムなどに置き換えることで, tifスタックイメージを適切な形式で書き出すことができると考えられます. OpenCVのバージョンが更新される度に, 関数の戻り値や引数の指定方法が変更になるかもしれないので, 環境で使用しているOpenCV APIのバージョンに対応した公式ドキュメントを参照することをお勧めいたします.

参考・引用元

[1] Image J (NIH)

Discussion