3. 기타 등등

[영상처리] 안저 영상(Fundus Image)에서 심플하게 시신경유두(Optic Disc) 찾기

M_AI 2021. 5. 31. 21:34


안녕하세요! M_AI 입니다!

이번 포스팅은 딥러닝 모델이 아닌, 그냥 안저 영상(fundus image)에서 간단하게 시신경유두(optic disc, OD)를 찾는 방법을 알려드리고자 합니다!

사실 제 학사 학위 논문 주제가 당뇨망막병증 안저 영상(diabetic retinopathy fundus image)에서 삼출물(exudates)를 찾는 것인데, 여기서 삼출물이 밝다는 특성을 이용하여 추출하고자 하였습니다. 하지만 이 과정에서 가장 큰 걸림돌이 다름이 아닌 optic disc인데, 이 optic disc 또한 fundus image에서 매우 밝아 이를 찾아서 제거할 필요가 있었습니다.

그래서 본인은 optic disc의 위치를 찾는 방법을 구글링을 했는데

그 방법들이 어마어마하더라구요.

처음에는 Optic disc 마스크가 있는 데이터셋으로 optic disc만 추출하도록 U-Net으로 학습하여 뽑아서 제거하려 했으나,

배보다 배꼽이 더 커질 것 같아 해당 방법은 제외하였습니다.

그래서 구현하기도 쉽고, 이해하기도 쉬운 방법을 하나 택하였습니다.

해당 방법은 "Locating the Optic Disc in Retinal Images Using Morphological Techniques" 라는 논문에서 소개된 방법을 설명하고자 합니다!

이름에서도 알 수 있듯이 모폴로지를 이용하여 OD를 찾고자 하는 건데, 이 과정을 설명을 드리고자 합니다


본 게시글의 목적

※ 본 게시글은 상세한 이론적 설명보다는 코드 분석하고 이해하는 데에 목적에 있습니다!
※ 상세한 이론을 원하면 다른 곳에서 찾아보시길 바랍니다!


본 게시글의 특징

