의료 영상 처리(Medical Image Processing)를 시작할 때 가장 먼저 마주하는 장벽은 데이터 형식의 변환과 3차원 볼륨의 시각화입니다. 이번 포스팅에서는 실제 MRI 데이터(DICOM)를 3차원 볼륨(NIfTI)으로 변환하고, 이를 다양한 축(Axis)으로 잘라 2D 슬라이스 애니메이션(GIF)으로 만드는 과정을 정리합니다.
1. 필수 라이브러리 설치
의료 영상 처리를 위해 pydicom(DICOM 읽기), nibabel(NIfTI 읽기/쓰기), dicom2nifti(변환 도구), 그리고 시각화를
위한 matplotlib과 scikit-image를 설치합니다.
!unzip -q "/content/drive/MyDrive/.../brain_images.zip" # 데이터 압축 해제
!pip install scikit-image natsort pydicom nibabel dicom2nifti matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as anim
import numpy as np
import pydicom
import nibabel as nib
import dicom2nifti
from skimage.util import montage
from natsort import natsorted
from pathlib import Path
from IPython.display import Image as show_gif
2. DICOM 읽기 및 기본 탐색
먼저 DICOM 폴더 내의 이미지들을 자연어 정렬(natsorted)하여 로드합니다. 여러 장의 2D 슬라이스를 montage를 사용하여 한눈에 볼 수 있는 그리드 형태로 표현해 전체적인 형태를 파악합니다.
BASE_PATH = Path("/content/brain_images/00825/T2w")
dicom_images = natsorted(list(BASE_PATH.glob("*.dcm")))
# 모든 DICOM 파일의 픽셀 배열을 3차원 배열로 결합
concat_images = np.array([pydicom.dcmread(i).pixel_array for i in dicom_images])
# 3행 15열 그리드로 전체 슬라이스 미리보기
plt.figure(figsize=(10, 10))
plt.imshow(montage(concat_images, grid_shape=(3, 15)), cmap='bone')
plt.axis('off')
plt.show()

3. DICOM을 NIfTI(.nii.gz) 형식으로 변환
딥러닝 모델 학습 시에는 주로 NIfTI(Neuroimaging Informatics Technology Initiative) 형식을 사용합니다. dicom2nifti 라이브러리를 사용하여 DICOM 폴더를 NIfTI 파일로 변환합니다.
# DICOM 폴더를 NIfTI 형식으로 변환
dicom2nifti.convert_directory("/content/brain_images/00825/T2w", "./")
# 변환된 NIfTI 파일 로드
nifti_path = '/content/8_t2w.nii.gz'
sample_img = nib.load(nifti_path)
img_array = np.asanyarray(sample_img.dataobj)
print(f'Original NIfTI Shape: {img_array.shape}')
# 일반적으로 (height, width, depth) 형태를 가짐
4. 3D 볼륨 데이터 전처리 (축 변환)
NIfTI 파일의 차원 순서는 데이터 생성 도구나 저장 방식에 따라 다를 수 있습니다. 일반적으로 뇌 영상에서는 Z축(슬라이스 방향)이 마지막 차원이나 첫 번째 차원에 위치합니다. 시각화 및 모델 입력을 위해 차원 순서를 (depth, height, width)로 맞추기 위해 transpose를 사용합니다.
# 차원 순서 변경: (height, width, depth) -> (depth, height, width)
# transpose((2, 1, 0))은 Z축을 첫 번째 축으로 이동시킴
transpose_img = img_array.transpose((2, 1, 0))
print(f'Processed Shape: {transpose_img.shape}')
5. 3D 데이터를 2D 슬라이스 GIF로 시각화하기
3차원 뇌 영상은 고정밀도가 필요하므로, 슬라이스별로 이미지를 추출하여 애니메이션(GIF)으로 만드는 것이 효율적입니다. 아래 클래스는 matplotlib의 ArtistAnimation을 사용하여 슬라이스를 프레임별로 추가하고 GIF로 저장하는 역할을 합니다.
class ImageToGIF:
def __init__(self, size=(500, 500), xy_text=(80, 30), dpi=100, cmap='CMRmap'):
self.fig = plt.figure()
self.fig.set_size_inches(size[0] / dpi, size[1] / dpi)
self.xy_text = xy_text
self.cmap = cmap
self.ax = self.fig.add_axes([0, 0, 1, 1])
self.ax.set_xticks([])
self.ax.set_yticks([])
self.images = []
def add(self, image, label, with_mask=False):
plt.set_cmap(self.cmap)
plt_img = self.ax.imshow(image, animated=True)
plt_text = self.ax.text(*self.xy_text, label, color='red')
self.images.append([plt_img, plt_text])
plt.close()
def save(self, filename, fps):
animation = anim.ArtistAnimation(self.fig, self.images)
animation.save(filename, writer='imagemagick', fps=fps)
5-1. 축 방향 1: Z축 슬라이스 (Axial View)
가장 일반적인 단면인 축 방향(Axial) 슬라이스를 시각화합니다. transpose_img의 첫 번째 축(Depth)을 따라 순회하며 각 슬라이스를 GIF 프레임으로 추가합니다.

