Edge Detection Filters

정예슬·2023년 12월 14일
0

vision

목록 보기
16/21
post-thumbnail

Edge란?

이미지에서 밝기 또는 색상이 급격하게 변하는 부분. 따라서 엣지를 찾는 가장 간단한 방법은 이미지를 “미분”하여 밝기(intensity)의 변화율(gradient)을 확인하는 것이다. gradient는 방향과 크기를 갖는 벡터(vector)로, 밝기가 변하는 방향(엣지의 방향)과 그 정도를 나타낸다.

이미지에서 엣지를 찾는 것은 컴퓨터 비전, 이미지 처리 분야에서 아주 중요하고 기초적인 단계라고 할 수 있다.


1. Laplacian filter

2차 미분을 사용하여 이미지의 경계를 검출한다.

Δf=2fx2+2fy2Δf=\frac{∂^2f}{∂x^2}+\frac{∂^2f}{∂y^2}

라플라시안 필터는 주로 다음과 같은 형태이다.

L=[010141010]L=\begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix} 또는 L=[010181010]L=\begin{bmatrix} 0 & 1 & 0 \\ 1 & -8 & 1 \\ 0 & 1 & 0 \end{bmatrix}

장점: 빠른 연산. 모든 방향 엣지를 잘 감지

단점: 노이즈에 매우 민감함


2. Sobel filter

x축 방향, y축 방향의 1차 미분(gradient)를 계산하여 이미지의 경계를 검출한다. Gaussian smoothing과 미분을 결합하여 노이즈에 강하다. (중간 행 또는 열이 더 큰 가중치를 가짐 → 가우시안 스무딩과 유사한 효과)

소벨 필터는 다음과 같은 형태이다.

  • x축 방향 소벨 필터

Gx=[10+120+210+1]G_x=\begin{bmatrix} -1 & 0 & +1 \\ -2 & 0 & +2 \\ -1 & 0 & +1 \end{bmatrix}

  • y축 방향 소벨 필터

Gy=[121000+1+2+1]G_y=\begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ +1 & +2 & +1 \end{bmatrix}

그래디언트 크기 (gradient magnitude) : Gx2+Gy2\sqrt{G^2_x + G^2_y}

그래디언트 방향 (gradient direction) : arctan(GyGx)arctan(\frac{G_y}{G_x})

장점: Laplacian에 비해 노이즈에 강하며, 수평/수직 방향 엣지를 잘 감지

단점: 대각선 방향 엣지 검출에 약함

  • 커널 계산 방법

    다음과 같은 3x3 픽셀 이미지가 있다고 하자. f=f =[123123123]\begin{bmatrix} 1 & 2 & 3 \\ 1 & 2 & 3 \\ 1 & 2 & 3 \end{bmatrix}

    각 위치에서 커널과 이미지의 해당 픽셀 부분을 곱한 후 결과를 모두 더한다.

    그러면 x축 방향 소벨 필터를 적용한다고 할 때, Gx=[10+120+210+1]G_x=\begin{bmatrix} -1 & 0 & +1 \\ -2 & 0 & +2 \\ -1 & 0 & +1 \end{bmatrix}이므로

    1x-1 + 2x0 + 3x1 + 1x-2 + 2x0 + 3x2 + 1x-1 + 2x0 + 3x1 = (-1) + 0 + 3 + (-2) + 0 + 6 + (-1) + 0 + 3 = (-4) + 12 = 8 이다. 이 값을 중앙 픽셀에 적용하면 된다.

    즉, x방향 소벨 필터 적용 결과는 f=[080080080]f’ = \begin{bmatrix} 0 & 8 & 0 \\ 0 & 8 & 0 \\ 0 & 8 & 0 \end{bmatrix}이 될 것이다. 같은 방식으로 y축 방향 소벨 필터 적용 결과를 구하면 f=[000000000]f’ = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix} 이 된다.


3. Scharr filter

sobel filter와 마찬가지로 x축, y축 방향 미분을 계산한다.

  • x축 방향 슈마르 필터

