Brain Tumor Radiogenomic Classification

[Brain Tumor] 대회의 DICOM 파일 확인 (EDA)

scone 2022. 10. 9. 15:46

다음 커널의 코드를 참고하였습니다.

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로 정보가 들어가 있습니다.

 

저희 데이터 안의 정보가 적은거 같아서 인터넷 검색 해보니깐

출처 : https://velog.io/@olxtar/Python-DICOM%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EA%B8%B0

다음과 같이 환자의 생일과 성별 등등의 정보들이 들어있는 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 ) 와 같이 시간 축에 따른 이미지 데이터가 나올 줄 알았는데

그냥 한 장짜리 이미지가 조회되네요..?

출처 : https://89douner.tistory.com/284?category=991951

위 스크린샷의 블로그 글 보니깐 image가 하나로만 구성될 수도 있다고 하네요.

 

아무래도 frame이 한장 한장 쪼개져서 폴더 안에 들어있는 모양입니다.

00002 번 환자의 FLAIR 사진들 129개

 

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)

https://pinkwink.kr/1090

 

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)

EDA with Animations and Modeling.ipynb - Untitled (Workspace) - Visual Studio Code 2022-10-09 15-40-24.mp4
5.26MB