自分のための備忘録的なブログです。

Ubuntu14.04LTS を使って、ディープラーニングの勉強をしています。
記載されているコードは、他の OS には互換性がない可能性があります。


DNN:
マシン性能別 学習速度の比較, TFチュートリアルをmodifyする

python3:
オブジェクト指向プログラミングとは, モジュールとインポート、パスを通す, システムコマンド(os), ファイル・フォルダ名取得, 画像の前処理,

Ubuntu14 の初期設定:
Ubuntu14初期設定, 初期設定-2, cudaなども, 初期設定-3

pydicom の基本的な使い方

DICOM ファイルを python で扱いたいとき、まず触るのが pydicom でしょう。

科学技術分野に強いプログラミング言語python で dicom を自由に扱えるようになれば、医用画像の研究にとても便利! もちろんディープラーニングにも。

しかし日本語ドキュメントが少ないのが残念なところ。

とりあえず、いくつかコードを試してみます。

 

Python で DICOM を扱うのは、情報が少ないですが、

学習できるページ:

https://pyscience.wordpress.com/2014/09/08/dicom-in-python-importing-medical-image-data-into-numpy-with-pydicom-and-vtk/ 

http://qiita.com/fukuit/items/ed163f9b566baf3a6c3f

 

元のユーザーガイドはこちらです(英語)。

Pydicom User Guide — pydicom 1.0a documentation

一通りのコマンドを使ってみます。

 

python 3.6 (Anaconda) + pydicom 0.9.9 にて動作確認。

・・・・・・・・・・・・・・・・・・・・・・・・・・・

 

 

pydicom をインストールする。

PIP を使えば簡単。

bash

$ bash

pip install pydicom

 

pydicom のバージョンを確認する。

PIP にて確認。

bash

 $ bash

pip freeze

 

# answer

alabaster==0.7.9

anaconda-client==1.6.0

anaconda-navigator==1.5

...

pydicom==0.9.9

...

xlrd==1.0.0

XlsxWriter==0.9.6

xlwt==1.2.0 

 

 

 

pydicom をインポートする

# 以下、python

 

>>> python

import dicom #0.9.9までの対応

import pydicom as dicom #1.0以降への対応 

 

# 互換性を維持するため、呼び出し時のメソッドを、pydicom から dicom に変更。

 

# よく使うので、自分はついでに

import sys, os, time, random, dicom, pylab, cv2

import numpy as np

import tensorflow as tf

import matplotlib.pyplot as plt

from PIL import Image

# あたりまで一気にインポートしてしまう。

# コピペ。

 

DICOM 画像を読み込む

 

dicom.read_file() を使う

>>> python

ds = dicom.read_file("IM0.dcm")  # 0.9.9

 

# version >= 1.0a で、メソッドを変更しておかない場合は

ds = pydicom.read_file("IM0.dcm") # >= 1.0a

# dicom.read の代わりに pydicom.read と書く。

 

 

 

 

DICOM ヘッダーを表示する

 

>>> python

ds

 

# answer

(0008, 0005) Specific Character Set CS: 'ISO_IR 100'
(0008, 0008) Image Type CS: ['DERIVED', 'SECONDARY', 'AXIAL', 'MPR THICK', '', '', 'PARALLEL']
(0008, 0012) Instance Creation Date DA: '20171201'
(0008, 0013) Instance Creation Time TM: '105041.192537'
(0008, 0016) SOP Class UID UI: CT Image Storage

...

(0008, 0060) Modality CS: 'CT'

....

 

 

 

 

特定の DICOM ヘッダーを表示する

 

>>> python

ds.Modality

 

# answer

CT

 

 

 

ヘッダーを指定するメソッド( DICOM タグ)を確認する

 

>>> python

ds.dir()

 

# answer

['AccessionNumber', 'AcquisitionDate', 'AcquisitionNumber', 'AcquisitionTime', 'BitsAllocated', 'BitsStored', 'ClinicalTrialProtocolID', 'ClinicalTrialProtocolName', 'ClinicalTrialSiteID', 'ClinicalTrialSiteName', 'ClinicalTrialSponsorName', 'ClinicalTrialSubjectID', 'ClinicalTrialTimePointID', 'Columns', 'ContentDate', 'ContentTime',

(中略)

, 'PatientPosition', 'PatientSex', 'PhotometricInterpretation', 'PixelData', 'PixelRepresentation', 'PixelSpacing', 'PositionReferenceIndicator', 'PresentationLUTShape', 'ProcedureCodeSequence', 'ProtocolName', 'ReferringPhysicianName', 'RequestAttributesSequence', 'RequestedProcedureDescription', 'RescaleIntercept', 'RescaleSlope', 'Rows', 'SOPClassUID', 'SOPInstanceUID', 'SamplesPerPixel', 'SeriesDate', 'SeriesDescription', 'SeriesInstanceUID', 'SeriesNumber', 'SeriesTime', 'SliceThickness', 'SpecificCharacterSet', 'StationName', 'StudyDate', 'StudyDescription', 'StudyID', 'StudyInstanceUID', 'StudyTime', 'WindowCenter', 'WindowCenterWidthExplanation', 'WindowWidth'] 

 

 

 

