OpenCV 비전 실무4장 · 채널 처리와 히스토그램 분석8 / 21← 이전목차다음 →MetaContents

4장. 채널 처리와 히스토그램 분석

cv2.calcHist 의 인자

택배 회사에 "이 지역에서 온 상자만, 무게를 10개 구간으로, 0~50kg 범위에서 세어 주세요"라고 맡기는 장면을 떠올려 봅시다. 무엇을 셀지, 어디서 온 것만 셀지, 몇 구간으로 셀지, 어느 범위를 셀지를 알려 줘야 합니다. cv2.calcHist 도 같은 다섯 가지를 받습니다.

cv2.calcHist 에 주는 이미지, 채널, 마스크, bin 수, 범위의 다섯 인자를 나란히 놓은 비교 그림

그림의 다섯 상자가 cv2.calcHist 에 주는 다섯 인자입니다. 마스크를 뺀 네 가지는 대괄호 목록으로 감싸서 줍니다. 결과는 구간마다의 픽셀 수를 담은 배열 하나입니다. 여기서 상자 더미가 이미지, 상자의 종류가 채널, "이 지역에서 온 것만"이 마스크, 무게 구간의 개수가 bin 수, 0~50kg 이 범위입니다.

다섯 인자

순서인자흑백 그림의 보통 값뜻
1images[gray]셀 그림. 여러 장을 받을 수 있게 목록으로 준다
2channels[0]몇 번 채널을 셀까. 흑백은 0번 하나뿐이다
3maskNone셀 곳만 흰색인 판. 전체를 세면 None
4histSize[256]구간(bin) 개수
5ranges[0, 256]셀 값의 범위. 끝 값 256 은 들어가지 않으므로 0~255 를 센다

결과의 모양과 np.histogram 과의 차이

견줄 것cv2.calcHistnp.histogram
결과도수 하나도수와 구간 경계 두 개
도수의 모양OpenCV 5.0 은 (256,) 한 줄, 4.x 는 (256, 1) 세로로 긴 배열(256,), 한 줄
도수의 자료형float32(소수)int64(정수)
마스크셋째 인자로 준다없다(미리 골라낸 값을 넣는다)
속도그림에 맞춰 만들어 빠르다무엇이든 셀 수 있다

짧은 예시

Python
import cv2
import numpy as np

# 밝기 0~255 를 고르게 담은 아주 작은 흑백 그림(세로 2, 가로 4)
tiny = np.array([[0, 30, 60, 90],
                 [120, 200, 230, 255]], dtype=np.uint8)

# 구간을 4개로: 0~63, 64~127, 128~191, 192~255
hist = cv2.calcHist([tiny],     # images: 목록으로 감싼 그림
                    [0],        # channels: 0번 채널
                    None,       # mask: 전체를 센다
                    [4],        # histSize: 구간 4개
                    [0, 256])   # ranges: 0 이상 256 미만
print(hist.shape)                       # 결과: (4,) → OpenCV 5.0 기준. 4.x 에서는 (4, 1)
print([int(v) for v in hist.ravel()])   # 결과: [3, 2, 0, 3]

ravel() 은 여러 줄 배열을 한 줄로 펴 줍니다. ravel 은 "실타래를 풀다"라는 뜻입니다. OpenCV 4.x 에서는 결과가 (4, 1) 처럼 세로로 긴 모양이라, ravel() 로 펴 두면 어느 판에서나 같은 꼴로 쓸 수 있습니다. 0, 30, 60 이 첫 구간, 90, 120 이 둘째 구간, 200, 230, 255 가 넷째 구간에 들어가고 셋째 구간(128~191)은 비었습니다.

주의할 점

  • 범위를 [0, 255] 로 주면 255 인 칸이 세어지지 않습니다. 끝 값은 들어가지 않으므로 [0, 256] 으로 줍니다.
  • 결과는 소수(float32)입니다. 찍을 때는 int(...) 로 바꿔야 76800.0 대신 76800 이 나옵니다.
  • 인터넷의 예제는 대부분 OpenCV 4.x 기준이라 결과를 (256, 1) 로 설명하고 hist[k, 0] 처럼 꺼냅니다. 교안의 OpenCV 5.0 에서는 (256,) 이라 이 코드가 오류를 냅니다. hist.ravel() 로 펴서 쓰면 두 판 모두에서 돌아갑니다.
← 이전 절4장 · 히스토그램이란다음 절 →4장 · 밝기 분포 읽기