OpenCV 비전 실무5장 · 영상 향상과 학습용 전처리5 / 21← 이전목차다음 →MetaContents

5장. 영상 향상과 학습용 전처리

대비 조정

고무줄에 점을 몇 개 찍어 두고 양쪽으로 당기면, 점 사이의 거리가 모두 같은 비율로 벌어집니다. 칸의 밝기에 1 보다 큰 수를 곱하는 것이 이와 같습니다. 100 과 160 은 60 차이였지만, 1.5 를 곱하면 150 과 240 으로 90 차이가 됩니다. 밝은 곳과 어두운 곳의 차이, 곧 대비가 커집니다.

곱하기 alpha, 더하기 beta, 0~255 로 맞추기의 세 단계 흐름도

그림의 세 단계가 대비 조정 식 g = alpha × f + beta 입니다. f 는 원래 밝기, g 는 바뀐 밝기입니다. 먼저 alpha 를 곱해 차이를 넓히고, beta 를 더해 전체 밝기를 맞추고, 0~255 를 벗어난 값을 끝 값으로 맞춥니다. 여기서 고무줄을 당기는 힘이 alpha, 고무줄을 통째로 옆으로 옮기는 것이 beta 입니다.

alpha 와 beta 를 바꾼 네 가지 선으로 입력 밝기가 출력 밝기로 바뀌는 모습을 그린 그래프

가로축이 원래 밝기 f, 세로축이 바뀐 밝기 g 입니다. 초록 선(alpha 1, beta 0)은 그대로입니다. 갈색 선은 beta 만 50 이라 위로 평행하게 올라갔고, 다홍 선(alpha 1.5)은 기울기가 가팔라서 차이를 키웁니다. 보라 선(alpha 0.5)은 기울기가 완만해서 차이를 줄입니다. 선이 가파를수록 대비가 커진다고 읽으면 됩니다.

손으로 계산해 보기

alpha 1.5, beta -64 를 넣어 봅니다.

원래 밝기 f1.5 × f+ (-64)바뀐 밝기 g
100150150 - 6486
160240240 - 64176
차이6090
203030 - 64 = -340 이어야 하는데 convertScaleAbs 는 34

100 과 160 의 차이 60 이 90 으로 벌어졌습니다. beta 를 -64 로 둔 까닭은, 곱하기만 하면 전체가 너무 밝아지므로 다시 끌어내리기 위해서입니다.

짧은 예시

Python
import cv2
import numpy as np

f = np.array([[100, 160, 20]], dtype=np.uint8)

# convertScaleAbs(src, alpha, beta): alpha 를 곱하고 beta 를 더한 뒤 절댓값을 내어 0~255 로 맞춘다
print(cv2.convertScaleAbs(f, alpha=1.5, beta=-64))   # 결과: [[ 86 176  34]]

# 음수를 0 으로 막으려면 소수로 계산하고 np.clip 으로 0~255 를 자른 뒤 uint8 로 바꾼다
g = np.clip(1.5 * f.astype(np.float32) - 64, 0, 255).astype(np.uint8)
print(g)                                             # 결과: [[ 86 176   0]]

np.clip 의 clip 은 "잘라 내다"라는 뜻으로, 범위 밖의 값을 끝 값으로 바꿉니다.

주의할 점

  • cv2.convertScaleAbs 는 이름처럼 절댓값(Abs)을 냅니다. 계산이 -34 가 되면 0 이 아니라 34 가 됩니다. beta 를 음수로 크게 줄 때는 결과에 이런 칸이 섞일 수 있으니, 위의 np.clip 방법을 씁니다.
  • alpha 를 너무 크게 주면 많은 칸이 0 과 255 에 몰려 정보가 지워집니다. 히스토그램의 양 끝에 막대가 솟으면 지나친 것입니다.
← 이전 절5장 · 밝기 조정다음 절 →5장 · 정규화로 늘이기