特定の DICOM タグがあるかどうかを確認する

>>> python

"PatientsName" in ds

# answer

True

 

"Patients\ Name" in ds 

# answer

False

 

 

"""Patients Name""" in ds 

# answer

False

 

 

 

 

"pat" の入っている DICOM タグだけを grep (検索)したい

 

>>> python

ds.dir("pat")

 

# answer
 

['ImageOrientationPatient', 'ImagePositionPatient', 'IssuerOfPatientID', 'PatientAge', 'PatientBirthDate', 'PatientID', 'PatientIdentityRemoved', 'PatientName', 'PatientPosition', 'PatientSex']

 

 

 

特定の DICOM タグを削除する # 挙動は未確認

>>> python

del ds[0x10,0x1000]

 

# OR

 

tag = ds.data_element("OtherPatientIDs").tag
del ds[tag]

 

 

名前を匿名化して、別名保存する

>>> python

ds.PatientsName = 'Anonymus'

ds.save_as('anonymized.dcm')

 

 

ピクセルデータを取り出したい

幾つかの方法がある。

一列でデータを取る。

  普通に DL 目的に使うならこちらで良いか。

# MRIデータ

>>> python

pixel_bytes = ds.PixelData

pixel_bytes

 

 

# answer

\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

\x00\x00\x00\x00\x00\x00 ....

 

# CT データ 。

 

>>>python

CT_pixel_bytes = ds.PixelData

CT_pixel_bytes

 

# answer

'x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\

#中略

0\x93\x00\x8b\x00}\x00V\x00F\x008\x007\x00<\x00B\x00@\x00@\

x000\x00;\x005\x001\x00=\x00,\x00(\x00*\x00$\x00,\x00\x004\x00/\

x00G\x00^\x00Z\x00T\x00^\x00\x00R\x00N\x00G\x00F\x00?\

x00:\x003\x00-\x00:\x003\x00=\

#中略

\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

### CT では x00^ とか、x00Z とか、多彩な数字が出てきました (^_^;)

### x00 が マイナス1000 でしょうね。

### わからん・・・

 

array, 2次元でデータを取る。  

  jpg とかの CNN と、互換性を気にするならこちら。

>>> python
pix = ds.pixel_array # NumPy ライブラリが必要とのこと

pix 

 

 

# answer

array([[0, 0, 0, ..., 0, 0, 0],
          [0, 0, 0, ..., 0, 0, 0],
          [0, 0, 0, ..., 0, 0, 0],
          ...,
          [0, 0, 0, ..., 0, 0, 0],
          [0, 0, 0, ..., 0, 0, 0],
          [0, 0, 0, ..., 0, 0, 0]], dtype=int16)

### int16 16ビット整数

### -2 **15 から 2**15 - 1 の値をとる。

### -32768 ~ 32767

### ムムム、バックグラウンドは-1000HU のはずなのに、0になっとる。。。 

 

 

 

 

 

画像を表示させたい

matplotlib を使う場合。

 

>>> python

import matplotlib.pyplot as plt

import pylab

ds = dicom.read_file("IM0.dcm")

im = ds.pixel_array

plt.imshow(im, cmap=pylab.cm.bone)

plt.show() 

 

ちなみに、普通に

>>> python

import matplotlib.pyplot as plt

import pylab

ds = dicom.read_file("IM0.dcm")

im = ds.pixel_array

plt.imshow(im) #ここが違う

plt.show()

普通に plt.imshow(im) とすると、なぜかカラー画像になっちゃう。

 

Numpy ndarray 経由で tf に数値データを渡す。

import numpy as np

import tensorflow as tf

import os, dicom

os.listdir()

ds = dicom.read_file('filetfname')

im = ds.pixel_array

im_float = im.astype(np.float32) # これはしなくても良い

a = tf.Variable(im_float)

sess = tf.Session 

sess.run(tf.global_variables_initializer())

sess.run(a) 

 

ついでに np.ndarray データを一列にする。

import numpy as np

import tensorflow as tf

import os, dicom

os.listdir()

ds = dicom.read_file('filetfname')

im = ds.pixel_array

imflat = [item for sublist in im for item in sublist]

# 呪文みたい・・・

これで一列表記になる。

普通に imflat = ds.PixelData となると16進数でデータがとられて、データ型は 'bytes' 直感的ではない。いったん im = ds.pixel_array とすると、データ型は 'numpy.ndarray', 数値は int16, その後の処理に続けやすそう。いや、自分はまだ何もできないですけど。。。

imflat_float = imflat.astype(np.float32)

とか、float への変換も簡単。メモリ消費は np の方が多そうなので、デキるお方は bytes で頑張った方が速そうですが!

 

こうして数値で頑張れという話もある一方、面倒なので

plt.savefig('filename.jpg' bbox_inches='tight')

で jpg にしてしまえと言う悪魔のささやきも。。。 

 

jpg にするなら PIL.Image のほうがいいかも。

plt だと端っこに枠が入ってしまう。

Image.fromarray(ds.pixel_array).save('savename.jpg')

 

jpg にしてしまえば、あとは github や qiita にたくさんのコード例がありますからね。。。

へっへっへ。。。

 

ひとまず、以上。