マイブログ リスト

医療言語処理講座

2019年2月5日火曜日

Pyゼミ1.04 DICOMのタグ情報(ImagePosition)で画像ファイルをソートする

DICOM画像のタグ情報(Image Position)を使ってファイルをソートしてみよう


keyword : DICOM, Tag, Image Position, Sort

Image Position(Patient)とはDICOMのタグ情報(0020,0032)に格納された画像位置(x,yとz)を表す値です。
xとyは対象のCT画像の上下左右の位置を示してて,患者の上下,左右の位置に対応してます。
zは体軸方向の位置を示しています。
この値を基にしてソートすることで頭部から足部方向に順に画像を表示することができます。


Image Positionでファイルをソートするプログラム


下のソートするプログラムを入力して,実行してみよう。
listdirメソッドで指定したディレクトリの中のDICOM画像のファイル名をリストに取得した順では正しく並びません。

このプログラムでは画像位置でソートするsortFileByImagePosition関数を作成しました。
この関数は指定したディレクトリ内のDICOMファイルを画像位置に従ってソートしてファイル名を返します。


dicomSort.py

import os, sys
import pydicom

def sortFileByImagePosition(dirname):
    files = os.listdir(dirname)
  
    filedic = {}        # ファイル名とImagePositionを代入する辞書
    filelist = []       # ソートされた順でファイル名を代入するリスト
  
    # DICOM画像を読み込んでファイル名とImage Positionの辞書を作成
    for i, filename in enumerate(files):
        ds = pydicom.read_file(dirname + filename)
        filedic[filename] = ds.ImagePositionPatient[2]  # 辞書に登録
        print("MakeDic>>",i, filename, filedic[filename])
  
    print("-" * 50)
    # Sort( Image Positionを降順ソートのときは -x[1], 昇順のときは x[1] )
    fileSortedByImgpos = sorted(filedic.items(), key=lambda x: -x[1])
    for i, fname_imgPos in enumerate(fileSortedByImgpos):
        filelist.append(str(fname_imgPos[0]))
        print("Sorted >> ",i ,str(fname_imgPos[0]) + ": " + str(fname_imgPos[1]))
      
    return filelist
      
if __name__ == '__main__':
    dirname = "../dcmdir1/"

    #File SimpleDisplay
    files = os.listdir( dirname )
    for i, filename in enumerate(files):
        ds = pydicom.read_file(dirname + filename)
        print("Originl>>",i, filename, ds.ImagePositionPatient)
    print("=" * 50)
          
    sortedfiles = sortFileByImagePosition(dirname)
  
    print("=" * 50)
    for i, filename in enumerate(sortedfiles):
        print("RESULT >>",i, filename)




プログラムを実行する


$ python␣dicomSort.py⏎


実行結果は以下のようになります。
最初の'Original>>'ではファイル名と画像位置x,y,zを読み込んだ順番に表示しています。
ファイル名の表示順序はでたらめです。

次に,'MakeDic>>'はファイル名と画像位置zの辞書を作成しているいます。

Sorted>>"ではファイル名が画像位置zでソートされ,頭部(Brain),胸部(Chest),腹部(Abdomen)の順に並んでいます。
画像位置が小さな負の値から大きな負の値へ降順に並んでいます。


Originl>> 0 Chest01 ['-199.218', '-210.9375', '-789.0000']
Originl>> 1 Abdomen02 ['-199.218', '-210.9375', '-954.0000']
Originl>> 2 Brain01 ['-120.000', '-119.7761', '-462.6741']
Originl>> 3 Abdomen01 ['-199.218', '-210.9375', '-949.0000']
Originl>> 4 Chest03 ['-199.218', '-210.9375', '-914.0000']
Originl>> 5 Brain02 ['-120.000', '-119.7761', '-508.6741']
Originl>> 6 Chest02 ['-199.218', '-210.9375', '-809.0000']
Originl>> 7 Abdomen03 ['-199.218', '-210.9375', '-1024.000']
==================================================
MakeDic>> 0 Chest01 -789.0000
MakeDic>> 1 Abdomen02 -954.0000
MakeDic>> 2 Brain01 -462.6741
MakeDic>> 3 Abdomen01 -949.0000
MakeDic>> 4 Chest03 -914.0000
MakeDic>> 5 Brain02 -508.6741
MakeDic>> 6 Chest02 -809.0000
MakeDic>> 7 Abdomen03 -1024.000
--------------------------------------------------
Sorted >>  0 Brain01: -462.6741
Sorted >>  1 Brain02: -508.6741
Sorted >>  2 Chest01: -789.0000
Sorted >>  3 Chest02: -809.0000
Sorted >>  4 Chest03: -914.0000
Sorted >>  5 Abdomen01: -949.0000
Sorted >>  6 Abdomen02: -954.0000
Sorted >>  7 Abdomen03: -1024.000
==================================================
RESULT >> 0 Brain01
RESULT >> 1 Brain02
RESULT >> 2 Chest01
RESULT >> 3 Chest02
RESULT >> 4 Chest03
RESULT >> 5 Abdomen01
RESULT >> 6 Abdomen02
RESULT >> 7 Abdomen03




プログラム解説


mainでは,処理対象のディレクトリ名を変数dirnameに代入します。

はじめに指定したディレクトリの中のファイル名をlistdirメソッドで取得し,for文により1画像ずつ読み込んで,ファイル名と画像位置を表示します。

今回作成したsortFileByImagePosition関数にディレクトリ名を渡して,画像位置でソートしたファイル名をsortedfilesに代入します。
そして,ソートしたDICOMファイルを表示します。

sortFileByImagePosition関数

listdirメソッドを使ってディレクトリ内のDICOMファイルを取得しリストfilesに格納します。

次にファイル名と画像位置zの辞書filedicとソートしたファイル名を格納するリストfilelistを初期化します。

for文を使ってfilesの各DICOMファイル名を順に取り出して読み込み,画像位置(Image Position Patient)を抽出して辞書filedicに格納します。
     filedic[ filename ] = ds.ImagePositionPatient[ 2 ] 
このときfilenameはキーとなり,ds.ImagePositionPatient[ 2 ] はその値として辞書に登録します。

ds.ImagePositionPatientは3つの値x,y,zをリストで返します。
     ds.ImagePositionPatient[ 0 ] # x の値
     ds.ImagePositionPatient[ 1 ] # y の値
     ds.ImagePositionPatient[ 2 ] # z の値
zの値を利用するには2を指定します。

次にsortedメソッドを使って,ソートした結果を得ます。
今回,画像位置である辞書の値でソートを行うので,引数を以下のように記述します。
     fileSortedByImgpos = sorted( filedic.items(), key=lambda x: -x[1] )

もし,ファイル名である辞書のキーでソートを行う場合は次のように指定します。
     key=lambda x: -x[0]

また,画像位置で昇順にソートする場合は次のように指定します。
昇順はプラスxで指定します。
     key=lambda x:  x[1]

引数で与えた辞書形式のデータはsortedメソッドによりリスト型で返ります。
     辞書 filename:ImagePosition → リスト [filename, ImagePosition]
したがって,ソートされたファイル名は次のように取り出します。
     fname_imgPos[0]

ソートされたファイル名をリストfilelistに追加(Append)して返します。


おわりに


DICOM画像を順に処理したいような場合,画像位置でソートして連続した一連のデータとして扱うことができます。また,画像表示も画像位置でソートされていれば観察もしやすくなります。
今回のsortFileByImagePosition関数は2.02のDICOM画像のページングで利用します。

0 件のコメント:

コメントを投稿