본문 바로가기
Python/Computer Vision

[파이썬, Python] OpenCV - 히스토그램과 영상 균등화, 정규화

by coding-choonsik 2023. 8. 25.
728x90
반응형
SMALL

1. 히스토그램(histogram)

  • 영상의 픽셀값 분포를 그래프 형태로 표현
  • 예) 그레이스케일 영상에서 밝기 정보에 해당하는 픽셀의 개수를 구하고 막대 그래프로 표현
  • cv2.calcHist(영상, 히스토그램을 구할 채널, None, 빈의 개수를 나타내는 리스트, 히스토그램 각 차원의 최소값과 최대값으로 구성된 리스트)
    • 빈의 개수: 색상에 대한 개수(0 ~ 255) -> 관례적으로 256을 넣으면 됨

1-1. 영상과 히스토그램의 관계

  • 밝은 영상이면 히스토그램이 전체적으로 오른쪽으로 치우쳐져 있음
  • 어두운 영상이면 히스토그램이 전체적으로 왼쪽으로 치우쳐져 있음
  • 명암비가 확실한 영상이면 히스토그램이 전체적으로 양쪽으로 분포

✅ 흑백 영상의 히스토그램

import cv2
import matplotlib.pyplot as plt
src = cv2.imread('dog.bmp', cv2.IMREAD_GRAYSCALE)

hist = cv2.calcHist([src], [0], None, [256], [0, 255])  # 모든 매개변수를 리스트로 넣어줌

cv2.imshow('src', src)
plt.plot(hist)
plt.show()
cv2.waitKey()

▲ src
▲ src에 대한 히스토그램

 

 

✅ 컬러 영상의 히스토그램

import cv2
import matplotlib.pyplot as plt

# dog.bmp 이미지를 사용하여 3채널(RGB)로 계산해 히스토그램 그리기
# 단, 하나의 plot에서 RGB 그래프 그리기
src = cv2.imread('dog.bmp')

colors = ['b', 'g', 'r']

# 리스트로 결과가 저장됨
bgr = cv2.split(src)
for (b, c) in zip(bgr, colors):
    hist = cv2.calcHist([b], [0], None, [256], [0, 255])
    plt.plot(hist, color=c)
    # plt.legend(colors)
cv2.imshow('src', src)
plt.show()


cv2.waitKey()

▲ src
▲ src에 대한 히스토그램(BGR)


2. 균등화, 평탄화(Equalization)

  • 히스토그램을 활용하여 이미지의 품질을 개선하기 위한 방법
  • 화소값을 0 ~ 255 사이에 고르게 분포하도록 개선
  •  cv2.equalizeHist(영상)

 

✅ 히스토그램을 활용하여 그레이스케일 영상 균등화

import cv2
import matplotlib.pyplot as plt

src = cv2.imread('Hawkes.jpg', cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(src)

hist1 = cv2.calcHist([src], [0], None, [256], [0, 255])
hist2 = cv2.calcHist([equ], [0], None, [256], [0, 255])
# cv2.imshow('src', src)
hists = {'hist1': hist1, 'hist2': hist2}

plt.figure(figsize=(12,8))
for i, (k,v) in enumerate(hists.items()):
    plt.subplot(1,2,i+1)
    plt.title(k)
    plt.plot(v)

cv2.imshow('src', src)
cv2.imshow('equ', equ)
plt.show()
cv2.waitKey()

 

▲ 원본(왼쪽)과 균등화한 결과(오른쪽) 
▲ 균등화 전(왼쪽) 히스토그램과 균등화 후(오른쪽) 히스토그램


 

✅ 컬러 영상 균등화

import cv2

src = cv2.imread('field.bmp')

# ycrcb = []
# dst = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)
# ycrcb = cv2.split(dst)  # 색상분할 -> 리스트로 저장됨
# ycrcb = list(ycrcb)
#
# # print(ycrcb)
#
# # 빛의 밝기 정보[0]만 균등화하고 재저장
# ycrcb[0] = cv2.equalizeHist(ycrcb[0])
#
# # 분할한 색상 정보를 병합
# dst = cv2.merge(ycrcb)
#
# # ycrcb를 BGR로 바꾸어줘야 cv2에서 띄울수 있음
# dst = cv2.cvtColor(dst, cv2.COLOR_YCrCb2BGR)

dst = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)

# 첫번째 채널이 색상정보이기 때문
dst[:, :, 0] = cv2.equalizeHist(dst[:,:,0])
dst = cv2.cvtColor(dst, cv2.COLOR_YCrCb2BGR)

cv2.imshow('src',src)
cv2.imshow('dst',dst)
cv2.waitKey()

▲ 균등화 전(왼쪽)과 균등화 후(오른쪽) 

 


7. CLAHE(Contrast Limited Adaptive Histogram Equalization)

  • 평탄화를 하면 이미지의 밝은 부분이 날라가는 현상을 보정하기 위해 사용
  • 이미지의 일정한 영역으로 나누어 평탄화를 적용
  • 이미지를 따로 적용
    • CLAHE객체 = cv2.createCLAHE(대비, 영역 크기)
    • CLAHE객체.apply(영상)

▲ 순서대로 원본, 정규화, CLAHE 적용 결과

 



8. 정규화(Normalization)

  • 이미지에서도 정규화가 필요한 경우가 있음
  • 특정 영역에 값이 몰려 있는 경우 화질을 개선하고, 이미지 간의 연산 시 서로 조건이 다른 경우 같은 조건으로 변경
  •  cv2.normalize(정규화 이전 영상, 정규화 이후 영상, 정규화 구간1, 정규화 구간2, 정규화 알고리즘 선택 플래그)
  • 정규화 구간2: 구간 정규화가 아닌 경우는 사용하지 않음
    •  정규화 알고리즘 선택 플래그
    •  cv2.NORM_MINMAX: 정규화 구간1 ~ 정규화 구간2를 구간으로 하는 정규화
    •  cv2.NORM_L1: 전체 합으로 나눔
    •  cv2.NORM_L2: 단위 벡터로 정규화
    •  cv2.NORM_INF: 최대값으로 나눔
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('Hawkes.jpg', cv2.IMREAD_GRAYSCALE)

# cv2.NORM_MINMAX
img_norm1 = img.astype(np.float32)
img_norm1= ((img_norm1 - img_norm1.min())) * 255 / (img_norm1.max() - img_norm1.min())
img_norm1 = img_norm1.astype(np.uint8)

img_norm2 = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)

hist = cv2.calcHist([img], [0], None, [256], [0, 255])
hist_norm1 = cv2.calcHist([img_norm1], [0], None, [256], [0, 255])
hist_norm2 = cv2.calcHist([img_norm2], [0], None, [256], [0, 255])

cv2.imshow('img', img)
cv2.imshow('img_norm1', img_norm1)
cv2.imshow('img_norm2', img_norm2)

hists = {'hist': hist, 'hist_norm1': hist_norm1, 'hist_norm2': hist_norm2}
plt.figure(figsize=(8,6))
for i, (k,v) in enumerate(hists.items()):
    plt.subplot(1,3,i+1)
    plt.title(k)
    plt.plot(v)
plt.show()
cv2.waitKey()

▲ 순서대로 img, img_norm1, img_norm2

 

 

 

▲ img, img_norm1, img_norm2 히스토그램

 

 

728x90
반응형
LIST