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

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

AscendingやDescendingを加味したDICOMからPNG変換

f:id:AIProgrammer:20200508145557p:plain

目的

  • DICOMからPNGに変換

  • ただし、被験者によっては撮像の順番(Ascending, Descending)がばらばら

  • PNGのファイル名は、Decendingを基準として番号をふる

準備

フォルダ構造はこのような感じ。 2000人分のフォルダがあり、それぞれの中に複数の画像が入っている。

$ tree
.
├── 0001
│   ├── instance_0.dcm
│   ├── instance_1.dcm
│   ├──instance_2.dcm
           ・
           ・
           ・
└──      instance_19.dcm

           ・
           ・
           ・
├── 0002
           ・
           ・
           ・
└── 2000

①ヘッダー情報の収集

【Linux】DICOMから被験者の情報を一括自動収集で作成した、DICOMからヘッダー情報を収集するコードを参考にする。

今回は、画像の断面(z-axis)の位置も重要であるため、各断面の位置(SliceLocation)も取得する。 各被験者の1枚目の断面位置を数値で比較すれば、AscendingかDescendingかわかるため、最初に撮像した画像の断面位置のみを各被験者ごとに格納する。

function get_dcminfo (){
echo $(find $1 -type f  |sort -n | head -n 1 | xargs -i dcmdump {} \
| grep $2 \
| cut -d [ -f2| cut -d ] -f1)","
}

for k in  $(\ls |sort -n);do
# 被験者フォルダ名
echo $k"," >> tmp1
# 名前(PatientName)
get_dcminfo $k "PatientName" >> tmp2
# ID(PatientID)
get_dcminfo $k "PatientID" >> tmp3
# 生年月日(PatientBirthDate)
get_dcminfo $k "PatientBirthDate" >> tmp4
# 性別(PatientSex)
get_dcminfo $k "PatientSex" >> tmp5
# 年齢(PatientAge)
get_dcminfo $k "PatientAge" >> tmp6
# 検査日(PerformedProcedureStepStartDate)
get_dcminfo $k "StudyDate" >> tmp7
# z position(SliceLocation)
get_dcminfo $k "SliceLocation" >> tmp8
# targeted file name
echo $(find $k -type f |sort -n | head -n 1)"," >> tmp9
echo "$k done"
done

# tmp1, tmp2, tmp3,...tmp7を左詰めでpasteし一つのファイルに
paste tmp* >> dcm_info.csv
# tmpファイルの削除
rm tmp*

②断面の座標を確認

取得したデータを開き、SliceLocationの列でソートする。 そうすると、SliceLocationがマイナスである被験者とプラスである被験者がいる。 これをヒントにAssendingかDessendingかをSliceOrder列にLabelづけし、dcm_info.csvとして保存

FolderName PatientName PatientID PatientBirthDate # 性別(PatientSex) PatientAge PerformedProcedureStepStartDate SliceLocation PerformedProcedureStepStartDate SliceOrder
3 XXX 3 19480418 M 067Y 20151125 -49.93 0003/instance_0.dcm assending
2 XXX 2 19380903 M 077Y 20151117 -47.36 0002/instance_0.dcm assending
1 XXX 1 19390107 F 076Y 20151117 36.39 0001/instance_0.dcm assending

③DICOMからPNGへ変換

DICOMからPNGへの変換は【Python】DICOMからPNGやCSVに変換を参考にしている。

AscendingとDescendingの区別は、dcm_info.csvに保存されたSliceOrderを参照する。 保存時のファイル名には数字を割り振っているが"{0:03d}".format(i)で名前付けすることで桁数が揃うように工夫してある。

Pythonで以下を実行。

import pandas as pd
import os
import numpy as np
import pydicom  
import glob
import cv2

def dcm2png(dcm):
    d = pydicom.read_file(dcm)
    value = d.pixel_array
    wc = d.WindowCenter
    ww = d.WindowWidth
    max, min = wc + ww / 2, wc - ww / 2
    value_std = 255 * (value - min) / (max - min)
    return value_std


df = pd.read_csv('dcm_info.csv', dtype=str)
for k in range(df.shape[0]):
    os.makedirs('PNG/' + df['FolderName'][k])
    output = []
    if df['SliceOrder'][k] == 'assending':
        for i in range(int(df['Slices'][k])):
            output.append("{0:03d}".format(i))
    else:
        for i in range(int(df['Slices'][k]) -1, -1, -1):
            output.append("{0:03d}".format(i))

    for j, dcm in enumerate(sorted(glob.glob('./rawdata/' + str(df['FolderName'][k])+'/*'))):
        print("{}/{}".format(k,dcm))
        value_std = dcm2png_csv(dcm)
        cv2.imwrite(('PNG/' + df['FolderName'][k] + '/' + output[j]+'.png'), value_std)

④画像の確認

いちいちフォルダを開いてみていては、日が暮れるため工夫をする。 やり方は、【画像連結】画像をタイル状に並べるを参考にする。 まず初めに、被験者ごとに横並びになるように画像を結合して1枚の画像(tile.jpg)にする。 結合にはImageMagickを用いる。 Bashで以下を実行。

$ for k in *;do
> montage $k/*png -geometry 512x512 -tile 20x1 $k/tile.jpg
> done

次に、被験者ごとに作成したtile.jpgをhtmlを通して一括でみれるようにする。

$ echo "<html>" >> index.html 
$ echo "<body>" >> index.html 
$ find . -type f -name tile.jpg |sort |xargs -i echo '<a href="{}">{}<img src="{}" WIDTH=1400 /></a><br />' >> index.html
$ echo "</html>" >> index.html 
$ echo "</body>" >> index.html

できあがったindex.htmlをブラウザで開くと、すべての被験者のtile.jpgがみれる。 index.htmlの中身はこんな感じ。

<a href="./0001/0001.jpg">0001.jpg><img src="./0001/0001.jpg" WIDTH=5000 /></a><br />
<a href="./0002/0002.jpg">0002.jpg><img src="./0002/0002.jpg" WIDTH=5000 /></a><br />
<a href="./2000/2000.jpg">2000.jpg><img src="./2000/2000.jpg" WIDTH=5000 /></a><br />



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