关于医疗影像的mhd和dcm格式图像的读取和坐标转换
本篇博客主要對(duì)近年來(lái)大賽(Luna16,kaggle,天池)中使用的肺部圖像的讀取和坐標(biāo)轉(zhuǎn)換進(jìn)行整理,如果有錯(cuò)誤,歡迎批評(píng)指正,謝謝。
1 介紹mhd格式的數(shù)據(jù):
數(shù)據(jù)可以在Luna16(https://luna16.grand-challenge.org/Data/)下載。
(1) ?每個(gè)病例的數(shù)據(jù)的存儲(chǔ)都是由一個(gè).mhd和一個(gè).raw格式的文件組成。
mhd的內(nèi)容和比較重要的注釋:
ObjectType = Image ? ? ??
NDims = 3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#三維數(shù)據(jù)
BinaryData = True ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #二進(jìn)制數(shù)據(jù)
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 ? ? ? ?#原點(diǎn)坐標(biāo)
CenterOfRotation = 0 0 0
AnatomicalOrientation = RAI
ElementSpacing = 0.7617189884185791 0.7617189884185791 2.5 ? ? #像素間隔 x,y,z
DimSize = 512 512 121 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #數(shù)據(jù)的大小 x,y,z
ElementType = MET_SHORT
ElementDataFile = 1.3.6.1.4.1.14519.5.2.1.6279.6001.105756658031515062000744821260.raw ? ? #數(shù)據(jù)存儲(chǔ)的文件名
(2) ?mhd已經(jīng)交代了圖像數(shù)據(jù)的信息,接下來(lái)對(duì)圖像數(shù)據(jù)進(jìn)行讀取,這里主要用的Python中的SimpleITK庫(kù):
以一個(gè)病例為例:
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) #這部分給出了關(guān)于圖像的信息,可以打印處理查看,這里就不在顯示了 #print(itkimage) image = sitk.GetArrayFromImage(itkimage) #z,y,x #查看第100張圖像 plt.figure() plt.imshow(image[100,:,:])(3) ?坐標(biāo)轉(zhuǎn)換
在luna16大賽中提供了醫(yī)生標(biāo)注肺結(jié)節(jié)位置信息的csv文件 和病例的圖像(mhd)。
csv文件中的內(nèi)容形式為:
seriesuid:表示每個(gè)病例圖像對(duì)應(yīng)的文件名
coordX,coordX,coordX,diameter_mm:表示醫(yī)生標(biāo)注的結(jié)節(jié)位置信息和直徑
在使coordX用卷積網(wǎng)絡(luò)對(duì)肺結(jié)節(jié)進(jìn)行檢測(cè)時(shí),我們需要根據(jù)醫(yī)生提供的標(biāo)注信息,在圖像中找到相應(yīng)的肺結(jié)節(jié)位置,接下來(lái)說(shuō)醫(yī)生標(biāo)注的坐標(biāo)與圖像中的坐標(biāo)的關(guān)系。
以一個(gè)病例上的一個(gè)肺結(jié)節(jié)為例:
csv:
mhd中給定了圖像中的原點(diǎn)坐標(biāo)為(-163.1962890625, -319.1962890625, -380.5) ? ? #x,y,z
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?像素間隔為(0.607421875 ,0.607421875 ,0.5) ? ? ? ? ? ? ? ? ? ? #x,y,z
通過(guò)以上信息可以計(jì)算結(jié)節(jié)相對(duì)原點(diǎn)的坐標(biāo),然后用這個(gè)坐標(biāo)除以像素間隔,即為在圖像中對(duì)應(yīng)的結(jié)節(jié)位置。
代碼:
#世界坐標(biāo)轉(zhuǎn)換到圖像中的坐標(biāo)
def worldToVoxelCoord(worldCoord, origin, spacing):stretchedVoxelCoord = np.absolute(worldCoord - origin)voxelCoord = stretchedVoxelCoord / spacingreturn voxelCoord#圖像上的坐標(biāo)轉(zhuǎn)換為世界坐標(biāo):
def VoxelToWorldCoord(voxelCoord, origin, spacing):strechedVocelCoord = voxelCoord * spacingworldCoord = strechedVocelCoord + originreturn worldCoord2、介紹dcm格式的數(shù)據(jù)
數(shù)據(jù)可以從kaggle(https://www.kaggle.com/c/data-science-bowl-2017/data)或LIDC-IDRC(https://wiki.cancerimagingarchive.net/display/Public/LIDC-IDRI)下載
與mhd文件不同的是,每個(gè)病例都是由幾十到幾百?gòu)埖那衅瑯?gòu)成。
接下來(lái)以一個(gè)病例的一個(gè)切片為例:
(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 ? #用于唯一區(qū)分每一張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' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #切片的厚度,注:不同儀器,會(huì)導(dǎo)致不同的切片厚度,但是同一個(gè)病例上的切片厚度是相同的
(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 ? ? #?每個(gè)病例對(duì)應(yīng)的檢查實(shí)例號(hào)
(0020, 000e) Series Instance UID ? ? ? ? ? ? ? ? UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192 ? ? #不同檢查對(duì)應(yīng)的序列實(shí)例號(hào), 注:比如一個(gè)病例中包括不同形式切片,像x光和對(duì)肺部不同顯示的CT切片,如果想要對(duì)他們進(jìn)行歸類時(shí),可以使用這個(gè)實(shí)例號(hào)
(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'] ? ? ?#表示圖像的左上角在空間坐標(biāo)系中的x,y,z坐標(biāo),單位是毫米
(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軸相對(duì)位置
(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這兩個(gè)用于將像素轉(zhuǎn)化為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
以上我對(duì)一些重要的信息做了標(biāo)注。
CT圖像可視化:
image= dicomimage.pixel_array plt.figure(2) plt.imshow(image)(2)坐標(biāo)轉(zhuǎn)換和mhd類似。
(3)接下來(lái)直接貼比較重要的代碼了:
a、將一個(gè)病例的所有圖像進(jìn)行堆疊:
slices = [dicom.read_file(s) for s in dcm] slices.sort(key=lambda x: float(x.ImagePositionPatient[2])) #從小到大排序 從肺的底部到頭部 #x.ImagePositionPatient[2]表示切片空間對(duì)應(yīng)的位置,即z軸b、將CT圖像中的像素轉(zhuǎn)換成HU值
for slice_number in range(len(slices)): #slices表示一個(gè)病例的所有切片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)?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的关于医疗影像的mhd和dcm格式图像的读取和坐标转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python人脸识别表情检测器(2):基
- 下一篇: 猫抓 浏览器插件安装教程,适用Chrom