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

10장. Sobel 과 Laplacian 경계 검출

가로 기울기와 세로 기울기

아파트 단지 지도에서 "동쪽으로 한 칸 가면 몇 층 높아지나"와 "남쪽으로 한 칸 가면 몇 층 높아지나"를 따로 적어 두면, 어느 방향으로 걷든 가파른 정도를 알 수 있습니다. 그림도 가로 방향의 변화(gx)와 세로 방향의 변화(gy)를 따로 잽니다. 가로로 빼면 세로로 선 경계가, 세로로 빼면 가로로 누운 경계가 드러납니다.

가로 기울기 gx 는 세로로 선 경계를, 세로 기울기 gy 는 가로로 누운 경계를 찾는다는 비교 그림

왼쪽 상자가 가로 기울기, 오른쪽 상자가 세로 기울기입니다. 빼는 방향과 찾아지는 선의 방향은 서로 직각입니다. 네모의 왼쪽 변은 세로로 서 있지만, 그 변을 가로질러 왼쪽에서 오른쪽으로 걸을 때 밝기가 바뀌므로 가로 기울기에서 드러납니다. 여기서 동쪽으로 한 칸이 gx, 남쪽으로 한 칸이 gy 입니다.

도형 그림의 원본, 가로 기울기의 절댓값, 세로 기울기의 절댓값을 나란히 놓은 그림

가운데 그림(|gx|)에는 네모의 왼쪽·오른쪽 변과 계단 띠의 세로 선이 밝게 나오고, 네모의 위·아래 변은 나오지 않습니다. 오른쪽 그림(|gy|)은 거꾸로 위·아래 변과 띠의 위·아래 끝만 나옵니다. 원과 세모의 비스듬한 변은 양쪽에 모두 조금씩 나옵니다. 이 그림은 다음 절에서 볼 Sobel 로 계산했지만, 어느 쪽 경계가 나오는지는 [-1, 0, 1] 과 같습니다.

두 방향의 차이 커널

견줄 것가로 기울기 gx세로 기울기 gy
커널[[-1, 0, 1]] (1줄 3칸)[[-1], [0], [1]] (3줄 1칸)
빼는 방향오른쪽 − 왼쪽아래 − 위
+ 가 나오는 곳오른쪽으로 갈수록 밝아질 때아래로 갈수록 밝아질 때
드러나는 경계세로로 선 경계가로로 누운 경계

짧은 예시

Python
import cv2
import numpy as np

img = cv2.imread("ch10_shapes.png", cv2.IMREAD_GRAYSCALE)

# 1줄 3칸짜리 차이 커널. .T(transpose, 뒤집어 세우기)로 3줄 1칸짜리를 만든다
kx = np.array([[-1, 0, 1]], dtype=np.float32)
ky = kx.T

# filter2D(그림, 결과 자료형, 커널): 결과를 소수(CV_64F)로 받아야 음수가 남는다
gx = cv2.filter2D(img, cv2.CV_64F, kx)
gy = cv2.filter2D(img, cv2.CV_64F, ky)
print(gx[80, 57:63].tolist())   # 결과: [0.0, 0.0, 150.0, 150.0, 0.0, 0.0] → 네모의 왼쪽 변
print(gy[37:43, 100].tolist())  # 결과: [0.0, 0.0, 150.0, 150.0, 0.0, 0.0] → 네모의 위 변

6장에서 본 cv2.filter2D 에 차이 커널을 넣었을 뿐입니다. 손계산의 150 이 그대로 나옵니다. .T 는 transpose(자리 바꾸기)를 줄인 이름으로, 가로로 누운 표를 세로로 세웁니다.

주의할 점

  • cv2.filter2D 의 둘째 인자를 -1 로 주면 결과가 원본과 같은 uint8 이 되어 음수가 0 으로 잘립니다. 기울기를 잴 때는 cv2.CV_64F 처럼 소수 자료형을 줍니다.
  • 6장에서 본 것처럼 cv2.filter2D 는 커널을 뒤집지 않고 그대로 겹쳐 곱합니다. 그래서 [-1, 0, 1] 은 정말로 "오른쪽 − 왼쪽"을 계산합니다.
← 이전 절10장 · 기울기: 옆 칸끼리 빼기다음 절 →10장 · Sobel 연산자