【初心者向け】基礎&実践プログラミング

初心者がつまづきやすいところ、最短で実力が身につく方法をお伝えします。

【Python】画像の類似度の計算(Dice係数)

f:id:AIProgrammer:20200610184649p:plain

目的

  • NIFTI形式の画像からPythonを使ってDice係数を計算する。

準備

必要となるパッケージは以下の通りです。必要に応じてインストールしてください。

pip3 install nibabel
pip3 install numpy
pip3 install glob
pip3 install pandas

フォルダ構造

フォルダ構造は以下の通りです。image1とimage2に比較したい画像をいれてください。比較したい画像同士が比較できるようにimage1とimage2の並び順は対応させておいてください。calc_dice.pyはDice係数を計算するためのPythonスクリプトです。

.
├── calc_dice.py
├── image1
│   ├── sub001.nii.gz
│   ├── sub002.nii.gz
│   └── sub003.nii.gz
└── image2
    ├── sub001.nii.gz
    ├── sub002.nii.gz
    └── sub003.nii.gz

画像類似度の計算(Dice係数)

以下のコードをimage1フォルダとimage2フォルダと同じ階層にcalc_dice.pyとして保存します。

calc_dice.py

import nibabel as nib
import numpy as np
import glob
import pandas as pd


def load(file):
    img = nib.load(file)
    data = img.get_fdata().astype("float16")
    data_reshape = data.reshape(-1)
    return data_reshape

def dice(x, y):
    """
    Dice's coefficient
    Sørensen-Dice coefficient
    https://en.wikipedia.org/wiki/Dice%27s_coefficient
    """
    return 2 * np.sum(((x==y)&(x==1)&(y==1)) / float(sum(map(len, (x[x==1], y[y==1])))))

filelist1 = sorted(glob.glob("image1/*.nii.gz"))
filelist2 = sorted(glob.glob("image2/*.nii.gz"))

filename1, filename2, dice_index = [], [], []

for i in range(len(filelist1)):
    img1 = load(filelist1[i])
    img2 = load(filelist2[i])
    # img1[img1>0]=1
    # img1[img1<0]=0
    # img2[img2>0]=1
    # img2[img2<0]=0
    di = dice(img1,img2)
    filename1.append(filelist1[i])
    filename2.append(filelist2[i])
    dice_index.append(di)
    print("{} vs {}, DI:{:.3f}".format(filelist1[i],filelist2[i],di))

df = pd.DataFrame({"File1":filename1, "File2":filename2, "Dice_Index":dice_index})
df.to_csv("result_diceindex.csv",index=False)

Dice計算を実行するには、以下のコマンドを実行します。

$ python3 calc_dice.py 
image1/sub001.nii.gz vs image2/sub001.nii.gz, DI:0.765
image1/sub002.nii.gz vs image2/sub002.nii.gz, DI:0.956
image1/sub003.nii.gz vs image2/sub003.nii.gz, DI:0.465

calc_dice.pyを実行すると結果を「result_diceindex.csv」にまとめてくれます。

result_diceindex.csv

File1 File2 Dice_Index
image1/sub001.nii.gz image2/sub001.nii.gz 0.765
image1/sub002.nii.gz image2/sub002.nii.gz 0.956
image1/sub003.nii.gz image2/sub003.nii.gz 0.465

FSLでやりたい場合

脳画像解析をしている人ならFSLで完結したい人もいると思います。
その場合は、以下のソースコードを保存して、実行する際に対象の2つの画像を引数として渡すことでDice係数を計算することができます。
私の戦友からに教えてもらいました!

fsl_dicecalc.sh

image1=$1
image2=$2
fslmaths ${image1} -mul ${image2} -bin image_and
vox_and=($(fslstats image_and -V))
vox_image1=($(fslstats ${image1} -V))
vox_image2=($(fslstats ${image2} -V))
printf '%.3f\n' "$(echo "scale=4; 2 * ${vox_and[0]} / (${vox_image1[0]} + ${vox_image2[0]})" | bc)"
\rm -f image_and.nii*

上記のコードを「fsl_dicecalc.sh」として保存し、以下のコマンドを実行。

$ bash fsl_dicecalc.sh <image1> <image2>



頑張れ!喝!!の代わりにB!ブックマークを押していただけるとただただうれしいです(^^)! ↓