< 4-7. Canny Edge Detection >
이번 챕터에서는
- Canny edge detection의 개념
- OpenCV의 cv2.Canny() 함수에 대해 볼 것이다.
Theory
Canny Edge Detection은 가장자리를 탐지하는 유명한 알고리즘이다. 1986년 canny에 의해서 개발되었다. 이는 다층 알고리즘이고, 각 층별로 봐볼 것이다.
1. Noise Reduction
가장자리 검출이 이미지 내의 노이즈에 영향을 받기 쉽기에, 첫 번째로 5x5 가우시안 필터로 이미지의 노이즈를 제거해준다. 이전 챕터에서 봤었던 내용이다.
2. Finding Intensity Gradient of the Image
Smoothened 이미지는 수평 및 수직 방향으로 Sobel 커널로 필터링하여 수평 방향(
gradient 방향은 항상 가장자리에 대해 수직이다. 이것은 수직,수평 그리고 두 개의 대각선을 나타내는 네 개의 각도 중 하나로 둥글게 되어 있다.
3. Non-Maximum Suppression
Gradient의 크기와 방향을 얻은 이후에, 가장자리를 구성하지 않는 원하지 않는 픽셀들을 제거하기 위해 이미지 전체 스캔이 진행된다. 이를 위해, 모든 픽셀에 대해, 픽셀은 gradient의 방향으로 인접한 지역들 사이에서 local maximum인지를 확인한다.
사진
점 A는 가장자리 위에 있다(수직 방향). Gradient 방향은 가장자리(Edge)에 대해 수직이다. 점 B와 C는 gradient 방향이다. 그래서 점 A가 local maximum인지 확인하기 위해 점B,C와 비교한다. 만약에 그렇다면, 다음 층으로 넘어가며, 아닐 경우 0으로 처리한다.
요약하자면, 얻는 결과는 “가는 가장자리”를 가진 이진 이미지이다.
4. Hysteresis Thresholding
이번 층에서는 모든 가장자리(이전의 결과)가 실제 가장자리인지 아닌지를 결정한다. 이를 위해, 두 가지 임계값minVal과 maxVal이 필요하다. intensity gradient가 maxVal보다 높은 경우 가장자리(Edge)이고, 낮은 경우 가장자리가 아니라고 판단한다. 이 두 개의 임계값 사이에 있을경우 그들의 연결성에 기반하여 가장자리인지 아닌지로 분류한다. 만약에 그것이 “가장자리” 픽셀과 연결되어있다면, 가장자리의 일부라고 판단될 것이다. 반대의 경우 버릴 것이다. 이미지를 보면 이해가 될 것이다.
사진
가장자리 A는 maxVal 위에 있기에, “가장자리”라고 판단된다. 비록 가장자리 C가 maxVal 아래에 있지만 가장자리 A와 연결되어 있기에 유효한 가장자리라고 판단하고 전체 커브를 가져가게 된다. 하지만 가장자리 B는 minVal 위에 있고 C와 같은 지역에 위치하지만, “실제 가장자리”와 연결되어있지 않아서 제거된다. 그래서 minVal과 maxVal을 선택하는 것이 정확한 결과를 얻는데 중요한 요소이다.
이번 층에서도 가장자리가 기다란 선이라는 가정하에 작은 픽셀 노이즈를 제거한다.
그래서 결국에는 이미지에서 강한 가장자리 부분만 얻게 된다!
Canny Edge Detection in OpenCV
OpenCV는 위의 과정을 하나의 함수인 cv2.Canny()에 담았다. 어떻게 사용하는지 봐보자! 처음 인자(argument)는 입력 이미지이다. 두 번째와 세 번째 인자는 각각 minVal과 maxVal이다. 네 번째 인자는 apeture_size이다. 이는 이미지 gradients를 찾기위해 사용되는 Sobel 커널의 사이즈이다. 기본적으로 3을 사용한다. 마지막 인자는 gradient 크기를 찾는걸 도와주는 식인, L2gradient이다. 이 인자가 True이면, 더 정확한 위에서 말한 식을 사용하고, False일 경우 다음의 함수를 사용한다.
img = cv2.imread('./images/soccer.jpg',0)
canny = cv2.Canny(img,100,300)
plt.figure(figsize=(12,8))
plt.subplot(1,2,1), plt.imshow(img,'gray')
plt.title('Original'), plt.axis('off')
plt.subplot(1,2,2), plt.imshow(canny,'gray')
plt.title('Canny Endge Detection'), plt.axis('off')
plt.show()
가장자리 부분만 검출된 것을 볼 수 있다.