Histogram Equalization 이란?

이미지의 히스토그램이 특정영역에 너무 집중되어 있으면 contrast가 낮아 좋은 이미지라고 할 수 없음
따라서 좌측 히스토그램 처럼 특정 영역에 집중되어 있는 분포를 오른쪽 처럼 골고루 분포하도록 하는 작업
1. Numpy로 CDF값을 이용해서 균일화 작업 하기
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('images/hist_unequ.jpg');
hist, bins = np.histogram(img.flatten(), 256,[0,256])
cdf = hist.cumsum()
# cdf의 값이 0인 경우는 mask처리를 하여 계산에서 제외
# mask처리가 되면 Numpy 계산에서 제외가 됨
# 아래는 cdf array에서 값이 0인 부분을 mask처리함
cdf_m = np.ma.masked_equal(cdf,0)
#History Equalization 공식
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
# Mask처리를 했던 부분을 다시 0으로 변환
cdf = np.ma.filled(cdf_m,0).astype('uint8')
img2 = cdf[img]
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(img2),plt.title('Equalization')
plt.show()

2. OpenCV cv2.equalizeHist 함수 사용하기
equalized = cv2.equalizeHist(gray)

- 정의: 특정 밝기(Intensity)에 치중된 픽셀 분포를 고르게 펼쳐 어두운 부분은 더 어둡게, 밝은 부분은 더 밝게 만들어 이미지 전체의 대비를 높임
- 장점: 간단하고 빠르게 이미지의 대비를 개선할 수 있음
- 단점:
- 전역적인 적용: 이미지 전체에 동일한 변환을 적용하기 때문에, 이미지의 특정 영역에서는 오히려 대비가 감소하거나 노이즈가 증폭될 수 있음.
- 과도한 밝기 증가: 이미지의 밝은 영역이 너무 밝아져 정보가 손실될 수 있다
2. CLAHE - Contrast Limited Adaptive Histogram Equalization

- 정의: 입력 영상을 M×N 크기의 타일(grid)로 분할한 뒤, 각 타일마다 평준화를 적용하고 경계에서 부드럽게 이어붙이는 방식으로 동작
- 장점 : 이미지 각 영역의 특성에 맞게 대비를 향상시켜 더 자연스러운 결과 출력, 노이즈 증폭 제한
2-1. cv2.createCLAHE 함수
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
equalized = clahe.apply(gray)
- clipLimit(대비 제한 임계값) : 값이 클수록 국소 대비가 크게 증폭되어 노이즈가 늘어날 수 있음, 2–5 범위 권장

- tileGridSize : 타일 크기를 지정. 예를 들어 (8,8)이면 영상을 8×8 격자로 나누어 각 타일별 평준화를 수행

3. Multi-channel (color) Image Equalization
3-1. RGB 채널을 분리하여 equalization 후 합치기
구현이 훨씬 직관적이지만 색조가 변할 수 있음 (아래 예시 참조)
# B, G, R 채널 분리
(b, g, r) = cv2.split(image)
# 각 채널에 히스토그램 평준화 적용
b_eq = cv2.equalizeHist(b)
g_eq = cv2.equalizeHist(g)
r_eq = cv2.equalizeHist(r)
# 평준화된 채널 병합
equalized = cv2.merge([b_eq, g_eq, r_eq])

3-2. YCrCb 색공간을 사용
- BGR/RGB처럼 R-G-B 3가지 채널이 모두 밝기와 색 정보를 섞어 담고 있는 것과 달리
밝기 정보와 색차 정보(chrominance)를 분리해 표현하는 컬러 모델. - 장점
- 밝기채널(Y)만 조작하면 색조에 영향 없이 이미지 전반의 대비를 개선 가능 : 영상 컬러 보정에서 많이 쓰임
- 사람 눈이 색 정보보다는 밝기 정보에 민감하므로 Cr/Cb 채널의 해상도를 낮춰 품질저하를 최소하하면서 압축률 향상 가능
- 색차 채널만 선택적으로 조절해 색상 강조나 톤 매핑을 할 수 있음
- 채널구성
- Y (Luma)
- 픽셀의 밝기(명암) 정보만 담고 있음
- 인간 눈이 밝기 변화에는 민감하지만 색 변화에는 덜 민감하다는 점을 활용해, 밝기만 별도로 다루면 압축 효율이나 대비 조정 시 장점이 큼
- Cr (Chroma-Red)
- “빨강 성분 – 밝기” 차이 값을 저장합니다.
- 기본적으로 Cr = R – Y 형태로 계산되며, 양(+)일수록 붉은 기운이 강함
- Cb (Chroma-Blue)
- “파랑 성분 – 밝기” 차이 값을 저장합니다.
- Cb = B – Y 형태로 계산되며, 양(+)일수록 푸른 기운이 강함
- Y (Luma)
# 1) BGR → YCrCb 변환
ycrcb = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)
# 2) Y 채널만 히스토그램 평준화
y_channel, cr, cb = cv2.split(ycrcb)
y_eq = cv2.equalizeHist(y_channel)
ycrcb_eq = cv2.merge([y_eq, cr, cb])
# 3) YCrCb → BGR 재변환
equalized = cv2.cvtColor(ycrcb_eq, cv2.COLOR_YCrCb2BGR)

**참고
*OpenCV의 컬러채널 순서는 (B,G,R)
matplotlib의 컬러채널 순서는 (R,G,B) 이므로 결과 출력할 때 cv2.COLOR_BGR2RGB로 변환하기
orig_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
eq_rgb = cv2.cvtColor(equalized, cv2.COLOR_BGR2RGB
# matplotlib으로 나란히 출력
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].imshow(orig_rgb)
axes[0].set_title("Original")
axes[0].axis("off")
axes[1].imshow(eq_rgb)
axes[1].set_title("Equalized")
axes[1].axis("off")
plt.tight_layout()
plt.show()
출처
OpenCV Histogram Equalization and Adaptive Histogram Equalization (CLAHE) - PyImageSearch
In this tutorial, you will learn to perform both histogram equalization and adaptive histogram equalization with OpenCV.
pyimagesearch.com
참고자료
'PyImageSearch' 카테고리의 다른 글
| CDF(누적 분포 함수) (0) | 2025.06.16 |
|---|---|
| OpenCV - Histogram Matching (0) | 2025.06.16 |
| OpenCV - Image Histograms (0) | 2025.06.15 |
| OpenCV - Edge detection (0) | 2025.06.14 |
| OpenCV - Image Gradients(엣지검출) (0) | 2025.06.13 |