다음 커널의 코드를 참고하였습니다.
https://www.kaggle.com/code/ihelon/brain-tumor-eda-with-animations-and-modeling/notebook
🧠Brain Tumor🧠 - EDA with Animations and Modeling
Explore and run machine learning code with Kaggle Notebooks | Using data from multiple data sources
www.kaggle.com
pydicom으로 데이터 둘러보기
pydicom 설치
pydicom 을 설치해주었습니다.
pydicom이란 python으로 dicom 파일을 읽기 위한 모듈이라고 하네요.
requirement 들을 import 해줍니다.
train_label에는 다음과 같이 환자(고객) 번호와 MGMT 여부가 들어있습니다.
전체 총 585 명의 환자 데이터네요.
pydicom.dcmread()
pydicom의 dcmread를 사용하면 dicom의 데이터를 읽어드리게 됩니다.
저번 게시물에서 배운 DICOM 관련된 정보들이 눈에 들어옵니다.
Pixel은 보시다싶이 마지막에 Pixel Data 의 attribute로 정보가 들어가 있습니다.
저희 데이터 안의 정보가 적은거 같아서 인터넷 검색 해보니깐
다음과 같이 환자의 생일과 성별 등등의 정보들이 들어있는 dicom 파일도 있는 반면에 저희꺼는 좀 적게 들어있는게 맞는 것 같습니다.
dicom 파일의 특성 조회
다음과 같이 개별 특성 또한 조회해볼 수 있습니다.
이런 저런 시도 해보다가 나름의 규칙성을 찾았는데
가령 Patient's Name 이라는 특성을 보고 싶으면 PatientName 이라 치면 되고,
가령 Pixel Bandwidth 를 보고 싶으면 PixelBandwidth 를 치니 나왔습니다.
띄어쓰기 무시하고, 's 같은 거 무시하고 치니 나오네요.
그렇다면 Pixel data는!!!
pixel data 는 이렇게 찾는게 아니라 pixel_array 라고 쳐야 array 형태로 나오는 듯 했습니다.
pixel_array
512 x 512 짜리 이미지 입니다.
MRI 데이터여서 ( 96, 512, 512 ) 와 같이 시간 축에 따른 이미지 데이터가 나올 줄 알았는데
그냥 한 장짜리 이미지가 조회되네요..?
위 스크린샷의 블로그 글 보니깐 image가 하나로만 구성될 수도 있다고 하네요.
아무래도 frame이 한장 한장 쪼개져서 폴더 안에 들어있는 모양입니다.
pixel data 이미지로 확인
dicom의 pixel array는 int16으로 되어있는데요.
일반적인 영상 이미지가 uint8 로 되어있고 0 ~ 255의 범위를 가지고 있는 것과는 다릅니다.
따라서 이를 일반적인 이미지와 같게 만들어주기 위한 처리가 필요합니다.
먼저 pixel array의 모든 요소에서 min 값을 빼줍니다.
그러면 모든 요소가 0 ~ max 값 까지 나오겠죠?
이후 모든 요소를 max값으로 나눠줍니다. 그러면 모든 요소가 0 ~ 1 의 값으로 스케일링 될 것입니다.
이후 255를 곱해주면, 0 ~ 255의 값이 되고, 타입을 uint8로 바꿔주기에 문제가 없습니다.
이후 image show를 통해 이미지로 보여주면 됩니다.
잘못된 이미지를 가져온 모양입니다....
첫 번째 사진이어서 그런가..? 대충 중간 사진으로 다시 가져와볼게요.
우연의 일치인지 뭔지 모르겠는데 사진 고르는거 3번 시도 해서 마지막 시도에 뇌 사진이 나왔네요...
MGMT = 0 이미지와 MGMT = 1 이미지 확인
랜덤으로 사진들 몇개 뽑아서 더 관찰해보도록 하겠습니다.
앞서 사용한 코드를 함수화 시켜 주었습니다.
- 폴더 에서 사진 꺼내어 plt로 그려주는 함수
ㄱ. patient_path 는 train 이라는 폴더 안에 있는 brats21id ( 환자 식별 번호 ) 폴더 경로를 의미합니다.
환자 식별 번호는 위에서 봤듯이 0, 2, 3, 5, 6, ..... , 1005 등과 같이 그냥 숫자 형태로 쭉 있기 때문에 식별번호 5자리 숫자를 만들어주기 위해 zfill 함수로 앞을 0으로 채워주어야 합니다.
zfill(5) 이면 앞에 0을 채워서 5자리 숫자를 만들라는 의미인 것 같아요.
ㄴ. enumerate 는 인덱스와 value를 반환하는 함수입니다.
enumerate의 두 번째 인자에 1이 들어갔는데, 이는 인덱스값을 1부터 세라는 의미인 것 같네요.
만약 두 번째 인자가 안들어갔다면 i는 0부터 3까지를 순서대로 반환합니다.
ㄷ. glob.glob 함수는 파일의 이름을 가져오는 함수입니다.
glob.glob(os.path.join(patient_path, t, '*' )) 라고 하면 patient_path 안의 t 폴더 안에 있는 모든 파일 명을 가지고 오라는 의미라 볼 수 있겠습니다.
그리고 sorted 함수에서 key 값을 lambda x: int(x[:-4].split("-")[-1]) 이라고 두었네요.
파일 이름이 Image-386 이면 뒤의 숫자 386만 따로 꺼내 이를 기준으로 정렬시킨 것으로 보입니다.
ㄹ. data = load_dicom( t_paths[ int( len(t_paths) * slice_i ) ] )
가령 slice_i가 0.5 라면 파일 전체 목록 가운데 가운데 있는 파일을 0 ~ 255 의 픽셀 값으로 변환할 수 있을 것입니다.
- 그린 결과
대충 이렇습니다.
보고 MGMT value가 바로 뭐다라고 와닿지는 않는것 같습니다.
Matplotlib으로 에니메이션 표현하기; rc
- 쥬피터 노트북에 애니메이션을 보여주게 하는 코드
from matplotlib import animation, rc
rc('animation', html='jshtml')
- 에니메이션을 설정해주는 함수
ims는 파일들의 픽셀 배열들 리스트를 의미합니다.
def create_animation(ims):
fig = plt.figure(figsize=(6, 6))
plt.axis('off')
im = plt.imshow(ims[0], cmap="gray")
def animate_func(i):
im.set_array(ims[i])
return [im]
return animation.FuncAnimation(fig, animate_func, frames = len(ims), interval = 1000//24)
Matplotlib에서 그래프를 애니메이션으로 표현하기
Python이든 뭐든 데이터를 시각화하는 것은 항상 필요한 과정입니다. 그런데 그 데이터가 너무 길어 한 화면에 담아보면 구분이 되지 않거나, 시간의 흐름에 대해 약간 강조하고 싶다면 애니메이
pinkwink.kr
- imges 가져오기
def load_dicom_line(path):
t_paths = sorted(
glob.glob(os.path.join(path, "*")),
key=lambda x: int(x[:-4].split("-")[-1]),
)
images = []
for filename in t_paths:
data = load_dicom(filename)
if data.max() == 0:
continue
images.append(data)
return images
파일들이 들어있는 폴더의 주소를 넣어주면,
폴더 안의 모든 파일들에 대한 경로를 t_paths에 담고,
앞서 만든 함수 load_dicom으로 전처리한 각 파일의 이미지 픽셀 array를 imges에 하나하나 저장합니다.
검은 사진일 때는 max값이 0이므로 이는 제외하고 저장합니다.
images = load_dicom_line("./data/train/00000/T1wCE")
create_animation(images)
'Brain Tumor Radiogenomic Classification' 카테고리의 다른 글
[Brain Tumor] DICOM 파일이란? (1) | 2022.09.30 |
---|---|
[Brain Tumor] T1W, T2W, T1Gd, Flair 영상 비교 - 용어정리 2 (0) | 2022.09.29 |
[Brain Tumor] MRI, T1 강조, T2 강조 - 용어 정리 1 (0) | 2022.09.28 |
[Brain Tumor] 데이터 설명 (0) | 2022.09.28 |
[Brain Tumor] 대회 설명 (0) | 2022.09.28 |