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

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

히스토그램 평활화

반 학생 20명을 키 순서로 한 줄로 세운다고 해 봅시다. 맨 앞 학생은 "앞에서 5% 자리", 가운데 학생은 "50% 자리"입니다. 키가 165cm 근처에 우르르 몰려 있어도, 자리 순서로 번호를 매기면 번호는 1번부터 20번까지 고르게 퍼집니다. 평활화는 픽셀을 밝기 순서로 줄 세워 "앞에서 몇 % 자리인가"로 새 밝기를 매깁니다. 시험의 백분위와 같은 생각입니다.

밝기마다 세기, 누적하기, 비율 내기, 255 곱하기의 네 단계 흐름도

그림의 네 단계를 따라 계산합니다. 밝기마다 칸 수를 세고(4장의 히스토그램), 나보다 어둡거나 같은 칸 수를 쌓아 더하고(누적 도수), 전체에서 몇 %인지 비율을 내고, 그 비율에 255 를 곱합니다. 여기서 줄 선 학생이 픽셀이고, "앞에서 몇 % 자리"가 누적 비율입니다. 비유와 다른 점은, 밝기가 같은 칸들은 한 덩어리로 같은 자리를 받는다는 것입니다. 그래서 막대 하나가 둘로 갈라지지는 않습니다.

어두운 거리 장면의 평활화 전후 그림, 히스토그램, 누적 비율 곡선

위가 평활화 전, 아래가 평활화 뒤입니다. 막대는 칸 수이고 다홍 선이 누적 비율입니다. 평활화 전에는 막대가 왼쪽에 몰려 다홍 선이 왼쪽에서 가파르게 1 까지 올라갑니다. 평활화 뒤에는 막대가 0~255 에 흩어지고, 다홍 선이 왼쪽 아래에서 오른쪽 위로 계단처럼 고르게 올라갑니다. 누적 비율 선이 곧게 펴지는 것이 평활화의 목표입니다.

손으로 계산해 보기(픽셀 8개)

밝기가 50, 50, 50, 60, 60, 70, 80, 90 인 픽셀 8개를 평활화합니다. OpenCV 는 가장 어두운 밝기가 0 이 되도록, 누적 칸 수에서 가장 어두운 밝기의 칸 수(여기서는 3)를 빼고 계산합니다.

밝기칸 수누적 칸 수누적 - 3÷ (8 - 3)× 255 = 새 밝기
5033000
602520.4102
701630.6153
801740.8204
901851.0255

50~90 에 좁게 모여 있던 밝기가 0~255 로 퍼졌습니다. 50 과 60 은 10 차이였지만, 50 이 셋이나 되어 앞자리를 많이 차지하므로 새 밝기는 0 과 102 로 크게 벌어졌습니다. 칸이 많이 몰린 밝기일수록 다음 밝기와의 간격이 넓어집니다.

짧은 예시

Python
import cv2
import numpy as np

tiny = np.array([[50, 50, 50, 60],
                 [60, 70, 80, 90]], dtype=np.uint8)

# cv2.equalizeHist(src): 흑백(채널 하나) uint8 그림을 평활화한다
print(cv2.equalizeHist(tiny))
# 결과:
# [[  0   0   0 102]
#  [102 153 204 255]]

손계산 표의 새 밝기와 똑같이 나옵니다.

주의할 점

  • cv2.equalizeHist 는 채널이 하나인 흑백 그림만 받습니다. 컬러 그림을 넣으면 오류가 납니다. 컬러는 다음 절에서 다룹니다.
  • 평활화는 사진마다 결과가 크게 다릅니다. 이미 고른 사진도 막대를 다시 펴므로 지나치게 진해지거나, 넓고 고른 벽에 계단 무늬가 생길 수 있습니다.
← 이전 절5장 · 감마 보정다음 절 →5장 · 컬러 사진의 평활화