< 2D-Histograms >
이번 장에서는, 2D 히스토그램을 찾고 그려볼 것이다. 다가올 챕터들에 있어서 도움이 될 것이다.
Introduction
(1)에서는 1차원 히스토그램을 계산하고 그렸었다. 하나의 특성만 다루기에 1차원이라고 부르는 것이다. (흑백 스케일 픽셀의 강도 값) 하지만 2차원 히스토그램에서는, 두 가지 특성을 고려한다. 일반적으로 두 가지 특성이 모든 픽셀의 색조&채도 값인 컬러 히스토그램을 찾는데 사용된다.
컬러 히스토그램을 어떻게 만드는지 이해해볼 것이고, 앞으로 있을 히스토그램 Back-Projection을 이해하는데 유용할 것 이다.
2D Histogram in OpenCV
이는 다소 간단하고 cv2.calcHist() 함수를 이용하여 계산한다. 컬러 히스토그램에 대해, 이미지를 BGR에서 HSV로 변환해야 한다. (1차원 히스토그램에서는 BGR에서 GRAY로 변환했다.) 2D 히스토그램을 위해서는, 파라미터들이 다음과 같이 수정되어야한다.
- channels = [0,1] 왜냐하면 H와 S 면을 처리해야하기 때문이다.
- bins = [180,256] 180은 H 면을 위해 256은 S 면을 위한 것이다
- range = [0,180,0,256] 색조값은 0부터 180 사이에 놓여있고, 채도는 0부터 256사이에 있다.
아래 코드를 보자.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./images/golden.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
2D Histogram in Numpy
Numpy는 이를 위한 특정 함수인 np.histogram2d()를 제공한다.(1D 히스토그램을 위해서는 np.histogram()을 사용한다.)
img = cv2.imread('./images/golden.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
첫 번째 인자는 H 면이고, 두 번째 인자는 S 면이고, 세 번째는 각각에 대한 bins의 수이고, 네 번째는 그들의 범위이다.
이제 컬러 히스토그램을 어떻게 그리는지 확인해보자.
Plotting 2D Histograms
방법 - 1 : “cv2.imshow()” 사용하기
우리가 얻을 이차원 배열의 크기는 180x256이다. 그래서 cv2.imshow()를 사용하여 보여줄 수 있다. 흑백스케일의 이미지 일 것 이고, 다른 색상의 색조값을 알지 못하는 한, 무슨 색이었는지에 대해 정보를 주지 않는다.
방법 - 2 : “Matplotlib” 사용하기
matplotlib.pyplot.imshow() 함수를 이용하여 2D 히스토그램을 다른 컬러맵으로 그릴 수 있다. 이는 다른 픽셀 밀도에 관해 우리에게 더 많은 정보를 제공한다. 하지만 이것 또한, 다른 색의 색조값을 알지 않는 한, 첫 눈에 어떤 색이 있는지 알 수 없다. 그래도 이 방법을 선호한다. 간단하고 더 낫기 때문이다!
- 이 함수를 쓸 때, interpolation flag는 nearest로 사용하는게 결과가 더 낫다.
코드를 보자
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./images/golden.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
plt.figure(figsize=(12,8))
plt.subplot(121)
plt.imshow(img[:,:,::-1])
plt.subplot(122)
plt.imshow(hist,interpolation='nearest')
plt.show()
아래는 입력이미지와 컬러 히스토그램을 나타낸 것이다. X 축은 S 값을, Y축은 색조값을 보여준다.
히스토그램에서, H=20, S=100 주변부에서 높은 값을 볼 수 있다. 이는 밝은색인 털에 대응한다고 볼 수 있다. 유사하게 다른 피크점인 H=60,S=160은 코 주변이라고 볼 수도 있다. 이를 이미지 편집 툴 같은 GIMP로 확인해 볼 수 있다.
방법 3 : OpenCV 샘플 스타일!!
HSV 색 지도를 만들었다. 그리고 BGR로 전환했다. 결과 히스토그램 이미지에 이 색상 맵을 곱한다.
def onChange(x):
global hscale
hscale = x
np.random.seed(123)
hsvmap = np.zeros((180,256,3),np.uint8)
h,s = np.indices(hsvmap.shape[:2])
hsvmap[:,:,0] = h
hsvmap[:,:,1] = s
hsvmap[:,:,2] = 255
hsvmap = cv2.cvtColor(hsvmap,cv2.COLOR_HSV2BGR)
img = cv2.imread('./images/golden.jpg')
cv2.namedWindow('hist2D',0)
cv2.createTrackbar('scale','hist2D',hscale,32,onChange)
while True:
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
hist = np.clip(hist*0.005*hscale,0,1)
hist = hsvmap*hist[:,:,np.newaxis] / 255.0
cv2.imshow('hist2D',hist)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
히스토그램이 어떻게 변하는지 볼 수 있다.