Language - Python(Opencv)

Python Opencv - #14, histogram 기본

KimTory 2021. 11. 22. 22:23

▶ 영상의 히스토그램 분석하기

 -. 히스토그램(Histogram)은 영상의 픽셀 값 분포를 그래프의 형태로 표현한 것입니다.

예를 들어, 그레이스케일 영상에서 각 그레이스케일 값에 해당하는 픽셀의 개수를 구하고, 이를 막대 그래프 형태로 표현합니다.

 

 -. 정규화된 히스토그램(Normalized histogram)은 각 픽셀의 개수를 영상 전체 픽셀 개수로 나누어 준 것입니다.

 해당 그레이스케일 값을 갖는 픽셀이 나타날 확률을 의미합니다.

 

→ 영상과 히스토그램의 관계

 밝은 영상이면 히스토그램이 전체적으로 오른쪽으로 치우쳐져 있습니다.

 어두운 영상이면 히스토그램이 왼쪽으로 치우쳐져 있습니다.

 명암비가 확실한 영상이면 히스토그램이 전체적으로 분포해 있습니다.

 

 영상의 히스토그램을 보고 영상의 특징을 알 수 있습니다.

 

→ OpenCV로 히스토그램 구하기 - cv2.calcHist

 OpenCV에서 제공하는 cv2.calcHist() 함수로 히스토그램을 구할 수 있습니다.

 

[함수 설명]

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

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

[그레이스케일 영상의 히스토그램 구하기]

src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()
    
# 그레이스케일 [0], BG [0,1], BGR [0,1,2]
hist = cv2.calcHist([src], [0], None, [256], [0,256]) # 꼭 리스트 형태로 입력

cv2.imshow('src', src)
cv2.waitKey(1)  # 1로 설정한 이유는 다음 matplot 명령어를 실행시키기 위함. 창은 사라지지 않음

plt.plot(hist)
plt.show()

 흑백 영상의 히스토그램을 확인할 수 있습니다.

 

[컬러 영상의 히스토그램 구하기]

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

if src is None:
    print('Image load failed!')
    sys.exit()

colors = ['b', 'g', 'r']
bgr_planes = cv2.split(src)

for (p, c) in zip(bgr_planes, colors):
    hist = cv2.calcHist([p], [0], None, [256], [0, 256])
    plt.plot(hist, color=c)

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

plt.show()

import cv2
import numpy as np 
src = cv2.imread('lenna.bmp') 
bgr_plans = cv2.split(src) 
histSize = 256 
histRange = (0,256) 
accumulate = False 
b_hist = cv2.calcHist(bgr_plans, [0], None, [histSize], histRange, accumulate=accumulate) 
g_hist = cv2.calcHist(bgr_plans, [1], None, [histSize], histRange, accumulate=accumulate) 
r_hist = cv2.calcHist(bgr_plans, [2], None, [histSize], histRange, accumulate=accumulate) 

hist_w = 256*3 
hist_h = 400 
histImage = np.zeros((hist_h,hist_w,3), dtype=np.uint8) 

cv2.normalize(b_hist,b_hist,alpha=0,beta=hist_h,norm_type=cv2.NORM_MINMAX) 
cv2.normalize(g_hist,g_hist,alpha=0,beta=hist_h,norm_type=cv2.NORM_MINMAX) 
cv2.normalize(r_hist,r_hist,alpha=0,beta=hist_h,norm_type=cv2.NORM_MINMAX) 

for i in range(0,histSize): 
    cv2.line(histImage,(i,hist_h-int(np.round(b_hist[i]))), (i,hist_h - 0), (255,0,0), thickness=2) 
    cv2.line(histImage,(i+256,hist_h-int(np.round(g_hist[i-1]))), (i+256,hist_h - 0), (0,255,0), thickness=2) 
    cv2.line(histImage,(i+256*2,hist_h-int(np.round(r_hist[i-1]))), (i+256*2,hist_h - 0), (0,0,255), thickness=2)\

cv2.imshow('Source image', src) 
cv2.imshow('HIstogram', histImage) 
cv2.waitKey()

 

 

위 히스토그램 차트를 보듯이 B 색상의 값이 제일 높게 나타나는 것을 확인 할 수 있습니다.

영상마다 히스토그램 분석 시, 차이가 있을 수 있으므로 히스토그램은 단순 분포도로 사용 하는 것이

실무에서 좋을 거 같습니다.

 

히스토리 그램은 이 외에도 평활화, 스트레칭, 역투영, 정규화 작업 등 다양한 작업의

기반이 되기도 합니다.

 


https://computistics.tistory.com/38

 

[OpenCV] 6. 히스토그램, 명암비, 스트레칭, 평활화, 역투영

히스토그램 이미지처리를 할때 픽셀의 분포를 파악하기위해 사용하는 방법이다. 도메인마다 특징이 있는 픽셀값이 존재할 수 있으며, 이런 특징을 잘 핸들링 해주면 보다 퀄리티 높은 이미지를

computistics.tistory.com