히스토그램 (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)은 입력 영상의 픽셀 값이 전체 범위(0
255)를 충분히 사용하지 못하고, 좁은 구간에 몰려 있을 때 최소/최대 밝기값을 통해 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)를 향상시키는 기법.
- 특히 어두운 영상이나 밝기가 치우친 영상에서 세부 정보를 더 잘 볼 수 있게 만드는 간단한 이미지 향상 기법 중 하나.
- 히스토그램 평활화의 응용 방법: 3-1. 히스토그램 평활화 - CLAHE
방법
- 영상 크기:
- 픽셀 밝기값: (예: )
1. 히스토그램 계산
- 밝기값 에 대한 빈도수 계산
2. 정규화된 히스토그램 (확률 분포 함수, PDF)
- 총 픽셀 수로 나누어 확률 분포 정규화 (0~1)
- 이때, 모든 를 더하면 1이됨.
3. 누적 분포 함수 (CDF)
- 누적합 는 밝기값 이하의 픽셀이 차지하는 비율 (밝기 누적 비율)
- ()
4. 정규화된 CDF를 이용해 새로운 밝기값 매핑
- 는 [0, 1] 범위이므로 다시 [0, 255]로 스케일 조정
5. 전체 영상에 매핑 적용
- 영상의 모든 픽셀에 대해 수행
예시
원래 밝기 | 빈도수 | 정규화 | 누적합 | 매핑된 값 |
---|---|---|---|---|
0 | 4 | 0.2 | 0.2 | 51 |
1 | 3 | 0.15 | 0.35 | 89 |
2 | 2 | 0.1 | 0.45 | 115 |
3 | 6 | 0.3 | 0.75 | 191 |
4 | 5 | 0.25 | 1.0 | 255 |
코드 (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