PythonでDICOM画像を読み込んでみよう|pydicom入門

医療画像AIの第一歩は、DICOM画像を扱えるようになること。Pythonライブラリ「pydicom」を使った読み込み・メタデータ取得・画像表示の方法を、コード付きで丁寧に解説します。

DICOMとは?医療画像の標準フォーマット

医療AIに興味を持って「まずは画像を触ってみよう」と思ったとき、最初にぶつかるのが DICOM(ダイコム) という聞き慣れないファイル形式ではないでしょうか。

DICOMは「Digital Imaging and Communications in Medicine」の略で、CT・MRI・X線・超音波など、病院で撮影される医療画像のほぼすべてに使われている国際標準規格です。JPEGやPNGと違い、画像データだけでなく患者情報や撮影条件などのメタデータが1つのファイルにまとめて格納されているのが大きな特徴です。

💡 DICOMファイルの特徴

DICOMファイルには、画像のピクセルデータに加えて「患者名」「撮影日」「スライス厚」「ウィンドウ幅」など、数百種類のメタデータ(タグ)が含まれています。拡張子は .dcm が一般的ですが、拡張子がないファイルも多く存在します。

医療画像AIを開発するには、このDICOMファイルを正しく読み込み、ピクセルデータを取り出す必要があります。そこで活躍するのが、今回紹介する pydicom です。

pydicomのインストールと環境準備

pydicom は、PythonでDICOMファイルを扱うためのオープンソースライブラリです。DICOMファイルの読み込み・書き出し・メタデータの取得や編集が簡単にできます。

インストール

pip でインストールできます。画像を表示するために matplotlib、数値計算用に numpy も併せて入れましょう。

$ pip install pydicom matplotlib numpy

サンプルDICOMファイルの入手

学習用のDICOMファイルが手元にない場合でも大丈夫です。pydicomには練習用のサンプルデータが同梱されています。以下のコードでサンプルファイルのパスを取得できます。

Python
from pydicom.data import get_testdata_file # pydicom同梱のサンプルファイル一覧を確認 print(get_testdata_file("CT_small.dcm"))

また、パブリックドメインの医療画像データセットとしては The Cancer Imaging Archive(TCIA) が有名です。研究・学習目的で多数のDICOMデータを無料でダウンロードできます。

⚠ 注意:患者データの取り扱い

実際の臨床データを使う場合は、個人情報保護に十分注意してください。DICOMファイルには患者名・生年月日・施設名などの個人情報が含まれます。学習や研究には、匿名化済みのデータセットまたはpydicom同梱のサンプルデータを使用しましょう。

DICOMファイルを読み込んでみよう

pydicomでDICOMファイルを読み込むのはとても簡単です。dcmread() 関数にファイルパスを渡すだけです。

Python
from pydicom.data import get_testdata_file import pydicom # サンプルファイルのパスを取得して読み込む fpath = get_testdata_file("CT_small.dcm") ds = pydicom.dcmread(fpath) # データセットオブジェクトの中身を確認 print(ds)

dcmread() の戻り値は Dataset オブジェクトです。DICOMファイルに含まれるすべてのタグ情報と画像データがこのオブジェクトに格納されています。print(ds) を実行すると、タグの一覧が表示されます。

メタデータ(タグ情報)を取得する

DICOMファイルの強みは、画像と一緒に撮影条件や装置情報がすべて記録されていることです。pydicomでは、タグ名を属性としてアクセスするだけで値を取得できます。

Python
# 主要なメタデータにアクセス print("患者名 :", ds.PatientName) print("患者ID :", ds.PatientID) print("モダリティ :", ds.Modality) # CT, MR, CR など print("撮影日 :", ds.StudyDate) print("画像サイズ :", ds.Rows, "×", ds.Columns) print("スライス厚 :", ds.SliceThickness) print("ピクセル間隔 :", ds.PixelSpacing)

出力例は次のようになります。

患者名 : CompressedSamples^CT1 患者ID : 1CT1 モダリティ : CT 撮影日 : 20040119 画像サイズ : 128 × 128 スライス厚 : 5.000000 ピクセル間隔 : [0.661468, 0.661468]

タグ番号でアクセスする方法

DICOMの各項目には「タグ番号」と呼ばれる (グループ, エレメント) の組が割り当てられています。タグ番号で直接アクセスすることもできます。

Python
# タグ番号でアクセス(Modality = (0008, 0060)) modality_tag = ds[0x0008, 0x0060] print(modality_tag) # → (0008, 0060) Modality CS: 'CT' # 全タグの一覧をループで確認 for elem in ds: if elem.tag.group != 0x7FE0: # ピクセルデータは除外 print(elem)

💡 よく使うDICOMタグ一覧

医療画像AI開発でよく参照するタグをまとめておきます。Modality(CTかMRIかの判別)、PixelSpacing(ピクセルの実寸)、SliceThickness(スライス厚)、RescaleSlope / RescaleIntercept(CT値への変換係数)、WindowCenter / WindowWidth(表示ウィンドウの設定値)あたりは頻繁に使います。

画像データをmatplotlibで表示する

DICOMファイルの画像データ(ピクセル配列)は ds.pixel_array で取得できます。これはNumPy配列として返されるので、そのまま matplotlib で表示できます。

