히스토그램 역투영(Histogram backprojection)
* 영상의 각 픽셀이 주어진 히스토그램 모델에 얼마나 일치하는지를 검사하는 방법
* 임의의 색상 영역을 검출할 때 효과적
* 확률론적 의미를 가지고 있음(역투영 이미지)
cv2.calcBackProject(images, channels, hist, ranges, scale, dst=None) -> dst
import cv2
import sys
import matplotlib.pyplot as plt
src = cv2.imread('ch03\\images\\cropland.png')
if src is None:
print('Image load failed')
sys.exit()
# ROI 창 생성(드래그 할 수 있음) / spacebar 누르면 ROI 적용됨
x, y, w, h = cv2.selectROI('ROI', src)
print(x, y, w, h)
# Histogram(RGB가 아닌 YCrCb가 임의의 색추출에 용의)
src_ycrcb = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)
crop = src_ycrcb[y:y+h, x:x+w] # ROI
channels = [1,2] # Y: 밝기 정보라 필요 X(Cr, Cb)
cr_bins = 128 # 0~255, 256을 써야하지만 128( 결과는 비슷함 )
cb_bins = 128
histsize = [cr_bins, cb_bins]
cr_range = [0,256] # 256 = 255까지의 값이기 때문에
cb_range = [0,256]
ranges = cr_range + cb_range
print(ranges) ## [0,256,0,256]
'''
cv2.normalize(cv2.log(hist + 1))
= Histogram이 큰 애들은 너무 큰 값이 나오기 때문에 큰 몇개의 픽셀만 밝게 나옴
= 나머지는 0에 가까운 검정색이 나옴. so, log값이 0이 나올수 있으니 +1을 해줌
hist 그래프 = plt.plot(hist)
# *mask = 특정영역(mask)에서만 Histogram을 계산하고 싶다면*
'''
hist = cv2.calcHist([crop], channels, None, histsize, ranges, cv2.CV_8U)
hist_norm = cv2.normalize(cv2.log(hist+1), None, 0, 255, cv2.NORM_MINMAX)
# cv2.calcBackProject = cv2.calcHist와 인자값이 비슷하다
# 하지만 calcHist는 Histogram을 출력으로 내주는 것이고
# calcBackProject는 calcHist를 입력으로 받고 그 histogram과 부합되는 영역만
# 0보다 큰 값으로 되있는 확률과 같은 개념의 이미지를 반환
# backproj = grayscale
backproj = cv2.calcBackProject([src_ycrcb], channels, hist, ranges, 1)
dst = cv2.copyTo(src, backproj)
# cv2.copyTo : ROI를 지정한 backproj(grayscale) = 흰 부분만 가져오기
# 특정 mask만 추출시
src1 = cv2.imread('ch03\\images\\kids1.png')
mask = cv2.imread('ch03\\images\\kids1_mask.bmp', cv2.IMREAD_GRAYSCALE)
print(mask.shape) # grayscale로 안불러오면 d= 3
if src1 is None or src2 is None or mask is None:
print('Image load failed')
sys.exit()
# 임의의 색을 추출하기위한 변환
src1_ycrcb = cv2.cvtColor(src1, cv2.cv2.COLOR_BGR2YCrCb)
channels = [1,2]
histSize = [128, 128]
ranges = [0,256,0,256] # Cr, Cb 범위 지정
# *mask = 특정영역(mask)에서만 Histogram을 계산하고 싶다면*
# histsize = 픽셀의 범위는 0 ~ 255
# ranges = 픽셀 범위의 값들을 계산하기위함
hist = cv2.calcHist([src1_ycrcb], channels, mask, histSize, ranges)
hist_norm = cv2.normalize(cv2.log(hist+1), None, 0, 255, \
cv2.NORM_MINMAX, cv2.CV_8U) # cv2.CV_8U default
backproj = cv2.calcBackProject([src1_ycrcb], channels, hist, ranges, 1)
'OpenCV > OpenCV-Chapter' 카테고리의 다른 글
CH04 Opencv-Python 필터링(filtering) - blurring, Sharpening (0) | 2021.12.18 |
---|---|
CH03 Opencv-Python Chroma_key (0) | 2021.12.18 |
CH03 Opencv-Python Histogram, Contrast (0) | 2021.12.18 |
CH03 Opencv-Python 영상 처리 기법(화소, 연산) (0) | 2021.12.18 |
CH02 OpenCV-Python 기초(도형그리기) (0) | 2021.12.18 |
댓글