DICOM ๋ฐ์ดํฐ์ DICOM RTSS ๊ตฌ์กฐ ํ์ผ์ ์ฌ์ฉํ์ฌ CT ์ค์บ์์ pyradiomics๋ฅผ ์๋ํ๊ณ ์์ต๋๋ค. RTSS ํ์ผ์๋ ์ฌ๋ฌ ๊ตฌ์กฐ๊ฐ ์์ต๋๋ค. ๋ช
๋ น์ค์ ํตํด plastimatch๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ฌ์ฉํ์ฌ dicom ์ด๋ฏธ์ง ํ์ผ์ ๋จ์ผ 3d nrrd ํ์ผ๋ก ๋ณํํ ๋ค์ RTSS dicom ํ์ผ์ ๋ค๋ฅธ nrrd ํ์ผ๋ก ๋ณํํ์ต๋๋ค.
pydicom์ผ๋ก ํน์ง์ถ์ถ์ ํ๋ฉด ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธด ํ๋ฐ ํ๋์ ์ซ์ ์งํฉ์
๋๋ค. nrrd ๊ตฌ์กฐ ์ธํธ ์ด๋ฏธ์ง์ ๊ฐ ๊ตฌ์กฐ์ ๋ํ ๊ฐ์ ์ป์ ๊ฒ์ผ๋ก ์์ํ์ต๋๋ค. pydicom์ ๋ง์คํฌ๋น ํ๋์ ๊ตฌ์กฐ์์๋ง ์๋ํฉ๋๊น?
๋ฒ์ (๋ค์ ์ ๋ณด๋ฅผ ์์ฑํ์ญ์์ค):
๊ฐ ๊ฒฝ์ฐ์ ๋ํด PyRadiomics๋ ๋ง์คํฌ ํ์ผ( label
๊ฐ์ผ๋ก ์๋ณ)์ 1 ROI์ ๋ํ ๊ธฐ๋ฅ๋ง ๊ณ์ฐํฉ๋๋ค.
์ด ํ๋ผ์คํฐ๋งค์น์ ์๋ ์ฐธ์กฐํ์ญ์์ค. ์ฌ๋ฌ ROI๊ฐ ์ถ๋ ฅ ๋ณผ๋ฅจ์ i๋ฒ์งธ ๋นํธ์ ํ ๋น๋์ด ๊ตฌ์กฐ๊ฐ ๊ฒน์น ์ ์์ต๋๋ค. ๋ํ plastimatch๋ ์ธ๊ทธ๋จผํธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ์ผ์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
๊ฒน์น๋ ์ธ๊ทธ๋จผํธ๊ฐ ์๋ ๊ฒฝ์ฐ PyRadiomics๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง ์๋๋ค๋ ์ ์ ์ ์ํ์ญ์์ค! PyRadiomics๋ ํน์ ์ธ๋ฑ์ค๊ฐ ์๋ ์ ์ฒด ๊ฐ๋ง ๋ด ๋๋ค. 4D ๋ณผ๋ฅจ์ ๋ง์คํฌ๋ก ๊ณต๊ธํ์ฌ ๋ง์คํฌ์์ ๊ฒน์น๋ ๊ตฌ์กฐ๋ฅผ ํ์ฉํฉ๋๋ค. ๊ฒน์นจ์ด ์์ผ๋ฉด ์ ๋๋ก ์๋ํด์ผ ํฉ๋๋ค(์: ๊ฐ๋ฅํ ๋ ์ด๋ธ์ 1, 2, 4, 8 ๋ฑ).
๋ง์คํฌ์ ์ด๋ค ๋ ์ด๋ธ์ด ์๋์ง ์๊ณ ์๋ค๋ฉด ๋ฐฐ์น ๋ชจ๋(์ด "Label") ์์ PyRadiomics๋ฅผ ์ฌ์ฉํ ๋ ๋ ์ด๋ธ์ ์ ์ํ ์ ์์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค @JoostJM
์ด์ ๋ฌธ์ ๋ฅผ ํจ์ฌ ๋ ์ ์ดํดํฉ๋๋ค.
๋์๊ฒ ์ฌ์ ํ ์ฝ๊ฐ ํผ๋์ค๋ฌ์ด ๊ฒ์ ์ด๋ค ๋ ์ด๋ธ์ด ์ด๋ค ๊ตฌ์กฐ๋ฅผ ๋ํ๋ด๋์ง ์์๋ด๋ ๊ฒ์
๋๋ค.
32๊ฐ์ ๊ตฌ์กฐ๊ฐ ์๋ RTSS dicom ํ์ผ์ ์ฌ์ฉํ์ต๋๋ค. ํ์ผ ๋ด์ฉ์ ์๋์ ๋ถ์ฌ๋ฃ์ต๋๋ค.
0|0 255 0|๋ฐ๋
1|0 0 160|์ ๋งฅ_IVC
2|0 255 64|์ ๋งฅ_PV
3|255 0 0|HepVeinRight
4|255 0 0|HepVeinMid
5|255 0 0|๋งฅ๋งฅ ์ผ์ชฝ
6|255 0 0|์ข์ธก ํฌํธ๋ฒ ์ธ
7|255 0 0|PortVeinRight
8|10 10 250|LivSegI
9|128 255 255|LivSegVII
10|255 128 128|LivSegVIII
11|128 64 64|LivSegVI
12|0 150 0|LivSegV
13|0 150 0|LivSegII
14|0 0 160|LivSegIII
15|255 255 128|๋ฆฌ๋ธ์ธ๊ทธIVa
16|255 0 255|LivSegIVb
17|0 0 255|์ ๋งฅ_SMV
18|0 0 255|์ ๋งฅ_๋น์ฅ
19|255 255 0|์ฝ๋ก
20|255 0 255|์ฅ์
21|0 0 255|์
22|187 255 187|์ญ์ด์ง์ฅ
23|128 64 64|์ท์ฅ
24|0 255 255|๋ด๋ญ
25|0 127 255|๋น์ฅ
26|255 128 128|์ ์ฅR
27|50 204 153|์ ์ฅ
28|255 255 0|์๊ดR
29|255 255 0|์๊ด
30|255 210 0|๋ถ์ R
31|255 210 0|๋ถ์ L
32|255 0 0|๋๋๋งฅ ๋๋๋งฅ
33|255 128 0|์ํธ_์
๋ฆฌ์
34|255 128 0|์ํธ_SMA
35|255 128 0|์ํธ_IMA
36|255 128 0|์ํธ๋ ๋
37|0 0 255|์ ๋งฅ_์ ์ฅ
๊ทธ๋ฌ๋ ๋ ์ด๋ธ์ ์ฌ๊ธฐ์ ์๋ ์ซ์์ ์ผ์นํ์ง ์์ต๋๋ค.
๋ ์ด๋ธ์ ๊ตฌ์กฐ์ ์ผ์น์ํค๋ ๋ฐฉ๋ฒ์ ์์๋ด๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ณํ๋ ๋ง์คํฌ ํ์ผ์ ๊ณต์ ํ ์ ์๋์? ๊ทธ๋ฌ๋ฉด ๋ฌด์์ธ์ง ์ ์ ์์ ๊ฒ ๊ฐ์์.
์ด๊ฒ์ .nrrd ํ์ผ์ ๋ํ ๋งํฌ์
๋๋ค.
https://www.dropbox.com/s/mdavn9gxk4fpt5d/abdomen_rtss1.nrrd?dl=0
์ด๊ฒ์ด ์์๋ผ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์
๋๋ค.
์ถ๋ ฅ ํ์ผ์ ์ค์ ๋ก plastimatch ๋ฌธ์์ ์ง์ ๋ ๊ฒ๊ณผ ๊ฑฐ์ ๋น์ทํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ฐ์ดํฐ ์ ํ์ uint8์ ๋๋ค(8๋นํธ = 8๊ฐ์ ๊ฐ๋ฅํ ๋ ์ด๋ธ์ ์๋ฏธ). ๋ ๋ง์ ์ธ๊ทธ๋จผํธ(๊ทํ์ ๊ฒฝ์ฐ 38๊ฐ)๋ฅผ ํ์ฉํ๊ธฐ ์ํด ๋ณผ๋ฅจ์ด 4D ๋ณผ๋ฅจ์ผ๋ก ๋ณํ๋๋ฏ๋ก ์ฑ๋๋น ๋ ์ด๋ธ์ด 8๊ฐ์ ๋๋ค.
Slicer์ PyRadiomics๊ฐ ์ดํดํ๋ ๊ฒ์ ์ป์ผ๋ ค๋ฉด ๋ช ๊ฐ์ง ๊ตฌ์กฐ ์กฐ์ ์ด ํ์ํฉ๋๋ค.
import numpy as np
import SimpleITK as sitk
ma = sitk.ReadImage(r'abdomen_rtss1.nrrd')
ma_arr = sitk.GetArrayFromImage(ma)
labels = []
for channel in range(ma_arr.shape[3]):
for bit in range(8):
label_map = np.zeros(ma_arr.shape[:3], dtype='uint8')
roi = np.bitwise_and(ma_arr[..., channel], 2 ** bit) > 0
if np.sum(roi) > 0:
label_map[roi] = 1
labels.append(label_map)
mask_arr = np.array(labels).transpose(1, 2, 3, 0)
mask_arr.shape
mask = sitk.GetImageFromArray(mask_arr)
mask.CopyInformation(ma)
sitk.WriteImage(mask, r'segmentation.seg.nrrd', True) # Specify True to enable compression
์ด ์ฝ๋ ์กฐ๊ฐ์ ๊ฐ๋ฅํ ๋ชจ๋ ๋ ์ด๋ธ์ ๋ฐ๋ณตํ๊ณ ์ผ์นํ๋ ๋ณต์ ์ ์ฐพ์ผ๋ฉด ๋ ์ด๋ธ ๋งต์ ์ ์ฅํฉ๋๋ค(์ด๋ uint8 ๋ฐ์ดํฐ ์ ํ์ 3D ๋ณผ๋ฅจ์ ๊ฐ์ ํ๋ค๋ ์ ์ ์ ์ํ์ญ์์ค).
๊ทธ๋ฐ ๋ค์ ๋ง์ง๋ง์ 1๊ฐ์ 4D ํ๋ ฌ์ ๋ง๋ค๊ณ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ญ๋๋ค. ๋ง์ง๋ง ๋จ๊ณ๋ก ๋ง์คํฌ์ ๊ธฐํํ์ ์ ๋ณด๊ฐ ๋ณต์ฌ๋๊ณ ๋ถํ ์ด ๋ถํ ๋ก ์ ์ฅ๋ฉ๋๋ค. ์ด๊ฒ์ ์ฌ๋ผ์ด์์ ๋ก๋ํ์ฌ ์ฌ๋ฐ๋ฅธ์ง ํ์ธํ ์ ์์ต๋๋ค.
์ถ๋ ฅ ํ์ผ์ ์ฒซ ๋ฒ์งธ ๊ฐ(0-37)์ ๋ถํ ์ ์ธ๋ฑ์ค์ ์ผ์นํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด "Art_IMA"์ ๋ํ ๊ธฐ๋ฅ์ ์ถ์ถํ๋ ค๋ฉด label_channel=35
์ค์ ์ผ๋ก PyRadiomics๋ฅผ ์คํํ์ญ์์ค( label=1
์ ๋ณ๊ฒฝ๋์ง ์์์ผ ํจ).
๋ง์ง๋ง์ผ๋ก SlicerRT ํ์ฅ์ ์ฌ์ฉํ์ฌ RTSTRUCT๋ฅผ ์ฌ๋ผ์ด์ ๋ ธ๋์ ์ง์ ๋ก๋ํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ถํ ํ์ผ์ ๋ง๋ค ์๋ ์์ต๋๋ค(๊ทธ๋ฌ๋ฉด ์ด๋ฆ๋ ์๋์ผ๋ก ํตํฉ๋จ).
์ ๋ง ๊ฐ์ฌํฉ๋๋ค! @JoostJM
์๋ฆ๋ต๊ฒ ์๋ํฉ๋๋ค. ์ฌ๋ผ์ด์ ๋ฐ ํ์ด์ฌ ์ถ๋ ฅ์์ โโํ์ธํ์ต๋๋ค.
๊ณํ ์์คํ
์์ ์ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์ํํ์ฌ ์์
์๊ฐ์ ์ ์ฝํ์ต๋๋ค. ์ ๋ง ๊ฐ์ฌํฉ๋๋ค.
๋์ ์ค ์์์ด์ ๊ธฐ๋ป
ํด๋น ์ฝ๋๋ฅผ ๋ฐฐ์น ํ์ผ ์์ "batchprocessing.py"์ ์ด๋ป๊ฒ ํตํฉํ์๊ฒ ์ต๋๊น?
@JE-Jimenez, PyRadiomics์ ์ผ๊ด ์ฒ๋ฆฌ์ ๋ํ ๊ถ์ฅ ์ง์ ์ ์ ๋ช ๋ น์ค์ ํตํ ๊ฒ์ ๋๋ค(๋ ๋์ ์ค๋ฅ ์ฒ๋ฆฌ, ๋ค์ค ์ฒ๋ฆฌ ์ง์ ๋ฑ). ์ด ๊ฒฝ์ฐ ๊ฐ๊ฐ "Image", "Mask" ๋ฐ "Label"/"Label_channel" ์ด์ ์ฌ์ฉํ์ฌ csv ํ์ผ์์ ์ด๋ฏธ์ง, ๋ง์คํฌ ๋ฐ ๋ ์ด๋ธ ์กฐํฉ์ ์ง์ ํ ์ ์์ต๋๋ค("Label"์ ๋ ์ด๋ธ ๋งต์ ๋ ์ด๋ธ ๊ฐ์ ๋ํ๋ด๊ณ , "Label_channel" ์ธ๊ทธ๋จผํธ์ 0 ๊ธฐ๋ฐ ์ธ๋ฑ์ค, ์ฐจ์ด์ ์ ๋ ์ด๋ธ ๋งต์ 3D ์ฌ๋ผ์ด์ ๋ฐ ์ธ๋ถํ ์ฐธ์กฐ).
batch processing.py์์ ๋น์ทํ ๊ฒ์ ์ป์ ์ ์์ง๋ง ํ์ฌ๋ label
์๋ง ์ ๊ณต๋ฉ๋๋ค. L81-84 ์ฐธ์กฐ
๋ ์ด๋ธ ๊ฐ ๊ตฌ๋ฌธ ๋ถ์์ ๋ํ ์์ธํ ๋ด์ฉ์