수민 '-'

플오그래밍

제가 작성하는 모든 글은 절대 상업적인 이용이 아니며, 그저 개인적인 공부 용도로만 사용하는 것임을 밝힙니다.

병리 WSI 실습 - OpenSlide, read_region, 피라미드 레벨

WSI(Whole Slide Imaging)는 병리 슬라이드를 고배율로 스캔해 만든 기가픽셀급 이미지다. JPEG 한 장처럼 통째로 메모리에 올리기 어렵기 때문에, OpenSlide처럼 타일·피라미드 레벨 단위로 필요한 영역만 읽는 방식이 표준에 가깝다.

이번 글에서는 (1) GDC Data Portal 소개, (2) OpenSlide 설치·슬라이드 로드, (3) 메타데이터·레벨 정보 확인, (4) read_region으로 ROI 잘라보기까지 실습 코드를 정리한다.


1. GDC Data Portal

암 관련 공개 의료 데이터를 탐색·다운로드할 때 자주 쓰는 포털이다.

병리 WSI를 포함한 다양한 암 유전체·영상 데이터셋을 검색할 수 있다. 실습용 샘플은 강의 자료의 pathology_img.zip을 사용한다.


2. OpenSlide 설치 및 데이터 준비

!apt-get install openslide-tools
!pip install openslide-python
import os
import matplotlib.pyplot as plt
from pathlib import Path
from openslide import OpenSlide
from pprint import pprint
!unzip -q "/content/drive/MyDrive/랭체인 AI 영상객체탐지분석 플랫폼 구축/14. 메디컬 이미지/data/pathology_img.zip"
BASE_PATH = Path("/content/pathology_img")
path_img_path = list(BASE_PATH.glob("*/*"))[0]

slide = OpenSlide(path_img_path)
slide

OpenSlide는 SVS, NDPI, MRXS 등 WSI 포맷을 열고, 레벨별 해상도 정보와 함께 부분 영역만 읽어오는 API를 제공한다.


3. 슬라이드 기본 정보 확인

def show_path_info(slide):
    # 슬라이드의 전체 가로, 세로 크기를 출력
    print("Patient's dimentstions..:", slide.dimensions)
    # 슬라이드가 몇 개의 레벨을 가지고 있는지 출력
    # level0 ~ level3: 원본, 조금 축소, 더 축소, 가장 많은 축소
    print("Patient's z level:", slide.dimensions)
    # 각 레벨별 이미지 크기를 출력
    print("Patient's z dimentstion:", slide.level_dimensions)

print(f'file size: {round(os.path.getsize(path_img_path) / 1024 ** 2, 2)} MB')

show_path_info(slide)
출력 항목 의미
slide.dimensions level 0(최고 해상도) 기준 전체 가로·세로 픽셀 수
slide.level_count 피라미드 레벨 개수 (코드 주석: level0~level3)
slide.level_dimensions 레벨마다 (width, height) — 레벨이 올라갈수록 축소

파일 크기(MB)를 함께 보면, 왜 전체 이미지를 한 번에 로드하지 않는지 감이 잡힌다.


4. 메타데이터(properties) 확인

# properties: OpenSlide 슬라이드 객체의 메타데이터, 제조사, 해상도, 확대 비율, 촬영 장비 등
pprint(dict(slide.properties))

여기에는 스캐너 제조사, 목표 배율(objective power), MPP(microns per pixel), 타일 크기 등이 들어 있다. 전처리·스케일 보정·논문 재현 시 자주 참고한다.


5. read_region — ROI 잘라보기

read_region(location, level, size)level 0 좌표계에서 시작점 (x, y)를 잡고, 지정한 level에서 size 크기만큼 잘라온다. 반환 이미지는 RGBA다.

5-1. level 0, 256 x 256

# 시작 좌표(x, y)
region = (30000, 30000)
level = 0
size = (256, 256)
# read_region: 반환하는 이미지는 RGBA
region = slide.read_region(region, level, size)
plt.figure(figsize=(20, 20))
plt.imshow(region)

print(region.size)

5-2. level 0, 500 x 500 (다른 좌표)

region = (12000, 12000)
level = 0
size = (500, 500)
region = slide.read_region(region, level, size)
plt.figure(figsize=(20, 20))
plt.imshow(region)

5-3. level 3, 큰 타일

# level 0에서 읽는 것과 level 2에서 읽는 것은 보이는 실제 범위가 다를 수 있음
# level 2는 이미 축소된 레벨이기 때문
region = (10000, 10000)
level = 3
size = (2158, 2158)
region = slide.read_region(region, level, size)
plt.figure(figsize=(20, 20))
plt.imshow(region)

핵심은 다음과 같다.

  • 같은 location·size라도 level이 다르면 실제로 커버하는 조직 영역(물리적 범위)이 달라진다.
  • level 0: 최고 해상도, 디테일 확인·세밀 라벨링에 유리
  • level 3: 축소본, 넓은 맥락·저배율 탐색에 유리

6. WSI 처리 시 자주 쓰는 패턴

단계 도구/개념 역할
전체 구조 파악 낮은 level read_region 슬라이드 전역·병변 위치 대략 확인
학습용 패치 level 0 read_region + 타일링 CNN/ViT 입력 크기(예: 256, 512)로 crop
뷰어 QuPath, OpenSlide 기반 웹 뷰어 ROI 주석·QC
공개 데이터 GDC 등 암 병리·유전체 연계 연구

DICOM·NIfTI 실습과 달리, 병리 WSI는 좌표·레벨·MPP를 함께 관리하는 것이 파이프라인 설계의 출발점이다.


마치며

  • WSI는 파일이 크므로 OpenSlide로 필요한 영역만 읽는 방식이 기본이다.
  • dimensionslevel_dimensions로 피라미드 구조를 확인한 뒤, read_region으로 ROI를 잘라본다.
  • level을 바꾸면 해상도와 실제 조직 범위가 함께 바뀌므로, 학습·시각화 목적에 맞게 level을 선택해야 한다.
  • 다음에는 타일 단위 데이터셋 생성(좌표 샘플링, 증강, 라벨 마스크 정렬)까지 이어서 정리보면 디지털 병리 AI 파이프라인이 한층 명확해진다.

참고