PyDicom
DICOM
醫學影像
醫學影像(Medical Imaging),是指利用某種介質(例如X射線、電磁、超聲波等等)與人體相互作用,從而以影像方
式將人體內部組織器官的結構和密度表現出來,然后提供給醫生進行判斷並對人體健康狀況得出結論的一門科學。
醫學儀器
醫學影像儀器主要包含:
1, X光影像儀器
2, CT(Computerized Tomography Computed Tomography)
3, 超聲(分B超、彩色多普勒超聲、心臟彩超、三維彩超)
4, 核磁共振成像(MRI)
DICOM簡介
DICOM(醫學數字成像和通訊),英文全稱Digital Imaging and Communications in Medicine,是ACR(美國放射協會
和NAMA(美國國家電子制造商協會)聯合開發醫學數字成像和通訊的一個通用標准。隨着X線斷層造影技術和其他數字診斷模式的產生,
以及計算機的使用在臨床應用中的增長,為實現在不同制造商生產的設備之間傳輸圖像和聯合信息的標准方法—DICOM標准,在1985年
應運而生並不斷的改版升級,現在主要是3.0版本。對於醫學專業的同學如要了解更多的相關背景知識,可以參考Dicom
官方文檔。DICOM顧名思義,關鍵點在於D-igital I-maging和C-ommunications,
標准主要由三個部分組成:
- a file format for images and reports
- a set of defined services
- a network protocol
DICOM文件格式詳解
Dicom全稱是醫學數字圖像與通訊,文件后綴通常為*.dcm,DICOM文件是標記的圖像文件,包含圖像和有關圖像的數據集合,其能夠在兩
個以DICOM格式接收患者數據和圖像的實體之間進行交流。通俗的理解就是:患者的醫學圖像以DICOM文件格式進行存儲,其中包含了圖像 信息以及患者的PHI(protected health
information,即姓名、性別、年齡等),以及產生圖像的設備的相關信息。
文件解析:整體結構先是128字節所謂的導言部分,然后是dataElement依次排列的方式 就是一個dataElement接一個dataElement的 方式排到文件結尾,其存儲的信息為二進制格式。
DICOM文件頭包含了標識數據集合的相關信息,每個DICOM文件都必須包含文件頭,主要信息:
- 文件導言: 由128個字節組成,描述文件的相關導言信息。
- DICOM前綴: 由4個字節組成,用於判斷其字符串值是否為"DICOM"從而判斷是否為DICOM文件,可以理解為一個標志信息。
- 文件元信息元素
DICOM數據集是DICOM文件的主要組成部分,其由DICOM數據元素按照指定的順序排列。數據元素最基本的數據單元是數據元, 按照TAG從小到大順序排列,即一個數據元表示一個TAG。數據元主要由4個部分組成:
- TAG號: 由4個字節組成,包括2字節的組號和2字節的元素號(例如:0010 0040
表示患者性別,其中的組號:0002描述設備通訊信息、0008描述特征參數、0010描述患者信息、0028描述圖像信息參數)。我們后期所需要的DICOM文件相關數據時,就是根據TAG來獲取。 - 值表示(VR,value representation) 由兩個字節的字符組成,存儲描述該項數據元信息的數據類型,包含例如:LO(Long String,長字符串)、IS(Interger
String,整型字符串),DA(data,日期)等等共27種數據類型。 - 值長度(value length 存儲描述該項信息的數據長度
- 值域(value) 存儲描述該項信息的數據值
標記tag(2字節UInt16分組號和2字節UInt16元素號)
tag是4個字節表示的 前兩字節是組號后兩字節是元素號 比如0008(組號) 0018(元素號)。
我們獲取dicom里面的數據,就是根據tag,來知道這個dataElement里面是否是我們需要的數據,然后讀取該dataElement里面的數據。
tag的dataElement結構,分為下面三種:
- 顯示VR:VR為OB OW OF UT SQ UN的元素結構
組號 | 元素號 | VR | 預留 | 值長度 | 數據元素值 |
---|---|---|---|---|---|
2 | 2 | 2 | 2(0x00,0x00) | 4 | 由數據長度決定 |
組號和元素號組成tag,上面的數組表示給類型占有的字節長度
- 顯示VR:VR為普通類型時元素結構(少了預留那一行)
組號 | 元素號 | VR | 值長度 | 數據元素值 |
---|---|---|---|---|
2 | 2 | 2 | 4 | 由數據長度決定 |
- 隱式VR時元素結構(也就是dataElement中沒有VR這個值)
組號 | 元素號 | 值長度 | 數據元素值 |
---|---|---|---|
2 | 2 | 4 | 由數據長度決定 |
所有dataElement從前到后按tag又可簡單分段
文件元dataElement | 不受傳輸語法影響 總是以顯示VR方式表示 因為它里面就定義了傳輸語法 |
---|---|
普通dataElement | 受傳輸語法影響 顯示VR表示方式還是隱式VR表示方式 |
像素數據dataElement | 最重要也是最大的一個數據項 其實存儲的就是圖像數據 |
dicom文件的圖像分為壓縮過的和沒壓縮的。
下面羅列出該tag的VF值,並介紹他表示的意義
未壓縮:
無損壓縮:
有損壓縮:
其中數據元信息可以根據信息的不同,分為4類:
Patient Study Series Image
可以理解為一個患者(patient)可以做多次檢查(study),一次檢查包含多個檢查部位(series),而每個檢查部位都有一張或多張相應的影像圖像(image)。常見的TAG如下:
-
Patient Tag
-
Study Tag
-
Series Tag
-
Image Tag
pydicom
說明
- Pydicom是一個用於處理DICOM格式文件的Python包,可以處理包括如醫學圖像(CT等)、報告等。
- Pydicom支持DICOM格式的讀取:可以將dicom文件讀入python結構,同時支持修改后的數據集可以
再次寫入DICOM格式文件。但需要注意,它不是被設計為查看圖像,主要是用來操作DICOM文件的各種數據元素。
安裝
- 支持PIP和Conda安裝
# conda
conda install pydicom --channel conda-forge
# pip
pip install pydicom
文件的讀取以及數據元的獲取
import pydicom
info = {}
# 讀取dicom文件
dcm = pydicom.read_file("test.dcm")
# 通過字典關鍵字來獲取圖像的數據元信息(當然也可以根據TAG號)
# 這里獲取幾種常用信息
info["PatientID"] = dcm.PatientID # 患者ID
info["PatientName"] = dcm.PatientName # 患者姓名
info["PatientBirthData"] = dcm.PatientBirthData # 患者出生日期
info["PatientAge"] = dcm.PatientAge # 患者年齡
info['PatientSex'] = dcm.PatientSex # 患者性別
info['StudyID'] = dcm.StudyID # 檢查ID
info['StudyDate'] = dcm.StudyDate # 檢查日期
info['StudyTime'] = dcm.StudyTime # 檢查時間
info['InstitutionName'] = dcm.InstitutionName # 機構名稱
info['Manufacturer'] = dcm.Manufacturer # 設備制造商
info['StudyDescription'] = dcm.StudyDescription # 檢查項目描述
print(info)
獲取圖像Tag中的像素矩陣並保存為JPG圖片
import pydicom
import matplotlib.pyplot as plt
import numpy as np
filename = "test.dcm"
jpgname = "test.jpg"
# 讀取dicom文件
dcm = pydicom.read_file(filename)
# 獲取圖像唯一標識符UID
uid = dcm.SOPInstanceUID
# 獲取像素矩陣
img_arr = dcm.pixel_array
# 打印矩陣大小
print(img_arr.shape)
# 獲取像素點個數
lens = img_arr.shape[0] * img_arr.shape[1]
# 獲取像素點的最大值和最小值
arr_temp = np.reshape(img_arr, (lens,))
max_val = max(arr_temp)
min_val = min(arr_temp)
# 圖像歸一化
img_arr = (img_arr - min_val) / (max_val - min_val)
# 繪制圖像並保存
plt.figure(figsize=(12, 12), dpi=250) # 圖像大小可以根據文件不同進行設置
plt.imshow(img_arr, cmap=plt.cm.bone)
plt.title(f"UID:{uid}")
plt.savefig(jpgname)
plt.close()
若試圖直接用pydicm打開並讀取pixel_array,則會報錯:
安裝gdcm后進行讀取:
dicom格式轉換從PEG-LS Lossless Image Compression 轉為UI: Explicit VR Little Endian
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: 解壓縮
# Author: yunhgu
# Date: 2022/2/16 18:25
# Description: dicom格式轉換從PEG-LS Lossless Image Compression 轉為UI: Explicit VR Little Endian
# -------------------------------------------------------------------------------
import gdcm
file = r"F:\測試代碼\個人學習\Pydicom使用測試\code\data\16365990659181.dcm"
file2 = r"F:\測試代碼\個人學習\Pydicom使用測試\code\data\16365990659181.unzip.dcm"
reader = gdcm.ImageReader()
reader.SetFileName(file)
if not reader.Read():
print("error")
change = gdcm.ImageChangeTransferSyntax()
change.SetInput(reader.GetImage())
change.SetTransferSyntax(gdcm.TransferSyntax(gdcm.TransferSyntax.ImplicitVRLittleEndian))
if not change.Change():
print("error2")
writer = gdcm.ImageWriter()
writer.SetFileName(file2)
writer.SetFile(reader.GetFile())
writer.SetImage(change.GetOutput())
if not writer.Write():
print("write")