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

10장. Sobel 과 Laplacian 경계 검출

음수와 자료형

은행 통장에는 입금(+)과 출금(−)이 함께 적힙니다. 그런데 "0 원 아래는 적을 수 없는" 장부에 옮겨 적으면 출금 기록이 모두 0 원이 되어 사라집니다. 기울기도 밝아지는 경계는 +, 어두워지는 경계는 − 입니다. 0~255 만 담는 uint8 에 바로 담으면 − 값이 모두 0 이 되어 어두워지는 쪽 경계가 사라집니다.

CV_64F 로 계산, 음수와 양수가 함께 담김, 절댓값으로 뒤집기, uint8 로 담기의 네 단계 흐름도

그림의 네 단계가 기울기를 다루는 순서입니다. 먼저 소수(CV_64F)로 계산해 음수를 지키고, 그림으로 볼 때는 절댓값을 취해 모두 양수로 만든 뒤 0~255 에 담습니다. 여기서 통장의 입출금 기록이 CV_64F 의 기울기이고, "0 원 아래는 못 적는 장부"가 uint8 입니다.

도형 그림의 원본, uint8 로 받은 Sobel 가로 기울기, CV_64F 로 받아 절댓값을 취한 가로 기울기를 나란히 놓은 그림

가운데 그림은 결과 자료형을 uint8(cv2.CV_8U)로 받은 것입니다. 왼쪽에서 오른쪽으로 밝아지는 변(네모의 왼쪽 변, 원의 왼쪽 반)만 남고, 어두워지는 변(네모의 오른쪽 변, 원의 오른쪽 반)은 사라졌습니다. 오른쪽 그림은 CV_64F 로 받아 cv2.convertScaleAbs 로 절댓값을 취한 것으로, 양쪽 변이 모두 남았습니다.

결과 자료형 견주기

받는 법600 인 칸−600 인 칸쓸 곳
cv2.CV_8U (또는 -1)255 (넘쳐서 잘림)0 (음수라 잘림)쓰지 않는다
cv2.CV_64F600.0−600.0계산(크기, 방향, 임계값)
CV_64F → cv2.convertScaleAbs255255눈으로 보기, 저장
CV_64F → convertScaleAbs(alpha=0.25)150150255 를 넘는 값을 줄여서 보기

cv2.convertScaleAbs 는 칸마다 "배율(alpha)을 곱하고, 절댓값을 취하고, 0~255 로 잘라 정수로" 바꿉니다. 배율을 주지 않으면 1 이라 600 은 255 로 잘립니다. 0.25 를 주면 600 × 0.25 = 150 이 되어 잘리지 않습니다.

짧은 예시

Python
import cv2

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

# ddepth 로 CV_8U(uint8)를 주면 음수는 0, 255 넘는 값은 255 로 잘린다
as_u8 = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=3)
print(int(as_u8[80, 59]), int(as_u8[80, 140]))   # 결과: 255 0 → 오른쪽 변이 사라졌다

# CV_64F 로 계산한 뒤 convertScaleAbs: 절댓값을 취하고 0~255 로 담는다
gx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
shown = cv2.convertScaleAbs(gx)
print(int(shown[80, 59]), int(shown[80, 140]))   # 결과: 255 255 → 양쪽 변이 모두 남았다

# alpha: 먼저 곱할 배율. 600 × 0.25 = 150
print(int(cv2.convertScaleAbs(gx, alpha=0.25)[80, 140]))   # 결과: 150

주의할 점

  • 크기 합치기, 방향, 임계값 같은 계산은 `CV_64F` 그대로 합니다. convertScaleAbs 로 바꾼 그림은 255 에서 잘리고 부호도 잃었으므로, 보기와 저장에만 씁니다.
  • 5장에서 본 것처럼 cv2.convertScaleAbs 는 음수를 절댓값으로 바꿉니다. 밝기 조절에서는 이것이 문제였지만, 기울기에서는 바로 이 성질이 필요합니다.
← 이전 절10장 · Sobel 연산자다음 절 →10장 · 기울기의 크기와 방향