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

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

정규화로 늘이기

고무줄의 한쪽 끝을 0 에, 다른 끝을 255 에 걸어 당긴다고 해 봅시다. 고무줄 위의 점들은 저마다 차지하던 비율 자리로 옮겨 갑니다. 정규화가 이 일입니다. 사진에서 가장 어두운 칸을 0 으로, 가장 밝은 칸을 255 로 늘이고, 그 사이의 칸은 비율대로 자리를 잡습니다.

가장 어두운 값 빼기, 범위로 나누기, 255 곱하기의 세 단계 흐름도

그림의 세 단계가 정규화의 계산입니다. 가장 어두운 값을 빼면 가장 어두운 칸이 0 이 되고, 범위(가장 밝은 값 - 가장 어두운 값)로 나누면 모든 칸이 0~1 사이의 비율이 되고, 255 를 곱하면 가장 밝은 칸이 255 가 됩니다. 여기서 고무줄의 양 끝이 가장 어두운 값과 가장 밝은 값이고, 고무줄 위의 점이 칸 하나하나입니다. 대비 조정에서 alpha 와 beta 를 손으로 고르던 일을 사진의 숫자에 맞춰 저절로 해 준다고 볼 수 있습니다.

대비 낮은 거리 장면을 NORM_MINMAX 로 늘이기 전과 뒤의 그림과 히스토그램

4장의 대비 낮은 사진(low_contrast.png)은 가장 어두운 값이 97, 가장 밝은 값이 164 라 막대가 가운데에 좁게 모여 있습니다. 늘인 뒤에는 0 부터 255 까지 퍼졌습니다. 막대의 순서와 모양의 짜임은 그대로이고 간격만 넓어졌습니다.

손으로 계산해 보기

가장 어두운 값이 90, 가장 밝은 값이 165 인 사진에서, 밝기 120 인 칸은 어디로 갈까요?

단계계산결과
① 가장 어두운 값 빼기120 - 9030
② 범위로 나누기30 ÷ (165 - 90) = 30 ÷ 750.4
③ 255 곱하기0.4 × 255102

밝기 120 은 90~165 범위에서 아래로부터 40% 자리였으므로, 0~255 에서도 40% 자리인 102 로 갑니다.

짧은 예시

Python
import cv2
import numpy as np

t = np.array([[90, 120, 165, 100]], dtype=np.uint8)

# cv2.normalize(src, dst, alpha, beta, norm_type): NORM_MINMAX 면 가장 작은 값을 alpha, 가장 큰 값을 beta 로
out = cv2.normalize(t,                   # src: 바꿀 그림
                    None,                # dst: 결과를 담을 곳. None 이면 새로 만든다
                    0,                   # alpha: 가장 작은 값이 갈 자리
                    255,                 # beta: 가장 큰 값이 갈 자리
                    cv2.NORM_MINMAX)     # norm_type: 최솟값·최댓값 방식
print(out)   # 결과: [[  0 102 255  34]]

100 은 (100 - 90) ÷ 75 × 255 = 34 입니다. 여기서 alpha 와 beta 는 대비 조정 식의 alpha, beta 와 이름만 같고 뜻이 다릅니다. cv2.normalize 에서는 범위의 아래 끝과 위 끝입니다.

주의할 점

  • 아주 어두운 점 하나, 아주 밝은 점 하나만 있어도 범위가 0~255 로 잡혀 늘일 것이 없습니다. 이미 0 과 255 가 있는 사진에는 정규화가 아무 일도 하지 않습니다.
  • 정규화는 간격을 같은 비율로 늘일 뿐, 몰린 곳을 따로 펴지는 않습니다. 막대가 한쪽에 뭉쳐 있으면 평활화가 더 많이 바꿉니다.
← 이전 절5장 · 대비 조정다음 절 →5장 · 감마 보정