sample_data_gif = ImageToGIF()
label = nifti_path.replace("/", ".").split('.')[-2]
filename = f'{label}_axial.gif'
for i in range(transpose_img.shape[0]):
image = transpose_img[i]
sample_data_gif.add(image, label=f'{label}_{str(i)}')
sample_data_gif.save(filename, fps=15)
show_gif(filename, format='png')
결과 해석: 위 코드는 뇌의 위쪽에서 아래쪽(또는 그 반대)으로 슬라이스를 따라가며 단면을 보여주는 애니메이션을 생성합니다.
5-2. 축 방향 2: Z축 반대 방향 슬라이스 (Rotated View)
뇌 구조를 더 명확히 관찰하기 위해 이미지를 회전시켜 보는 경우도 있습니다. np.rot90을 사용하여 이미지를 180도 회전 시킨 후, 마지막 축(Width 또는 Height에 해당)을 따라 슬라이스를 자릅니다.
sample_data_gif = ImageToGIF()
label = nifti_path.replace("/", ".").split('.')[-2]
filename = f'{label}_rotated.gif'
# 마지막 축(2번 인덱스)을 따라 슬라이스
for i in range(transpose_img.shape[2]):
# 이미지를 180도 회전 (k=2: 90도 x 2회)
# axes=(1, 0): 0번과 1번 축을 기준으로 회전
image = np.rot90(transpose_img[..., i], k=2, axes=(1, 0))
sample_data_gif.add(image, label=f'{label}_{str(i)}')
sample_data_gif.save(filename, fps=15)
show_gif(filename, format='png')
결과 해석: 이 방식은 뇌의 좌우 대칭 구조나 특정 병변의 형태를 다른 각도에서 관찰할 때 유용합니다.

요약
- DICOM -> NIfTI 변환:
dicom2nifti라이브러리를 사용하여 의료 영상 표준 형식으로 변환합니다. - 차원 순서 조정:
transpose를 통해 모델 입력이나 시각화에 적합한(Depth, Height, Width)형태로 차원을 재배
열합니다. - 3D -> 2D 슬라이스 시각화:
matplotlib.animation을 활용하여 3D 볼륨 데이터를 2D 슬라이스 애니메이션(GIF)으로
변환합니다.shape[0]축 순회: 일반적인 Axial Viewshape[2]축 순회 + 회전: 변형된 단면 관찰
이 과정을 통해 복잡한 3D 의료 영상 데이터를 직관적으로 이해하고, 딥러닝 모델 학습 전 데이터의 품질을 확인할 수 있습니다.
'개념 정리 step2 > 메디컬 이미지' 카테고리의 다른 글
| [메디컬] 의료 인공지능을 위한 신호 처리 개념 정리 및 전처리 (0) | 2026.04.23 |
|---|---|
| [Technical Deep Dive] 메디컬 이미지 데이터의 이해와 Python DICOM 실습 (0) | 2026.04.05 |