Python
from pydicom.data import get_testdata_file import matplotlib.pyplot as plt import pydicom import numpy as np # DICOMファイルを読み込み fpath = get_testdata_file("CT_small.dcm") ds = pydicom.dcmread(fpath) # ピクセルデータをNumPy配列として取得 pixel_array = ds.pixel_array print("配列の形状:", pixel_array.shape) # (128, 128) print("データ型 :", pixel_array.dtype) # int16 # matplotlibで表示 plt.figure(figsize=(6, 6)) plt.imshow(pixel_array, cmap="gray") plt.title("DICOM Image") plt.colorbar(label="Pixel Value") plt.axis("off") plt.tight_layout() plt.show()

pydicomで読み込んだCT画像(matplotlib表示) CT_small.dcm をmatplotlibで表示した例

pixel_array は2次元のNumPy配列(グレースケール画像の場合)で、各要素がピクセル値を表しています。CT画像の場合、ピクセル値はCT値(ハンスフィールド値)に変換する前の「生の格納値」です。

CT値(ハンスフィールド値)への変換

CT画像では、格納されたピクセル値をCT値(HU: Hounsfield Unit)に変換するために、DICOMタグの RescaleSlopeRescaleIntercept を使います。

Python
# CT値(HU)に変換 slope = float(ds.RescaleSlope) intercept = float(ds.RescaleIntercept) hu_image = pixel_array * slope + intercept print("HU最小値:", hu_image.min()) print("HU最大値:", hu_image.max())

CT値は組織の密度を数値化したもので、水が 0 HU、空気が −1000 HU、骨が +1000 HU 前後です。この変換は医療画像AIの前処理で必ず行うステップなので、しっかり覚えておきましょう。

ウィンドニング(表示調整)を理解しよう

CT画像を plt.imshow() でそのまま表示すると、コントラストが弱くて見づらいことがあります。これは、CT値の幅が非常に広い(−1000〜+3000程度)のに対し、人間が一度に識別できる階調は限られているためです。

ウィンドニング(Window/Level) とは、表示するCT値の範囲を限定してコントラストを調整するテクニックです。DICOMファイルに推奨値が格納されていることが多く、WindowCenterWindowWidth というタグで確認できます。

Python
import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams['font.family'] = 'MS Gothic' def apply_window(image, center, width): """ウィンドニングを適用する関数""" lower = center - width / 2 upper = center + width / 2 windowed = np.clip(image, lower, upper) # 0〜255にスケーリング windowed = (windowed - lower) / (upper - lower) * 255 return windowed.astype(np.uint8) # DICOMに記録されたウィンドウ設定を取得(タグが存在しない場合はデフォルト値を使用) if hasattr(ds, "WindowCenter") and hasattr(ds, "WindowWidth"): wc = float(ds.WindowCenter) ww = float(ds.WindowWidth) else: wc = 40 # 軟部組織の一般的な値 ww = 400 print(f"WindowCenter: {wc}, WindowWidth: {ww}") # ウィンドニングを適用して表示 windowed_img = apply_window(hu_image, wc, ww) fig, axes = plt.subplots(1, 2, figsize=(12, 5)) axes[0].imshow(hu_image, cmap="gray") axes[0].set_title("元のCT画像(HU値そのまま)") axes[0].axis("off") axes[1].imshow(windowed_img, cmap="gray") axes[1].set_title(f"ウィンドニング適用 (C={wc}, W={ww})") axes[1].axis("off") plt.tight_layout() plt.show()

ウィンドニング適用前後のCT画像比較 左:HU値そのまま表示 右:ウィンドニング適用(C=40, W=400)

左がCT値をそのまま表示した画像、右がウィンドニングを適用した画像です。ウィンドニングを適用すると、注目したい組織のコントラストが大幅に改善されます。

💡 代表的なウィンドウ設定

観察する部位によって、よく使われるウィンドウ設定が決まっています。例えば、肺野を見るなら WC=-600, WW=1500、腹部の軟部組織なら WC=40, WW=400、骨を見るなら WC=300, WW=1500 が一般的です。AIモデルの入力画像を作る際も、適切なウィンドニングを適用するかどうかで精度が変わることがあります。

まとめ ── 次のステップへ

この記事では、Pythonの pydicom ライブラリを使ったDICOM画像の基本操作を解説しました。ポイントを振り返りましょう。

pydicomの基本をマスターしたら、次のステップとして「複数スライスを読み込んで3Dボリュームを再構成する」「画像の前処理パイプラインを構築する」「CNNで画像分類モデルを学習させる」といった応用に進んでいくとよいでしょう。

医療画像AI開発に必要な深層学習の知識については、E資格対策ページで体系的に学べます。特にCNN(畳み込みニューラルネットワーク)は医療画像処理の基盤技術なので、ぜひ押さえておいてください。

AI資格で医療キャリアを広げよう

E資格・G検定の合格ロードマップ、要点解説、オリジナル模試を無料公開中

E資格対策を見る G検定対策を見る

医療AIナビ 運営者

「医療×AI」を専門とする現役AIエンジニア。非専門家からAI開発に参入した経験をもとに、医療AIの最新情報やAI資格対策を発信しています。E資格・G検定・Generative AI Test合格済み。