곤약노트

이미지 변환 (Image Transformation) ③대비 높이기 – 히스토그램 스트레칭 (Stretching Histogram) 본문

Data Science/High-Dimensional Data Analytics

이미지 변환 (Image Transformation) ③대비 높이기 – 히스토그램 스트레칭 (Stretching Histogram)

곤약처럼 부드럽게, 쫀쫀하게 2025. 7. 2. 09:00

이미지의 대비(contrast)가 흐릿하게 느껴질 때가 있죠? 사진 전체가 뿌옇거나, 명암이 애매할 때 말이에요. 이런 경우에 히스토그램 스트레칭(histogram stretching)을 통해 이미지의 대비를 높여줄 수 있습니다.

대비(Contrast)란?
대비는 이미지에서 가장 밝은 픽셀과 가장 어두운 픽셀의 차이를 의미

Contrast = 최대 픽셀값−최소 픽셀값

*대비가 크면 선명한 이미지, 대비가 작으면 뿌연 이미지

 

 

히스토그램 스트레칭 (Histogram Stretching)

히스토그램 스트레칭은 픽셀 값의 범위를 넓혀서 대비를 강화하는 방법입니다. 밝기는 그대로 두고밝은 부분은 더 밝게, 어두운 부분은 더 어둡게 늘려주는 것이 핵심

 

 

$$g(x,y) = T(f(x,y)) = \left( \frac{f(x,y) - \min(f)}{\max(f) - \min(f)} \right) \times \lambda$$
  • f(x,y): 원본 이미지에서 (x, y)의 픽셀 값
  • min⁡(f): 이미지 전체 픽셀 중 최소/최대 값
  • λ: 스트레칭 후 확장할 범위 (보통 255) (*λ 값이 클수록 픽셀의 분포가 더 넓게 퍼지고, 대비가 향상)

 

 

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 1. 이미지 불러오기 (흑백 모드)
image = cv2.imread('watermelon.jpg', cv2.IMREAD_GRAYSCALE)

# 2. 원본 이미지의 최소값과 최대값 계산
min_val = np.min(image)
max_val = np.max(image)

# 3. 스트레칭 공식 적용 (픽셀 값 범위를 [0, 255]로 선형 변환)
lambda_ = 200
stretched = ((image - min_val) / (max_val - min_val)) * lambda_
stretched = np.clip(stretched, 0, 255).astype(np.uint8)

# 4. 시각화 (원본 vs 스트레칭 결과 vs 히스토그램)
plt.figure(figsize=(12, 5))

# 원본
plt.subplot(1, 3, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Grayscale')
plt.axis('off')

# 스트레칭 적용 이미지
plt.subplot(1, 3, 2)
plt.imshow(stretched, cmap='gray')
plt.title('Contrast Stretched (lambda = 200)')
plt.axis('off')

# 히스토그램
plt.subplot(1, 3, 3)
plt.hist(stretched.ravel(), bins=256, range=[0, 256], color='gray')
plt.title('Histogram after Stretching')
plt.xlabel('Pixel Intensity (0–255)')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()