OpenCV 비전 실무10장 · Sobel 과 Laplacian 경계 검출4 / 21← 이전목차다음 →MetaContents

10장. Sobel 과 Laplacian 경계 검출

기울기: 옆 칸끼리 빼기

산길을 걸을 때 "한 걸음에 몇 cm 오르는가"를 재면 길이 얼마나 가파른지 알 수 있습니다. 평지에서는 0cm, 완만한 비탈에서는 조금, 계단에서는 한 걸음에 크게 오릅니다. 그림에서는 한 걸음이 옆 칸 하나입니다. 오른쪽 칸의 밝기에서 왼쪽 칸의 밝기를 빼면 "한 칸 옮길 때 밝기가 얼마나 바뀌나"가 나옵니다. 이 값이 변화량이고, 변화량으로 잰 가파른 정도를 기울기라고 부릅니다.

![한 줄의 밝기 50, 50, 50, 200, 200 과, 옆 칸 빼기 결과, [-1, 0, 1] 커널 결과를 위아래로 놓은 계산 그림](assets/img/diagram/ch10_diff_calc.svg)

맨 위 줄이 밝기 다섯 칸입니다. 가운데 줄은 옆 칸끼리 뺀 값으로, 칸과 칸 사이마다 하나씩 나옵니다. 50 과 50 사이는 0, 50 과 200 사이만 150 입니다. 아래 줄은 다음에 볼 [-1, 0, 1] 커널의 결과로, 칸마다 "오른쪽 이웃 − 왼쪽 이웃"을 적습니다. 여기서 한 걸음이 옆 칸 하나이고, 한 걸음에 오른 높이가 변화량입니다. 수학에서는 이런 계산을 미분이라고 부르지만, 이 과정에서는 "변화량을 재는 계산"이라고만 생각하면 됩니다.

손으로 계산하기

칸 번호01234
밝기505050200200
옆 칸 빼기 (오른쪽 − 자기)50 − 50 = 050 − 50 = 0200 − 50 = 150200 − 200 = 0(오른쪽 없음)
[-1, 0, 1] (오른쪽 − 왼쪽)(왼쪽 없음)50 − 50 = 0200 − 50 = 150200 − 50 = 150(오른쪽 없음)

옆 칸 빼기는 칸 2 에서만 150 이고, [-1, 0, 1] 은 칸 2 와 칸 3 두 칸에서 150 입니다. [-1, 0, 1] 은 자기 칸을 건너뛰고 양옆을 빼므로, 경계를 사이에 둔 두 칸이 모두 큰 값을 받습니다. 경계는 그 두 칸 사이에 있습니다. 거꾸로 200 에서 50 으로 떨어지는 곳이면 값이 −150 이 됩니다. 부호는 밝아지는지(+) 어두워지는지(−)를 알려 줍니다.

짧은 예시

Python
import numpy as np

row = np.array([50, 50, 50, 200, 200])

# np.diff: 옆 칸끼리 뺀 값(오른쪽 − 왼쪽)을 돌려준다. 칸이 하나 줄어든다
print(np.diff(row).tolist())            # 결과: [0, 0, 150, 0]

# [-1, 0, 1] 을 손으로: 칸마다 오른쪽 이웃 − 왼쪽 이웃
print((row[2:] - row[:-2]).tolist())    # 결과: [0, 150, 150] → 칸 1, 2, 3 의 값

np.diff 의 diff 는 difference(차이)를 줄인 이름입니다. row[2:] - row[:-2] 는 "두 칸 오른쪽으로 민 줄"에서 "원래 줄"을 빼서, 칸마다 양옆의 차이를 한 번에 구합니다.

주의할 점

  • 그림에서 바로 꺼낸 줄은 uint8 입니다. uint8 끼리 빼서 음수가 되면 1장에서 본 시계 바늘처럼 돌아가, 50 − 200 이 106 이 됩니다. 빼기 전에 astype(int) 로 바꿉니다. 실습 1에서 직접 봅니다.
  • 변화량은 "얼마나 밝은가"가 아니라 "얼마나 바뀌나"입니다. 50 → 200 과 100 → 250 은 밝기가 달라도 변화량은 똑같이 150 입니다.
← 이전 절10장 · 경계란 무엇인가다음 절 →10장 · 가로 기울기와 세로 기울기