1
5

More than 1 year has passed since last update.

スタック画像をnumpy配列へいれる

Last updated at Posted at 2020-07-27

CTやMRI画像のように、xy二次元画像がz枚入っているデータセットを、numpyにいれるやり方。
opencvPILscikit-kimageを使う三種類のやり方がある
32bitグレースケールは、PILskimageを使う。

openCV


import cv2
import glob
import numpy as np

volume = []
files = sorted(glob.glob("./data/*.tif"))
for myFile in files:
    image = cv2.imread(myFile)
    volume.append(image)

xy画像は./dataに入っている。
これを一枚ずつimageに入れては三次元配列volumeappendしている。

確認は、

print(np.array(volume).shape)

などでできる。

任意のスライス番号の画像の表示は、例えば、

import matplotlib.pyplot as plt

plt.imshow(volume[300])
plt.show()

PIL (pillow)

openCVの時と、画像の読み込みが違うだけ。
RGBの順番が変わらないので、カラー画像のときはおすすめ。

from PIL import Image
import glob
import numpy as np
import matplotlib.pyplot as plt

volume = []
files = sorted(glob.glob("./data/*.tif"))
for myFile in files:
    image = Image.open(myFile)
    image = np.asarray(image, dtype=np.uint8)
    volume.append(image)

plt.imshow(volume[300],interpolation = 'none')
plt.show()

上の例では、300枚目のスライスを表示する。
なお、np.uint8で型指定している。(RGBなど)

32bitグレースケールの場合は、

from PIL import Image
import glob
import numpy as np

Nz=0
volume = []
files = sorted(glob.glob("./data/*.tif"))
for z in files:
    Nz = Nz + 1
    image = Image.open(z)
    image = np.asarray(image, dtype=np.float32)
    volume.append(image)

Ny = image.shape[0]
Nx = image.shape[1]
volume = np.ravel(volume).reshape(Nz,Ny,Nx)

numpyの配列に直接書き込むと遅くなる模様なので、
Python標準のlist配列にいったん変換してappendするべし。
https://qiita.com/discexOmnes/items/f84b54201aced12fec80

scikit-image

今のところ一番気に入っている。
速度はPILとかわらない。
ここでも先程と同じく、直接numpyで書き込まないのがミソ。

from skimage.io import imread
import glob
import numpy as np

files = sorted(glob.glob("./data/*.tif"))
volume = imread(files[0])
Nz = len(files)
Ny,Nx = volume.shape
volume = volume.tolist()
for z in files[1:]:
    volume.extend(imread(z))

volume = np.array(volume,dtype='float32').reshape(Nz,Ny,Nx)

画像表示は、300枚目の画像を輝度0~100で表示するには、、、

from skimage.io import imshow,show

imshow(volume[300],cmap='gray',vmin=0,vmax=100)
show()

このあたりは、関数化してしまうのが便利。
ただし、ファイルが一枚しかないスタック画像にも対応させるためにも、
Nz>=1としておくのが無難。

def loadvolume(folder):
    files = sorted(glob.glob(folder + "/*.tif"))
    PV = imread(files[0])
    Nz = len(files)
    Ny,Nx = PV.shape
    PV = PV.tolist()
    if (Nz>=1) :
        for z in files[1:]:
            PV.extend(imread(z))
####
    PV = np.array(PV,dtype='float32').reshape(Nz,Ny,Nx)
    return(PV,Nx,Ny,Nz)

もちろん利用方法は、

PV,Nx,Ny,Nz = loadvolume('folderpath')

です。

Color画像の読み込み(scikit-image)

以下のように、カラーの次元に注意する。

def ReadVolumeColor(dirname):
    files = sorted(glob.glob(dirname+'/*.tif'))
    volume = imread(files[0])
    Nz = len(files)
    Ny,Nx,_ = volume.shape
    volume = volume.tolist()
    for z in files[1:]:
        volume.extend(imread(z))
    volume = np.array(volume,dtype='uint8').reshape(Nz,Ny,Nx,3)
    return(volume)

ファイルへの書き出し

PIL

for z in range(Nz):
    Image.fromarray(volume[z]).save(str("./data2") + "/" + str(z).zfill(4) + ".tif")

scikit-image

from skimage.io import imsave

for z in range(Nz):
    imsave('path/'+str(z).zfill(4)+'.tif',volume[z])

参考

1
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5