关于医疗影像的mhd和dcm格式图像的读取和坐标转换
本篇博客主要對近年來大賽(Luna16,kaggle,天池)中使用的肺部圖像的讀取和坐標轉換進行整理,如果有錯誤,歡迎批評指正,謝謝。
1 介紹mhd格式的數據:
數據可以在Luna16(https://luna16.grand-challenge.org/Data/)下載。
(1) ?每個病例的數據的存儲都是由一個.mhd和一個.raw格式的文件組成。
mhd的內容和比較重要的注釋:
ObjectType = Image ? ? ??
NDims = 3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#三維數據
BinaryData = True ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #二進制數據
BinaryDataByteOrderMSB = False
CompressedData = False
TransformMatrix = 1 0 0 0 1 0 0 0 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #100,010,001 分別代表x,y,z
Offset = -198.10000600000001 -195 -335.209991 ? ? ? ?#原點坐標
CenterOfRotation = 0 0 0
AnatomicalOrientation = RAI
ElementSpacing = 0.7617189884185791 0.7617189884185791 2.5 ? ? #像素間隔 x,y,z
DimSize = 512 512 121 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #數據的大小 x,y,z
ElementType = MET_SHORT
ElementDataFile = 1.3.6.1.4.1.14519.5.2.1.6279.6001.105756658031515062000744821260.raw ? ? #數據存儲的文件名
(2) ?mhd已經交代了圖像數據的信息,接下來對圖像數據進行讀取,這里主要用的Python中的SimpleITK庫:
以一個病例為例:
import SimpleITK as sitk import matplotlib.pyplot as plt case_path = './1.3.6.1.4.1.14519.5.2.1.6279.6001.126264578931778258890371755354.mhd' itkimage = sitk.ReadImage(case_path) #這部分給出了關于圖像的信息,可以打印處理查看,這里就不在顯示了 #print(itkimage) image = sitk.GetArrayFromImage(itkimage) #z,y,x #查看第100張圖像 plt.figure() plt.imshow(image[100,:,:])(3) ?坐標轉換
在luna16大賽中提供了醫生標注肺結節位置信息的csv文件 和病例的圖像(mhd)。
csv文件中的內容形式為:
seriesuid:表示每個病例圖像對應的文件名
coordX,coordX,coordX,diameter_mm:表示醫生標注的結節位置信息和直徑
在使coordX用卷積網絡對肺結節進行檢測時,我們需要根據醫生提供的標注信息,在圖像中找到相應的肺結節位置,接下來說醫生標注的坐標與圖像中的坐標的關系。
以一個病例上的一個肺結節為例:
csv:
mhd中給定了圖像中的原點坐標為(-163.1962890625, -319.1962890625, -380.5) ? ? #x,y,z
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?像素間隔為(0.607421875 ,0.607421875 ,0.5) ? ? ? ? ? ? ? ? ? ? #x,y,z
通過以上信息可以計算結節相對原點的坐標,然后用這個坐標除以像素間隔,即為在圖像中對應的結節位置。
代碼:
#世界坐標轉換到圖像中的坐標
def worldToVoxelCoord(worldCoord, origin, spacing):stretchedVoxelCoord = np.absolute(worldCoord - origin)voxelCoord = stretchedVoxelCoord / spacingreturn voxelCoord#圖像上的坐標轉換為世界坐標:
def VoxelToWorldCoord(voxelCoord, origin, spacing):strechedVocelCoord = voxelCoord * spacingworldCoord = strechedVocelCoord + originreturn worldCoord2、介紹dcm格式的數據
數據可以從kaggle(https://www.kaggle.com/c/data-science-bowl-2017/data)或LIDC-IDRC(https://wiki.cancerimagingarchive.net/display/Public/LIDC-IDRI)下載
與mhd文件不同的是,每個病例都是由幾十到幾百張的切片構成。
接下來以一個病例的一個切片為例:
(1)dcm格式文件的讀取:
import dicom import matplotlib.pyplot as plt case_path = './1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192/000001.dcm' dicomimage = dicom.read_file(case_path) #給出了圖像中的信息 print(dicomimage)(0008, 0005) Specific Character Set ? ? ? ? ? ? ?CS: 'ISO_IR 100'
(0008, 0008) Image Type ? ? ? ? ? ? ? ? ? ? ? ? ?CS: ['ORIGINAL', 'PRIMARY', 'AXIAL']
(0008, 0016) SOP Class UID ? ? ? ? ? ? ? ? ? ? ? UI: CT Image Storage
(0008, 0018) SOP Instance UID ? ? ? ? ? ? ? ? ? ?UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.143451261327128179989900675595 ? #用于唯一區分每一張dcm切片
(0008, 0020) Study Date ? ? ? ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0008, 0021) Series Date ? ? ? ? ? ? ? ? ? ? ? ? DA: '20000101'
(0008, 0022) Acquisition Date ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0008, 0023) Content Date ? ? ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0008, 0024) Overlay Date ? ? ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0008, 0025) Curve Date ? ? ? ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0008, 002a) Acquisition DateTime ? ? ? ? ? ? ? ?DT: '20000101'
(0008, 0030) Study Time ? ? ? ? ? ? ? ? ? ? ? ? ?TM: ''
(0008, 0032) Acquisition Time ? ? ? ? ? ? ? ? ? ?TM: ''
(0008, 0033) Content Time ? ? ? ? ? ? ? ? ? ? ? ?TM: ''
(0008, 0050) Accession Number ? ? ? ? ? ? ? ? ? ?SH: '2819497684894126'
(0008, 0060) Modality ? ? ? ? ? ? ? ? ? ? ? ? ? ?CS: 'CT'
(0008, 0070) Manufacturer ? ? ? ? ? ? ? ? ? ? ? ?LO: 'GE MEDICAL SYSTEMS'
(0008, 0090) Referring Physician's Name ? ? ? ? ?PN: ''
(0008, 1090) Manufacturer's Model Name ? ? ? ? ? LO: 'LightSpeed Plus'
(0008, 1155) Referenced SOP Instance UID ? ? ? ? UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.675906998158803995297223798692
(0010, 0010) Patient's Name ? ? ? ? ? ? ? ? ? ? ?PN: ''
(0010, 0020) Patient ID ? ? ? ? ? ? ? ? ? ? ? ? ?LO: 'LIDC-IDRI-0001'
(0010, 0030) Patient's Birth Date ? ? ? ? ? ? ? ?DA: ''
(0010, 0040) Patient's Sex ? ? ? ? ? ? ? ? ? ? ? CS: ''
(0010, 1010) Patient's Age ? ? ? ? ? ? ? ? ? ? ? AS: ''
(0010, 21d0) Last Menstrual Date ? ? ? ? ? ? ? ? DA: '20000101'
(0012, 0062) Patient Identity Removed ? ? ? ? ? ?CS: 'YES'
(0012, 0063) De-identification Method ? ? ? ? ? ?LO: 'DCM:113100/113105/113107/113108/113109/113111'
(0013, 0010) Private Creator ? ? ? ? ? ? ? ? ? ? LO: 'CTP'
(0013, 1010) Private tag data ? ? ? ? ? ? ? ? ? ?LO: 'LIDC-IDRI'
(0013, 1013) Private tag data ? ? ? ? ? ? ? ? ? ?LO: '62796001'
(0018, 0010) Contrast/Bolus Agent ? ? ? ? ? ? ? ?LO: 'IV'
(0018, 0015) Body Part Examined ? ? ? ? ? ? ? ? ?CS: 'CHEST'
(0018, 0022) Scan Options ? ? ? ? ? ? ? ? ? ? ? ?CS: 'HELICAL MODE'
(0018, 0050) Slice Thickness ? ? ? ? ? ? ? ? ? ? DS: '2.500000' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #切片的厚度,注:不同儀器,會導致不同的切片厚度,但是同一個病例上的切片厚度是相同的
(0018, 0060) KVP ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DS: '120'
(0018, 0090) Data Collection Diameter ? ? ? ? ? ?DS: '500.000000'
(0018, 1020) Software Version(s) ? ? ? ? ? ? ? ? LO: 'LightSpeedApps2.4.2_H2.4M5'
(0018, 1100) Reconstruction Diameter ? ? ? ? ? ? DS: '360.000000'
(0018, 1110) Distance Source to Detector ? ? ? ? DS: '949.075012'
(0018, 1111) Distance Source to Patient ? ? ? ? ?DS: '541.000000'
(0018, 1120) Gantry/Detector Tilt ? ? ? ? ? ? ? ?DS: '0.000000'
(0018, 1130) Table Height ? ? ? ? ? ? ? ? ? ? ? ?DS: '144.399994'
(0018, 1140) Rotation Direction ? ? ? ? ? ? ? ? ?CS: 'CW'
(0018, 1150) Exposure Time ? ? ? ? ? ? ? ? ? ? ? IS: '570'
(0018, 1151) X-Ray Tube Current ? ? ? ? ? ? ? ? ?IS: '400'
(0018, 1152) Exposure ? ? ? ? ? ? ? ? ? ? ? ? ? ?IS: '4684'
(0018, 1160) Filter Type ? ? ? ? ? ? ? ? ? ? ? ? SH: 'BODY FILTER'
(0018, 1170) Generator Power ? ? ? ? ? ? ? ? ? ? IS: '48000'
(0018, 1190) Focal Spot(s) ? ? ? ? ? ? ? ? ? ? ? DS: '1.200000'
(0018, 1210) Convolution Kernel ? ? ? ? ? ? ? ? ?SH: 'STANDARD'
(0018, 5100) Patient Position ? ? ? ? ? ? ? ? ? ?CS: 'FFS'
(0020, 000d) Study Instance UID ? ? ? ? ? ? ? ? ?UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178 ? ? #?每個病例對應的檢查實例號
(0020, 000e) Series Instance UID ? ? ? ? ? ? ? ? UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192 ? ? #不同檢查對應的序列實例號, 注:比如一個病例中包括不同形式切片,像x光和對肺部不同顯示的CT切片,如果想要對他們進行歸類時,可以使用這個實例號
(0020, 0010) Study ID ? ? ? ? ? ? ? ? ? ? ? ? ? ?SH: ''
(0020, 0011) Series Number ? ? ? ? ? ? ? ? ? ? ? IS: '3000566'
(0020, 0013) Instance Number ? ? ? ? ? ? ? ? ? ? IS: '80'
(0020, 0032) Image Position (Patient) ? ? ? ? ? ?DS: ['-166.000000', '-171.699997', '-207.500000'] ? ? ?#表示圖像的左上角在空間坐標系中的x,y,z坐標,單位是毫米
(0020, 0037) Image Orientation (Patient) ? ? ? ? DS: ['1.000000', '0.000000', '0.000000', '0.000000', '1.000000', '0.000000']
(0020, 0052) Frame of Reference UID ? ? ? ? ? ? ?UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.229925374658226729607867499499
(0020, 1040) Position Reference Indicator ? ? ? ?LO: 'SN'
(0020, 1041) Slice Location ? ? ? ? ? ? ? ? ? ? ?DS: '-207.500000' ? ? ? ? ? ? ? ? ? ? ? ? ? ? #為切片z軸相對位置
(0028, 0002) Samples per Pixel ? ? ? ? ? ? ? ? ? US: 1
(0028, 0004) Photometric Interpretation ? ? ? ? ?CS: 'MONOCHROME2'
(0028, 0010) Rows ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?US: 512
(0028, 0011) Columns ? ? ? ? ? ? ? ? ? ? ? ? ? ? US: 512
(0028, 0030) Pixel Spacing ? ? ? ? ? ? ? ? ? ? ? DS: ['0.703125', '0.703125'] ? ? ? #像素間隔
(0028, 0100) Bits Allocated ? ? ? ? ? ? ? ? ? ? ?US: 16
(0028, 0101) Bits Stored ? ? ? ? ? ? ? ? ? ? ? ? US: 16
(0028, 0102) High Bit ? ? ? ? ? ? ? ? ? ? ? ? ? ?US: 15
(0028, 0103) Pixel Representation ? ? ? ? ? ? ? ?US: 1
(0028, 0120) Pixel Padding Value ? ? ? ? ? ? ? ? US: 63536
(0028, 0303) Longitudinal Temporal Information M CS: 'MODIFIED'
(0028, 1050) Window Center ? ? ? ? ? ? ? ? ? ? ? DS: '-600'
(0028, 1051) Window Width ? ? ? ? ? ? ? ? ? ? ? ?DS: '1600'
(0028, 1052) Rescale Intercept ? ? ? ? ? ? ? ? ? DS: '-1024' ? ? ? ? ? #有的CT圖像中像素不是HU值,Rescale Intercept和Rescale Slope這兩個用于將像素轉化為HU值
(0028, 1053) Rescale Slope ? ? ? ? ? ? ? ? ? ? ? DS: '1'
(0038, 0020) Admitting Date ? ? ? ? ? ? ? ? ? ? ?DA: '20000101'
(0040, 0002) Scheduled Procedure Step Start Date DA: '20000101'
(0040, 0004) Scheduled Procedure Step End Date ? DA: '20000101'
(0040, 0244) Performed Procedure Step Start Date DA: '20000101'
(0040, 2016) Placer Order Number / Imaging Servi LO: ''
(0040, 2017) Filler Order Number / Imaging Servi LO: ''
(0040, a075) Verifying Observer Name ? ? ? ? ? ? PN: 'Removed by CTP'
(0040, a123) Person Name ? ? ? ? ? ? ? ? ? ? ? ? PN: 'Removed by CTP'
(0040, a124) UID ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.335419887712224178340067932923
(0070, 0084) Content Creator's Name ? ? ? ? ? ? ?PN: ''
(0088, 0140) Storage Media File-set UID ? ? ? ? ?UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.211790042620307056609660772296
(7fe0, 0010) Pixel Data ? ? ? ? ? ? ? ? ? ? ? ? ?OW: Array of 524288 bytes
以上我對一些重要的信息做了標注。
CT圖像可視化:
image= dicomimage.pixel_array plt.figure(2) plt.imshow(image)(2)坐標轉換和mhd類似。
(3)接下來直接貼比較重要的代碼了:
a、將一個病例的所有圖像進行堆疊:
slices = [dicom.read_file(s) for s in dcm] slices.sort(key=lambda x: float(x.ImagePositionPatient[2])) #從小到大排序 從肺的底部到頭部 #x.ImagePositionPatient[2]表示切片空間對應的位置,即z軸b、將CT圖像中的像素轉換成HU值
for slice_number in range(len(slices)): #slices表示一個病例的所有切片intercept = slices[slice_number].RescaleInterceptslope = slices[slice_number].RescaleSlopeif slope != 1:image[slice_number] = slope * image[slice_number].astype(np.float64)image[slice_number] = image[slice_number].astype(np.int16)image[slice_number] += np.int16(intercept)?
?
?
?
?
總結
以上是生活随笔為你收集整理的关于医疗影像的mhd和dcm格式图像的读取和坐标转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python人脸识别表情检测器(2):基
- 下一篇: 计算机启动时滴滴两声,电脑开机时出现滴滴