[영상처리 및 비전] Edge Detection 정리 - Gradient부터 Canny까지
이번 포스팅에서는 영상처리에서 가장 기본이 되면서도 중요한 주제인 Edge Detection에 대해 다뤄보려 한다. Edge는 이미지에서 객체의 경계를 나타내는 핵심 정보이며, 컴퓨터 비전의 거의 모든 분야에서 출발점이 되는 개념이다. 이번 글에서는 edge가 무엇인지부터 시작해서, 어떻게 검출하는지, 그리고 Canny edge detector까지 차근차근 알아보자.
1. Edge란 무엇인가?
Edge는 이미지에서 픽셀 값이 급격하게 변하는 지점을 의미한다. 사람이 사물을 인식할 때 윤곽선만 보고도 그것이 무엇인지 파악할 수 있는 것처럼, edge는 이미지의 매우 효율적인 표현 방식이다. 픽셀 전체보다 훨씬 적은 양의 정보로 장면의 핵심을 담을 수 있는 강력한 feature인 것이다.
그렇다면 이미지에서 edge는 왜 생기는 것일까? Edge는 다음 네 가지 요인에 의해 발생한다.
- Depth discontinuity (깊이 불연속) — 물체와 배경 사이의 거리 차이
- Surface normal discontinuity (표면 법선 불연속) — 면의 방향이 꺾이는 부분
- Surface color discontinuity (표면 색상 불연속) — 색이 바뀌는 부분
- Illumination discontinuity (조명 불연속) — 그림자 경계 등
즉, edge는 단순히 "색이 바뀌는 곳"이 아니라 다양한 물리적 원인으로 발생하는 신호인 셈이다.
2. Edge를 수학적으로 어떻게 정의할까?
이미지의 한 행을 가로로 잘라 intensity 값을 그래프로 그려보면, edge가 있는 지점에서 값이 급격하게 변한다. 이 "급격한 변화"를 수학적으로 어떻게 잡아낼 수 있을까?
정답은 미분이다. 함수가 급격하게 변하는 지점은 곧 1차 미분 값이 극값(extrema)을 가지는 지점이다. 따라서 이미지를 미분해서 그 결과가 큰 지점을 찾으면 그것이 바로 edge가 된다.
3. 디지털 이미지를 어떻게 미분할까?
연속 함수와 달리 이미지는 픽셀 단위로 이산적(discrete)이다. 그래서 미분도 근사식으로 처리한다.
∂f∂x[x,y]≈F[x+1,y]−F[x,y]\frac{\partial f}{\partial x}[x, y] \approx F[x+1, y] - F[x, y]
이를 linear filter로 구현하면 다음과 같다.
- x방향 미분: Hx=[1,−1]H_x = [1, -1]
- y방향 미분: Hy=[−1,1]TH_y = [-1, 1]^T
이 필터를 이미지에 적용하면 어떻게 될까? 검은 사각형 이미지에 HxH_x 를 적용하면 수직 방향의 edge(좌우 경계)만 검출되고, HyH_y 를 적용하면 수평 방향의 edge(상하 경계)만 검출되는 결과를 얻게 된다. 각 필터는 해당 방향의 변화량만 측정하기 때문이다.
4. Image Gradient — 방향과 크기를 모두 담다
x방향 변화량과 y방향 변화량을 함께 묶으면 gradient vector가 된다.
∇f=[∂f∂x,∂f∂y]\nabla f = \left[\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}\right]
이 gradient vector는 intensity가 가장 빠르게 증가하는 방향을 가리킨다. 그리고 두 가지 중요한 정보를 추출할 수 있다.
Edge의 강도(strength) — gradient의 크기:
∥∇f∥=(∂f∂x)2+(∂f∂y)2\|\nabla f\| = \sqrt{\left(\frac{\partial f}{\partial x}\right)^2 + \left(\frac{\partial f}{\partial y}\right)^2}
Edge의 방향 — gradient의 각도:
θ=tan−1(∂f∂y/∂f∂x)\theta = \tan^{-1}\left(\frac{\partial f}{\partial y} \bigg/ \frac{\partial f}{\partial x}\right)
여기서 한 가지 짚고 넘어갈 점이 있다. Gradient 방향과 edge 방향은 서로 수직이다. 직관적으로 생각해보면, 절벽이 있을 때 절벽이 뻗은 방향(edge)과 절벽을 가로질러 올라가는 방향(gradient)은 90도 차이가 난다. 이 관계는 뒤에 NMS에서도 핵심적으로 쓰인다.
5. Noise라는 복병
이론은 깔끔하다. 그런데 실제 이미지에 그냥 미분을 적용하면 어떻게 될까?
결과는 참담하다. Noise가 조금만 있어도 미분 결과는 완전히 난장판이 된다. 이유는 간단하다. 미분은 변화량을 측정하는 연산이기 때문에, noise처럼 픽셀마다 작게 들쭉날쭉한 변화도 모두 신호로 잡아내 증폭시켜버린다. 결국 진짜 edge의 큰 변화가 noise의 작은 변화들 사이에 묻혀버리게 된다.
이 문제를 어떻게 해결할 수 있을까?
6. Solution: Smooth First
해결책은 의외로 간단하다. 미분하기 전에 먼저 smoothing을 해서 noise를 죽이는 것이다. Gaussian filter로 이미지를 부드럽게 만든 뒤 미분하면, noise는 평균화되어 사라지고 진짜 edge만 깔끔한 봉우리로 남게 된다.
순서를 정리하면 이렇다.
- 이미지 ff 에 Gaussian hh 를 conv → f∗hf * h (smoothing)
- 그 결과를 미분 → ddx(f∗h)\frac{d}{dx}(f * h) (edge 검출)
이렇게 한 결과, noise가 없는 깔끔한 edge 신호를 얻을 수 있게 된다. 물론 부작용으로 edge도 살짝 뭉개지지만, noise에 묻혀 아예 못 찾는 것보다는 훨씬 낫다.
7. 핵심 트릭: Convolution의 Associative Property
여기서 매우 중요한 수학적 성질이 등장한다. Differentiation 자체가 convolution이고, convolution은 결합법칙(associative)을 만족한다.
ddx(f∗h)=f∗ddxh\frac{d}{dx}(f * h) = f * \frac{d}{dx}h
이게 왜 중요할까? 원래대로라면 smoothing 한 번, 미분 한 번 해서 conv를 두 번 해야 한다. 하지만 이 성질을 이용하면 Gaussian을 미리 미분해둔 커널(ddxh\frac{d}{dx}h , 즉 Derivative of Gaussian, DoG)을 만들어서 이미지에 한 번만 conv하면 된다. 결과는 똑같은데 계산은 절반이다.
이 DoG 커널이 바로 뒤에 나올 Sobel operator의 기반이 된다.
8. Sobel Operator
Sobel operator는 Derivative of Gaussian의 가장 대표적인 근사 필터다.
sx=18[−101−202−101],sy=18[121000−1−2−1]s_x = \frac{1}{8}\begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix}, \quad s_y = \frac{1}{8}\begin{bmatrix} 1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1 \end{bmatrix}
여기서 한 가지 주의할 점이 있다. 표준 Sobel 정의에서는 1/8 항을 생략하는 경우가 많은데, edge detection 자체에는 영향이 없지만 정확한 gradient 값을 얻으려면 1/8 항이 반드시 필요하다. 단순히 edge 위치만 찾는다면 무시해도 되지만, gradient의 절대적 크기가 의미 있는 작업에서는 빼먹으면 안 된다.
Sobel 필터를 적용하면 sxs_x 는 수직 edge를, sys_y 는 수평 edge를 검출하고, 둘의 magnitude를 합치면 모든 방향의 edge를 담은 gradient magnitude 이미지를 얻을 수 있게 된다.
9. Laplacian of Gaussian (LoG)
지금까지는 1차 미분 이야기였다. 그렇다면 2차 미분으로는 어떻게 edge를 찾을 수 있을까?
1차 미분이 edge에서 peak를 만든다면, 2차 미분은 edge에서 zero-crossing(부호가 바뀌는 0 지점)을 만든다. Step edge에 2차 미분을 적용하면 양수로 솟았다가 음수로 떨어지는데, 그 사이 0을 지나는 정확한 지점이 edge의 위치가 된다.
이때 사용하는 필터가 바로 **Laplacian of Gaussian (LoG)**이다. Gaussian으로 smoothing하면서 동시에 2차 미분을 수행하는 결합 필터로, 가운데가 음수이고 주변이 양수인 멕시칸 햇(mexican hat) 모양을 가진다.
10. DoG와 LoG를 함께 쓰면?
여기서 흥미로운 통찰이 등장한다.
Gradient magnitude(DoG 계열)가 크고, 2차 미분(LoG)이 0인 픽셀이 edge다.
DoG만 쓰면 edge가 두껍게 검출되고, LoG만 쓰면 noise 영역에서도 zero-crossing이 생겨 false edge가 나온다. 그런데 둘을 AND로 결합하면 어떻게 될까? 두 조건을 모두 만족하는 픽셀만 남게 되어 매우 정확한 edge map을 얻을 수 있게 된다.
11. 그래도 남는 문제 — Edge가 두껍다
Gradient magnitude를 thresholding해서 얻은 edge 이미지를 자세히 보면, edge가 한 픽셀 두께가 아니라 여러 픽셀에 걸쳐 두꺼운 띠 형태로 나타난다. 진짜 edge는 딱 한 줄이어야 하는데 말이다.
이 문제를 어떻게 해결할 수 있을까?
12. Non-Maximum Suppression (NMS)
해결책은 Non-Maximum Suppression이다. 이름 그대로 "최대값이 아닌 것은 억제한다"는 뜻이다.
원리는 이렇다. 각 픽셀에서 gradient 방향을 따라 양옆 두 픽셀을 본다. 그리고 자기 자신이 그 셋 중 가장 큰 값이면 살리고, 아니면 0으로 만들어버린다.
왜 gradient 방향으로 비교할까? 앞서 말했듯 edge는 gradient에 수직이다. 따라서 gradient 방향을 따라가면 edge를 가로지르는 셈이고, 그 단면에서 가장 뾰족한 봉우리(peak)만 남기면 edge가 1픽셀 두께로 얇아진다.
여기서 한 가지 문제가 있다. Gradient 방향이 정확히 수평이나 수직이 아니라면, 비교해야 할 두 픽셀이 격자 위에 정확히 놓여 있지 않다. 이 경우 주변 픽셀들의 값을 interpolation(보간)해서 추정해야 한다. (이 부분은 다음 강의에서 자세히 다룰 예정이다.)
NMS를 적용한 결과, 두꺼웠던 edge가 깔끔한 1픽셀 두께의 선으로 정리되는 효과(thinning)를 얻을 수 있게 된다.
13. Hysteresis Thresholding
NMS로 edge를 얇게 만들었다고 끝이 아니다. 단일 threshold로 edge를 결정하면 또 다른 문제가 생긴다. Threshold를 높게 잡으면 진짜 edge의 약한 부분이 끊어지고, 낮게 잡으면 noise까지 edge로 잡힌다.
이 딜레마를 어떻게 풀 수 있을까?
답은 두 개의 threshold를 사용하는 것이다. 이를 hysteresis thresholding이라고 한다.
- High threshold 이상 → 확실한 edge로 인정 (시작점)
- Low threshold ~ High threshold 사이 → "약한 edge". 강한 edge와 연결되어 있으면 살리고, 아니면 버림
- Low threshold 미만 → 무조건 버림
예를 들어 강한 edge A에서 출발해서 따라가다가 약한 부분 C를 만났다면, C는 살려둔다. 반면 어디에도 연결되지 않고 혼자 떠 있는 약한 edge B는 noise로 간주해서 버린다. 이렇게 하면 진짜 edge의 약한 부분은 보존하면서 noise는 효과적으로 걸러낼 수 있게 된다.
14. 모든 걸 합치면 — Canny Edge Detector
지금까지 배운 모든 개념을 하나로 묶은 것이 바로 그 유명한 Canny edge detector다. 1986년 J. Canny가 제안한 이 방법은 지금까지도 컴퓨터 비전에서 가장 널리 쓰이는 edge detector 중 하나다.
전체 파이프라인은 다음과 같다.
- Filter image with derivative of Gaussian — DoG로 noise 제거하면서 gradient 계산
- Find magnitude and orientation of gradient — gradient의 크기와 방향 계산
- Non-maximum suppression — edge를 1픽셀 두께로 얇게
- Linking and thresholding (hysteresis) — 두 threshold로 진짜 edge만 남기기
Canny detector는 세 가지 파라미터에 의해 동작이 결정된다.
- σ\sigma : Gaussian blur의 폭
- High threshold
- Low threshold
특히 σ\sigma 의 선택이 결과에 큰 영향을 미친다. σ\sigma 가 작으면 작은 디테일까지 edge로 잡히고, σ\sigma 가 크면 큰 scale의 윤곽선만 검출되는 결과를 얻게 된다. 같은 이미지라도 σ=1\sigma=1 과 σ=2\sigma=2 로 처리한 결과는 전혀 다른 느낌을 준다. 어떤 scale의 edge를 원하는지에 따라 적절히 조절해야 한다.
15. 마치며 — 그리고 그 너머
지금까지 살펴본 방법들은 모두 수작업으로 설계된(hand-crafted) 필터에 기반한다. 그렇다면 최근에는 어떤 방식을 쓸까?
요즘은 딥러닝 기반의 edge detection이 많이 사용된다. 2017년 발표된 CASENet 같은 모델은 ResNet 기반의 deep network로 카테고리 정보까지 담은 semantic edge를 검출한다. 단순히 "여기 edge가 있다"가 아니라 "여기는 building과 road의 경계다"처럼 의미를 함께 출력하는 것이다.
하지만 그렇다고 해서 Canny가 의미 없어진 건 아니다. Canny는 여전히 빠르고, 학습 데이터가 필요 없으며, 해석 가능한 강력한 기본 도구다. 딥러닝 모델의 전처리나 후처리에 활용되기도 하고, 임베디드 환경처럼 연산 자원이 제한된 곳에서는 필수 도구로 쓰인다.
정리
이번 포스팅을 한 줄로 요약하면 이렇다.
Edge는 이미지의 미분으로 찾을 수 있지만, noise를 다루기 위해 Gaussian smoothing과 결합한 DoG/LoG를 사용하고, NMS와 hysteresis thresholding을 거쳐 깔끔한 edge map을 얻는다. 이 모든 과정을 묶은 것이 Canny edge detector다.
Edge detection은 영상처리의 가장 기본 주제이지만, 그 안에 미분, convolution, noise 처리, thresholding 등 핵심 개념들이 모두 녹아 있다. 이 파이프라인을 제대로 이해해두면 이후 feature detection, contour, segmentation 같은 주제로 넘어갈 때 훨씬 수월해질 것이다.
다음 포스팅에서는 NMS에서 잠깐 언급했던 interpolation에 대해 더 자세히 다뤄볼 예정이다.