[OpenCV] 04-10. Histograms in OpenCV (3)
🐍Python/OpenCV

[OpenCV] 04-10. Histograms in OpenCV (3)

728x90
반응형

< 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()


히스토그램이 어떻게 변하는지 볼 수 있다.

728x90
반응형