Python과 OpenCV – 20 : 히스토그램(Histogram) 1/4

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_histograms/py_histogram_begins/py_histogram_begins.html#histograms-getting-started 입니다.

아래 그림을 보면..

이미지에 대해 어떤 그래프를 표시하고 있는데, 화소의 강도(Gray 값 또는 하나의 채널에 대한 값)를 갖는 화소의 개수를 각각 X축과 Y축으로 표시하고 있습니다. 대부분의 경우 화소의 강도는 0-255입니다.

히스토그램을 얻는 방법은 Numpy를 이용하는 것과 OpenCV를 이용하는 것이 있습니다. 먼저 OpenCV를 이용한 예제를 보면..

import cv2

img = cv2.imread('./data/home.jpg',0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])

4번째 cv2.calcHist 함수가 이미지에 대한 히스토그램 정보를 얻는데, 이 함수의 첫번째는 입력 이미지의 배열이며 두번째는 히스토그램을 얻을 채널 인덱스, 세번째는 Mask 이미지, 네번째는 X 축 요소(BIN)의 개수이고 다섯번째는 Y 축 요소값의 범위로 하나의 채널에 대한 화소 강도가 0~255이므로 대부분의 경우 [0,256]이 됩니다. 이 함수의 반환값은 256개의 요소를 갖는 배열입니다.

Numpy를 이용하여 히스토그램을 얻는 코드는 다음과 같습니다.

import cv2
import numpy as np

img = cv2.imread('./data/home.jpg',0)
hist,bins = np.histogram(img.ravel(),256,[0,256])

5번째 코드의 np.histogram 함수가 히스토그램을 얻는 함수인데 반환값은 반환값은 256개의 요소를 갖는 배열인 hist와 X축 요소의 값을 나타내는 배열인 bins입니다. 이 함수 이외에도 hist = np.bincount(img.ravel(),minlength=256) 와 같은 더 빠른 함수가 가능합니다.

속도면에서 Numpy보다 OpenCV 방식이 훨씬 빠르므로 OpenCV를 사용하는 것이 좋습니다.

히스토그램 값을 그래프로 표시하기 위한 예제는 다음과 같습니다.

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./data/home.jpg',0)
plt.hist(img.ravel(), 256, [0,256]); 
plt.show()

결과는 다음과 같습니다.

BGR 형태와 같이 3개의 채널로 구성된 이미지에 대한 각 채널의 히스토그램도 시각화가 가능한데, 관련된 예제는 다음과 같습니다.

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./data/home.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
    histr = cv2.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

결과는 다음처럼 3개 채널 각각의 히스토그램 결과가 표시됩니다.

지금까지는 히스토그램 분석을 이미지 전체에 대해서 수행했는데, 필요할 경우 이미지의 원하는 영역에 대한 마스크를 지정해 해당 영역에 대한 히스토그램만을 분석할 수 있습니다. 아래의 코드가 예입니다.

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

img = cv2.imread('./data/home.jpg',0)

# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)

# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])

plt.show()

결과는 다음과 같습니다.

“Python과 OpenCV – 20 : 히스토그램(Histogram) 1/4”에 대한 2개의 댓글

    1. OpenCV는 입력소스를 동영상에서 간단히.. 이미처와 동일한 자료 구조로 얻을 수 있습니다. 자세한 내용은 역시 꾸글링이 최고죠..

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다