히스토그램 (Histogram)

  • 통계학에서 히스토그램은 데이터의 빈도수(frequency)를 막대그래프로 표시한 것으로 데이터의 밀도(density)를 추정할 수 있는 지표가 된다.
  • 영상에서 히스토그램은 영상의 각 픽셀 값의 분포에 대한 정보를 나타낸 것.
  • x축: 픽셀 밝기 값 (예: 0~255)
  • y축: 해당 밝기 값의 픽셀 개수 (빈도)

OpenCV

  • OpenCV에서 제공하는 calcHist() 함수를 이용해 히스토그램을 구할 수 있다.
hist = cv2.calcHist(images, channels, mask, histSize, ranges, hist, accumulate)
hist = cv2.calcHist([src], [0], None, [256], [0,256])

cv2.calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None) -> hist

images: 입력 영상 리스트
channels: 히스토그램을 구할 채널을 나타내는 리스트
mask: 마스크 영상. 입력 영상 전체에서 히스토그램을 구하려면 None 지정
histSize: 히스토그램 각 차원의 크기(빈(bin)의 개수)를 나타내는 리스트
ranges: 히스토그램 각 차원의 최솟값과 최댓값으로 구성된 리스트
hist: 계산된 히스토그램 (numpy.ndarray)
accumulate: 기존의 hist 히스토그램에 누적하려면 True, 새로 만들려면 False


히스토그램 스트레칭

개요

  • 히스토그램 스트레칭(Histogram Stretching)은 입력 영상의 픽셀 값이 전체 범위(0255)를 충분히 사용하지 못하고, 좁은 구간에 몰려 있을 때 최소/최대 밝기값을 통해 0255 범위로 확장.
  • 히스토그램 분포 모양은 그대로 유지되지만, 범위가 넓어져 명암비(contrast)를 향상 시킨다.

방법

  • : 입력 픽셀값
  • , : 영상의 최소/최대 픽셀값
  • : 총 레벨 수

코드 (Python)

import cv2
 
# 이미지 읽기 (그레이스케일)
img = cv2.imread("input.jpg", cv2.IMREAD_GRAYSCALE)
 
# 최소/최대 픽셀 값 구하기
min_val, max_val, _, _ = cv2.minMaxLoc(img)
 
# 히스토그램 스트레칭
stretched = ((img - min_val) / (max_val - min_val) * 255).astype(np.uint8)

히스토그램 평활화

  • 히스토그램 평활화(Histogram Equalization)는 영상의 밝기 분포를 넓게 퍼뜨려 전체적인 명암비(contrast)를 향상시키는 기법.
  • 특히 어두운 영상이나 밝기가 치우친 영상에서 세부 정보를 더 잘 볼 수 있게 만드는 간단한 이미지 향상 기법 중 하나.


방법

  • 영상 크기:
  • 픽셀 밝기값: (예: )

1. 히스토그램 계산

  • 밝기값 에 대한 빈도수 계산

2. 정규화된 히스토그램 (확률 분포 함수, PDF)

  • 총 픽셀 수로 나누어 확률 분포 정규화 (0~1)
  • 이때, 모든 를 더하면 1이됨.

3. 누적 분포 함수 (CDF)

  • 누적합 는 밝기값 이하의 픽셀이 차지하는 비율 (밝기 누적 비율)
  • ()

4. 정규화된 CDF를 이용해 새로운 밝기값 매핑

  • 는 [0, 1] 범위이므로 다시 [0, 255]로 스케일 조정

5. 전체 영상에 매핑 적용

  • 영상의 모든 픽셀에 대해 수행

예시

원래 밝기 빈도수 정규화 누적합 매핑된 값
040.20.251
130.150.3589
220.10.45115
360.30.75191
450.251.0255

코드 (Python)

# Using Numpy
import numpy as np
 
def histogram_equalization(img):
    flat = img.flatten()
    hist = np.bincount(flat, minlength=256)
    cdf = hist.cumsum()
    cdf_normalized = cdf * 255 / cdf[-1]
    equalized_flat = np.floor(cdf_normalized[flat]).astype(np.uint8)
    return equalized_flat.reshape(img.shape)
 
# Using OpenCV
import cv2
 
equalized = cv2.equalizeHist(img) # 1-channel

히스토그램 스트레칭 vs. 평활화

  • 히스토그램 스트레칭

  • 히스토그램 평활화


Prev: 2. 영상 이진화

Next: 3-1. 히스토그램 평활화 - CLAHE