① Langauge : Python 3
② Library : OpenCV 4
③ Dataset : IDRiD
( 데이터셋 출처 : https://drive.grand-challenge.org/)

DRIVE - Grand Challenge

Develop a system to automatically segment vessels in human retina fundus images.

drive.grand-challenge.org

원래 논문에서는 MESSIDOR 데이터셋을 사용하였지만 본인은 학사 논문 연구에 사용한 데이터셋을 중점으로 설명할 예정입니다.
⑤ 게시글에서는 반말


1. Y 채널에서 배경 제거

1.1. Y채널

기본적으로 해당 방식은 optic disc가 밝다는 것에서 기인한다. 그러므로 원본 이미지 RGB 채널에서 바로 추출하기 보다는, YUV 채널로 변경 후 밝기를 의미하는 Y채널에서 진행한다.

그래서 파이썬에서 OpenCV를 활용하여 Y채널만 뽑아본다.

# 1. Y channel img = cv2.resize(img, dsize=(img.shape[0], img.shape[1]), interpolation=cv2.INTER_AREA) yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV) Y, U, V = cv2.split(yuv_img) Y_img = Y



Figure 1-1. 원본 영상
Figure 1-2. Y채널 영상



1.2. 배경 제거

해당 논문에서 Background라고 표현하여 이를 그대로 번역하면 배경이기에 그냥 배경이라고 표현하겠다.

여기서 배경이란, Y채널 영상에서 평균값 필터(mean filter)로 흐리게(blurring)만든 영상이다. 여기서 blurring한다는 의미는 엣지(edge) 정보를 제거한다는 것인데, 즉, 배경 정보만 남기겠다는 의미이다. 필터 사이즈로는 논문에서는 69 x 69로 나와있지만 본인은 원본 영상으로 256 x 256 으로 리사이즈하였기에, 필터 사이즈를 31 x 31로 하였다.

해당 과정은 다음과 같다.

- Y채널 영상에서 31 x 31 크기의 mean filter로 blurring한다.
- Y채널 영상에서 배경 영상을 뺀다.
- 배경을 제거한 영상의 픽셀값은 매우 작아 어둡기 때문에, 픽셀값을 [0, 255]로 Histogram equilization을 통하여 선형 변환한다.

# 2. 배경 제거 No_BG_img = cv2.addWeighted(Y_img, 1, cv2.blur(Y_img, 31) , -1, 0) No_BG_img = cv2.equalizeHist(No_BG_img)


Figure 2-1.  배경 영상
Figure 2-2. 배경 제거 후, HE한 영상



2. 원형 커널 모폴로지 후 가장 밝은 부분 찾기

이제 배경을 제거한 영상에서 모폴로지를 진행하는데, 여기서 모폴로지를 열기(opening)과 닫기(closing)을 사용한다. 사용할 커널 형태는 원형이다. 그러한 이유는 optic disc 형태가 원형이기 때문에 이 형태에 맞춰주기 위해서 원형 커널로 열기, 닫기를 반복한다.

열기는 경계선 밖으로 튀어나온 부분을 제거하여 부드럽게하며, 닫기는 경계선에서 들어간 부분을 채움으로써 부드럽게 만든다.

논문에서는 반복횟수를 4번으로 하여, 각 반복 때마다 사용되는 원의 반지름 크기는 2, 4, 6, 8이다.

하지만 논문대로 진행한 결과, 모폴로지 후 가장 밝은 부분을 여러 개를 찾거나, 객체 자체가 모두 사라지는 경우가 발생하여 유동적으로 설정해야만 했다.

이를 위해서 반복 횟수를 달리하여 실험한 결과, 최대 10번을 진행해야만 안정적으로 최댓값 1개를 찾을 수가 있었다.

물론 10번을 반복하면 객체가 모두 사라지는 경우가 있기 때문에, 그러한 경우를 대비하여 반복 횟수를 하나씩 줄여나가며 다시 모폴로지를 진행한다.

(이러한 방식으로 진행한 이유는, 여러 데이터에 적용하기 위해서 시간이 조금 더 걸리더라도 자동적으로 처리해야만 했다.)

def Morphology(image, n): for a in range(1, n+1): radius = a * 2 kernal = np.zeros( (radius*2, radius*2), dtype='uint8' ) cv2.circle(kernal, (radius, radius), radius, 1, -1) image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernal) image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernal) return image iter = 10 Moph_img = Morphology(No_BG_img, iter) while(Moph_img.argmax() == 0): iter -= 1 Moph_img = Morphology(No_BG_img, iter)


해당 모폴로지 과정의 영상 Figure 3은 해당 논문에서 발췌하였다. Figure 3과 같이 열기와 닫기를 반복하다보면, 원형인 optic disc가 원형 형태를 갖추며, 여기서 가장 밝은 부분이 optic disc의 위치를 의미한다.

Figure 3. 4번의 모폴로지 열기, 닫기 연산 과정 영상 (출처 :  Locating the Optic Disc in Retinal Images Using Morphological Techniques)



더 나아가서 가장 밝은 부분 위치에 optic disc의 크기의 원 모양으로 표기를 하면 Figure 4와 같이 optic disc 마스크 영상이 된다.

Figure 4-1. 원본 영상
Figure 4-2. Optic Disc 마스크 영상


이렇게 위와 같은 방법을 진행하면 손쉽게 optic disc를 찾을 수가 있다.


하지만 여기서 질문!

무조건 다 통용 되나요?

라고 한다면 저는

아니요!

라고 답을 하겠다.

그러한 이유는 위에서 optic disc는 밝다는 특징을 가졌다고 하였는데, 만약 optic disc처럼 원형이고 더 밝은 값을 지닌 당뇨망막병증의 삼출물(diabetic retinopathy exudates)가 있으면 위의 방법이 통용 안 될 확률이 매우 높다.

그러니 이 점을 찾고하여, 정상인 데이터나 exudates가 작은 데이터에서 사용하길 바란다.

더 좋은 방법을 원한다면 그냥 optic disc mask가 있는 데이터셋으로 segmentation 모델을 학습하여 사용하는 것을 가장 추천한다!