Gx=[30+3100+1030+3]G_x=\begin{bmatrix} -3 & 0 & +3 \\ -10 & 0 & +10 \\ -3 & 0 & +3 \end{bmatrix}

  • y축 방향 슈마르 필터

Gy=[31030003+10+3]G_y=\begin{bmatrix} -3 & -10 & -3 \\ 0 & 0 & 0 \\ -3 & +10 & +3 \end{bmatrix}

장점: Sobel filter와 유사하나, 더 정확한 gradient 계산 제공 (커널의 가중치가 edge direction에 대한 정확한 정보를 포착하는 데 더 적합하게 설계) → 고해상도 이미지에서 미세한 엣지를 정확히 검출하고자 할 때 사용

단점: Sobel filter에 비해 계산 비용이 높음


sobel filter와 유사하다. (커널 값 차이)

  • x축 방향 프리윗 필터

Gx=[+101+101+101]G_x=\begin{bmatrix} +1 & 0 & -1 \\ +1 & 0 & -1 \\ +1 & 0 & -1 \end{bmatrix}

  • y축 방향 프리윗 필터

Gy=[+1+1+1000111]G_y=\begin{bmatrix} +1 & +1 & +1 \\ 0 & 0 & 0 \\ -1 & -1 & -1 \end{bmatrix}


5. Roberts cross filter

대각선 방향 엣지에 민감하며, 2x2 커널을 사용하고 연산 속도가 빠르다.

R=[+10+01]R=\begin{bmatrix} +1 & 0 \\ +0 & -1 \end{bmatrix} 또는 R=[0+110]R=\begin{bmatrix} 0 & +1 \\ -1 & 0 \end{bmatrix}


6. Canny Edge

sobel filter와 NMS(Non-Maximum Supression)을 사용하여 더 선명한 엣지를 검출한다.

Gaussian Filter → gradient 계산(sobel filter 사용) → Non-Maximum Suppression → Double Thresholding → Hysteresis

Non-Maximum Suppression : 엣지가 아닌 픽셀을 제거한다. 각 픽셀에서 그래디언트 방향을 따라 그래디언트 크기가 local maximum 값인지 확인한다. local maximum이 아니면 엣지가 아니라고 판단하고 제거한다.

Double Tresholding : 강한 엣지와 약한 엣지 구분을 위해 두 개의 임계값을 설정한다. 강한 엣지는 높은 임계값보다 큰 그래디언트를 가진 픽셀, 약한 엣지는 두 임계값 사이의 그래디언트를 가진 픽셀이다.

Hysteresis ****: 약한 엣지 중 강한 엣지와 연결된 픽셀만 엣지로 간주한다. 이를 통해 false edge를 제거한다.


필터별 Edge 검출 결과 비교

# Laplacian filter
laplacian = cv2.Laplacian(img,cv2.CV_64F)
abs_laplacian = cv2.convertScaleAbs(laplacian)

# sobel filter
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
abs_sobelx = cv2.convertScaleAbs(sobelx)
abs_sobely = cv2.convertScaleAbs(sobely)
sobel_combined = cv2.addWeighted(abs_sobelx, 0.5, abs_sobely, 0.5, 0)

# scharr filter
scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1)
abs_scharrx = cv2.convertScaleAbs(scharrx)
abs_scharry = cv2.convertScaleAbs(scharry)
scharr_combined = cv2.addWeighted(abs_scharrx, 0.5, abs_scharry, 0.5, 0)

# prewitt filter
prewittx = np.array([[1, 0, -1], [1, 0, -1], [1, 0, -1]])
prewitty = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])

img_prewittx = cv2.filter2D(img, -1, prewittx)
img_prewitty = cv2.filter2D(img, -1, prewitty)

img_prewitt = img_prewittx + img_prewitty

## roberts filter
robertsx = np.array([[1, 0], [0, -1]])
robertsy = np.array([[0, 1], [-1, 0]])

img_robertsx = cv2.filter2D(img, -1, robertsx)
img_robertsy = cv2.filter2D(img, -1, robertsy)

img_roberts = img_robertsx + img_robertsy

# canny edge 
edges = cv2.Canny(img, 100, 200)
profile
춘식이랑 함께하는 개발일지

0개의 댓글