- dicom meta 데이터를 활용한 이미지 전처리
- 실제 dicom 이미지에 저장된 값을 image값으로 변환하기
- dicom 내의 x좌표, y좌표 -> pixel_array[y좌표][x좌표]로 불러오기
- RescaleSlope,RescaleIntercept 는 디스크에 저장된 픽셀에서 메모리 표현으로의 선형 변환을 지정하는 태그
- CT 이미지는 일반적으로 부호없는 변수로 저장되기에 음수로도 저장되는 Houndsfield 단위에 대한 변환을 위해 후처리가 필요
1. Low-level 수준에서의 dicom 이미지 전처리
- RescaleSlope, RescaleIntercept를 활용하여 Dicnom 저장된 이미지 값으로 변환
- Dicom header의 Bits_Stored를 활용하여 normalizaion
- WindowWidth(너비), WindowCenter(중앙값)를 활용하여 조직에 맞게 강조되도록 이미지 수정
- Normalization
2. pydicom을 활용 dicom 이미지 전처리
- apply_modality_lut
- Modality_lut 모달리티에 대한 LUT(Look Up Table)을 활용해 변환(RescaleSlope, RescaleIntercept)
- apply_voi_lut
- LUT에 정의된 보고자 하는 조직에 맞게 강조(WindowWidth, WindowCenter)
# 1. Row-Level 수준에서의 이미지 전처리
ds = pydicom.read_file(Dicom path)
# apply_modality_lut와 동일
if(('RescaleSlope' in ds) and ('RescaleIntercept' in ds)):
pixel_array = (ds.RescaleSlope * ds.pixel_array) + ds.RescaleIntercept
# apply_voi_lut
y_min = 0
y_max = 2**ds.BitsStored - 1
pixel_array = pixel_array.astype("float64")
slope = ds.get("RescaleSlope", None)
intercept = ds.get("RescaleIntercept", None)
if slope is not None and intercept is not None:
ds.RescaleSlope = cast(float, ds.RescaleSlope)
ds.RescaleIntercept = cast(float, ds.RescaleIntercept)
y_min = y_min * ds.RescaleSlope + ds.RescaleIntercept
y_max = y_max * ds.RescaleSlope + ds.RescaleIntercept
y_range = y_max - y_min
elem = ds["WindowCenter"]
center = float(elem.value[0]) if elem.VM > 1 else elem.value
center = cast(float, center)
elem = ds["WindowWidth"]
width = float(elem.value[0]) if elem.VM > 1 else elem.value
width = cast(float, width)
center -= 0.5
width -= 1
below = pixel_array <= (center - width / 2)
above = pixel_array > (center + width / 2)
between = np.logical_and(~below, ~above) # AND 연산
pixel_array[below] = y_min
pixel_array[above] = y_max
if between.any():
pixel_array[between] = ((pixel_array[between] - center) / width + 0.5) * y_range + y_min
# 2. pydicom을 활용한 이미지 전처리
ds = pydicom.read_file(Dicom path)
img = ds.pixel_array
img = apply_modality_lut(img, ds) # RescaleSlope, RescaleIntercept
img = apply_voi_lut(img, ds) # bits_stored 및 WindowSlope, WindowWidth 영상 강조하기
!pip install dicom2nifti
import dicom2nifti
dicom_directory = 'path'
output_directory = 'path'
dicom2nifti.convert_directory(dicom_directory, output_directory)
- dicom→nifti(.dcm→.nii) library
- dicom format을 nifti format으로 바꾸는 라이브러리
- 공식문서 페이지: https://github.com/icometrix/dicom2nift
!pip install dicom2nifti
import dicom2nifti
dicom_directory = 'path'
output_directory = 'path'
dicom2nifti.convert_directory(dicom_directory, output_directory)
- PyDicom 사용법
- 공식문서 페이지 https://pydicom.github.io/7
pip install pydicom
import pydicom
# Data Read (key-value 쌍을 가지는 dict 형태로 출력)
dcm_data=pydicom.dcmread('path')
dcm_data
# 키워드를 통해 표준 요소에 액세스할 수 있음
dcm_data['SOPInstanceUID']
dcm_data.SOPInstanceUID
# 요소는 multi-valued일 수 있음(VM > 1)
dcm_data.ImageType
dcm_data.file_meta
- Load 옵션
- Img array가 무거우므로 로드 시 out of memory 발생할 수 있음 → header만 불러와 탐색하기
# option
stop_before_pixels=True
specific_tags=['header1', 'header2', ...]
- Image Load
def display_dicom_images(dcm_folder):
# 리스트에 dcm 파일들을 저장
dcm_files = [f for f in os.listdir(dcm_folder) if f.endswith(".dcm")]
# 모든 DICOM 파일에 대해 루프
for dcm_file in dcm_files:
# DICOM 파일 경로 생성
dcm_path = os.path.join(dcm_folder, dcm_file)
# Pydicom을 사용하여 DICOM 파일 읽기
dicom = pydicom.dcmread(dcm_path)
# DICOM 이미지 추출
image_array = dicom.pixel_array
# 이미지 출력
plt.imshow(image_array, cmap='gray')
plt.title(f"DICOM Image: {dcm_file}")
plt.show()
folder_path = 'path'
display_dicom_images(folder_path)
'Python Code' 카테고리의 다른 글
torch 모델 save, load (0) | 2024.01.22 |
---|---|
Nibabel 사용법 (0) | 2024.01.19 |
Glob 이용해서 특정폴더의 이미지 경로들을 DataFrame으로 만들기 (0) | 2024.01.11 |
json 파일을 읽고 DataFrame으로 바꾸는 코드 (0) | 2023.11.21 |
Streamlit (파이썬 웹기반 시각화툴) (0) | 2023.11.14 |