[CV] Canny Edge Detection

Date:     Updated:

카테고리:

태그:


Main Reference:
- Canny Edge Detection Step by Step in Python — Computer Vision

📹 Introduction

Original Image Canny Edge Detection
1_image 1_OpenCV_Canny

Canny Edge Detectior는 1986년 Canny가 제안한 알고리즘이다. 생각보다 훨씬 오래된 알고리즘임에도 너무 잘 작동해서 깜짝 놀랐다. 사실 2D vision이라 하면 deep learning에 밀려난 뒷방 늙은이인 줄만 알았는데, vision을 공부하면 할 수록 굉장히 건방진 생각이었다는 반성을 하게된다. 아무튼 오늘은 내가 좋아하는 기차 사진으로 Canny Edge Detection 과정을 따라가 보자.


Algorithm

  1. Noise Reduction
  2. Gradient Calculation
  3. Non-Maximum Suppression
  4. Double Threshold
  5. Edge Tracking


📹 Noise Reduction

Original Image RGB to Gray Gaussian Blurring
train image gaussian

Canny Edge Detection은 gradient를 기반으로 작동하기 때문에 먼저 이미지를 흑백으로 바꿔줘야 한다. 또한 픽셀 단위에서 gradient 값을 다루므로 noise에도 취약하다. 따라서 gaussian blurring을 통해 이미지를 부드럽게 만들어 noise의 영향을 줄여준다. 현재 예시에서는 이미지의 사이즈가 커 blurring 효과가 잘 느껴지지 않는다. 하지만 성능에는 큰 차이를 보이기 때문에 굉장히 중요한 작업이다.


📹 Gradient Calculation

Blurred Image Gradient Intensity
gaussian sobel
\[dx = \begin{bmatrix} 1 & 0 & -1 \\ 2 & 0 & -2 \\ 1 & 0 & -1 \\ \end{bmatrix} \textbf{ , } dy = \begin{bmatrix} 1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1 \\ \end{bmatrix}\] \[\left| \textbf{G} \right| = \sqrt{I_{x}^{2} + I_{y}^{2}}\] \[\Theta (x, y) = \textbf{arctan}\left ( \frac{I_{y}}{I_{x}} \right )\]
  • gradient는 sobel operator를 이용
  • 픽셀 단위로 gradient의 크기, 방향을 계산
  • gradient의 방향은 이후 Non-Maximum Suppression 단계에서 사용


📹 Non-Maximum Suppression

Gradient Intensity Gradient Intensity
sobel edge

앞에서 구한 gradient intensity map을 보면 edge들이 굉장히 진하고 두껍다. 이게 어떤 의미인가 하면 오른쪽 그림처럼 하나의 edge가 여러 픽셀을 지나가는 상황이다. 정교한 탐지를 위해 하나의 edge는 하나의 픽셀단위로 지나다녔으면 좋겠다. 이를 위해 non-Maximum Suppression 과정을 수행한다.


direction

우선 하나의 가정이 필요한데, gradient의 방향은 위와 같이 4가지 방향으로만 존재한다. 얼핏 생각하면 과격한 가정이라 생각할 수 있는데, 어차피 Edge는 픽셀 단위로 지나기 때문에 합리적인 가정이다.


direction2

위와 같이 (i,j)픽셀에서 3pi/4 방향의 edge가 있다고 가정해보자. 먼저 (i,j)픽셀에서 edge의 방향은 gradient 방향에 수직한다는 것을 이해해야 한다. Gradient의 수학적 의미를 생각해보면 간단하다. Gradient vector는 해당 지점에서 가장 변화율이 큰 방향을 향한다. 그리고 Edge라는 것은 edge를 지날 때 값이 확 바뀌는 지점이라 정의했다. 따라서 (i,j)픽셀에서의 gradient는 edge와 수직인 방향을 향할 것이다.
이제 NMS 과정에 대해 이야기해보자. 우리가 원하는 것은 두꺼운 edge가 얇아졌으면 좋겠다는 것이다. 따라서 edge와 수직인 방향의 값들을 비교하여 나보다 작으면 0으로 압축해버린다. 그래야 edge의 두께가 얇아질 것이다. 위 그림을 예로 들면, edge방향인 파란색 박스가 아니라 edge방향과 수직인 좌측상단, 우측하단의 픽셀 값들과 비교한다는 것이다. 만약 해당 값들이 (i,j)픽셀의 값보다 작으면 0으로 값을 바꿔주고, (i,j)픽셀의 값보다 높은 값이 존재한다면 (i,j)픽셀의 값을 0으로 바꿔준다.


📹 Double Threshold

threshold

이제 edge의 두께는 균일하게 맞추었고, 필요없는 후보들을 제외하는 과정을 수행한다. 보통 이런 상황에서는 threshold값을 정해 해당 값보다 작으면 후보에서 제외시키는 방법을 사용하는데, canny detector는 특이하게도 2가지 threshold값을 사용한다. 작동 방식은 다음과 같다.

  • High threshold값보다 높은 edge 후보들은 유지한다. → A, B 유지
  • Low threshold값보다 작은 edge 후보들은 제외한다. → D 제외
  • 두 threshold 사이에 존재하는 edge 후보들은 high threshold값보다 높은 edge와 연결된 경우에만 유지한다. → C 유지 & E 제외


Before NMS After NMS + Double Threshold
sobel canny




📹 Edge Tracking

tracking

마지막으로 픽셀 단위로 존재하는 edge들을 연결하는 과정이다. 필요 없는 edge 후보들은 제외시키고, 실질적인 edge들만 서로 연결시켜주는 간단한 작업이다. 작동 방식은 다음과 같다. 왼쪽 그림처럼 해당 픽셀 주변에 살아남은 후보가 없을 경우 edge에서 제외시킨다. 반면 오른쪽 그림처럼 해당 픽셀 주변에 살아남은 후보가 하나라도 존재할 경우에는 edge로 확정한다.

Before Tracking After Tracking
canny OpenCV_Canny





📹 Results

Original Image Canny Edge Detection
image OpenCV_Canny


맨 위로 이동하기

Vision 카테고리 내 다른 글 보러가기

댓글 남기기