CTやMRI画像のように、xy二次元画像がz枚入っているデータセットを、numpyにいれるやり方。
opencv
とPIL
とscikit-kimage
を使う三種類のやり方がある
32bitグレースケールは、PIL
かskimage
を使う。
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
に入れては三次元配列volume
にappend
している。
確認は、
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])
参考