【Python】DICOM画像(DCM)をJPG画像へ変換

DICOM画像は、医療用の画像フォーマットです。 DICOM画像の特徴は、通常の画像フォーマットと比較して高階調であり、一般的に使用される画像ビューアでは表示できないケースも多いです。 本記事では、DICOM画像を使用頻度が高いJPG画像へ変換することを試みます。 また、変換する際に必要となるウィンドウ処理に関しても記載します。

※私は医療 or 画像処理の専門ではないので、間違いがある可能性も多分にあります。 参考にして頂く際には、ご注意下さい。

DICOM画像

DICOM画像とは

wikiでは、DICOM画像を次のように説明しています。

DICOM(ダイコム)とは、CTやMRI、CRなどで撮影した医用画像のフォーマットと、それらを扱う医用画像機器間の通信プロトコルを定義した標準規格である。 (引用元:DICOM - Wikipedia)

また、DICOM画像は画像データだけではなく、患者の情報(名前・性別・身長など)や画像の撮影状況などのメタ情報を保持しています。 メタ情報の詳細は、下リンクが参考になると思います。

https://www.liberworks.co.jp/407/dicom.html

DICOM画像は、他の画像フォーマットと比較して『①高階調』・『②通常のビューアーでは表示できない』の2つがあります。

①高階調

高階調な画像とは、画素値(各ピクセルの色の濃淡や明るさを表す値)が幅広いレンジの画像のことを指します。 DICOM画像では、一般的な階調表現である8bitを超える10~16bitであることが多いです。

f:id:guarana001:20200725191714p:plain:w600
左図:高階調 / 右図:一般的な階調表現

②通常のビューアーでは表示できない

通常のビューアーでは、DICOM画像を表示できないケースが多いです。

f:id:guarana001:20200725192937p:plain:w600
通常のビューアーでは表示できないケース

サンプルとして使用するDICOM画像

下記リンクより取得できる『CT_JPG_IR6a.dcm』を使用します。

f:id:guarana001:20200725214935p:plain:w600
左図:カラー(未処理) / 右図:グレースケール

www.jira-net.or.jp

DICOM画像を表示するためのソースコード

次のソースコード は、『DICOM画像を扱う前の事前準備』を実施後に実行にして下さい。

from matplotlib import pyplot as plt
import pydicom
  
dcm_sample = pydicom.dcmread("CT_JPG_IR6a.dcm")
plt.imshow(dcm_sample.pixel_array) #カラー(未処理)
plt.imshow(dcm_sample.pixel_array, cmap = 'gray') #グレースケール
plt.show()

PythonでDICOM画像を扱う前の事前準備

PythonでDICOM画像を扱う前にpydicomをインストールする必要があります。 また、JPEGJPEG-LS・JPEG2000を解凍する必要がある場合は、gdcmをインストールして下さい。

pydicomをインストール

pip install pydicom

gdcmをインストール

conda install gdcm -c conda-forge

参考URL

DICOM画像をJPG画像へ変換する方法

DICOM画像のメタ情報にWindowCenter・WindowWidthが存在する場合は、ウィニング処理をした方が適切です。 理由としては、撮影時に重要視した対象()を鮮明に表現できるからです。

※恐らくWindowCenter・WindowWidthの値は、画像撮影時に設定されるものだと思っているので、上のように記述しました。 しかし、WindowCenter・WindowWidthの値を設定する正確なタイミングを把握できていないため、あくまで推察です。

ちなみに、WindowCenter・WindowWidthの有無を確認するソースコードは次の通りです。 WindowCenter・WindowWidthの有無に依り、5行目の結果が変化します。 存在する場合はTrue、存在しない場合はFalseとなります。

from matplotlib import pyplot as plt
import pydicom
  
dcm_sample = pydicom.dcmread("CT_JPG_IR6a.dcm")
print(('WindowCenter' in dcm_sample) and ('WindowWidth' in dcm_sample))

WindowCenter・WindowWidthがない場合

次のソースコード を用いると、DICOM画像をJPG画像(下図)に変換できます。

f:id:guarana001:20200726002239j:plain:w300
CT_NoWindow.jpg

import pydicom
import cv2
  
dcm_sample = pydicom.dcmread("CT_JPG_IR6a.dcm")
dcm_img = dcm_sample.pixel_array 
cv2.imwrite("CT_NoWindow.jpg", dcm_img)

WindowCenter・WindowWidthがある場合

DICOM画像をJPG画像(下図)に変換する際に、ウィニング処理を考慮した場合のソースコード は、次のようになります。 ウィニング処理に関しては、次の節をご確認下さい。

f:id:guarana001:20200726002242j:plain:w300
CT_Window.jpg

import pydicom
import cv2
  
dcm_sample = pydicom.dcmread("CT_JPG_IR6a.dcm")

dcm_wc  = dcm_sample.WindowCenter
dcm_ww  = dcm_sample.WindowWidth
dcm_img = dcm_sample.pixel_array 
  
#ウィンドウ処理
window_max = dcm_wc + dcm_ww/2                     
window_min = dcm_wc - dcm_ww/2
dcm_img = 255*(dcm_img - window_min)/(window_max - window_min)    
dcm_img[dcm_img > 255] = 255
dcm_img[dcm_img < 0] = 0 
cv2.imwrite("CT_Window.jpg", dcm_img)
参考URL

医療情報学研究室: Pyゼミ1.02 DICOMからJPEGなどへの変換

ウィンドウ処理

ウィンドウ処理とは

ウィンドウ処理とは、下図のように幅広いレンジの画素値(各ピクセルの色の濃淡や明るさを表す値)を持つ画像において、特定の範囲の画素値(Window Center ± 0.5*Window Width)一般的な階調表現 (例えば 8 bit)に変換する処理のことを指します。 ウィンドウ処理をすることで、特定の範囲の画素値を鮮明に表現できるようになります。

f:id:guarana001:20200725191710p:plain:w500
ウィンドウ処理

ウィンドウ処理(数式)とは

変換前の画像(高階調)のピクセルの画素値xとし、特定の範囲の画素値に関する情報であるWindow CenterWindow Widthをそれぞれwcwwとおきます。 また、変換後の画像の階調nbit 、変換後のピクセルの画素値yとします。 この時、ウィンドウ処理は、次のような数式で表現できます。

f:id:guarana001:20200726030018p:plain:w500
ウィンドウ処理 (数式)

ウィンドウ処理の効果

上記のDICOM画像が、ウィンドウ処理の有無で、どのように変化するかを比較すると次のようになります。 ウィンドウ処理ある場合の方が、画像が鮮明になり分かりやすくなります

f:id:guarana001:20200726031937p:plain:w500
左図:ウィンドウ処理なし / 右図:ウィンドウ処理あり

参考URL

まとめ

本記事では、医療用の画像フォーマットとして利用されるDICOM画像を、使用頻度が高いJPG画像へ変換する方法を記載しました。 加えて、階調の変換する際に必要となるウィンドウ処理についても記載しました。