用于图像分割和查找感兴趣目标。简单的说,会创建一个与输入图像同样大小的图像(单通道),每个像素对应像素属于目标的概率。更简单的说就是,输出图像在感兴趣的目标处更白。常常与
camshift
算法一起使用,用于目标跟踪(查找目标)
如何使用呢?创建一个图像的直方图,包含了感兴趣目标,目标必须尽可能充满图像,效果会更好。颜色直方图优于灰度直方图,因为对象的颜色比其灰度强度更适合定义对象。然后,我们反向投影这个直方图去测试图像上查找这个目标。换句话说,我们计算每个像素属于地面的概率并显示它,结果显示我们需要的地面。
import numpy as np
import cv2
img = cv2.imread("assets/messi5.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
ground_patch = cv2.imread("assets/messi_ground.png")
ground_hsv = cv2.cvtColor(ground_patch, cv2.COLOR_BGR2HSV)
# 计算目标的直方图
ground_hist = cv2.calcHist([ground_hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
# 归一化
cv2.normalize(ground_hist, ground_hist, 0, 255, cv2.NORM_MINMAX)
# 反向投影
dst = cv2.calcBackProject([hsv], [0, 1], ground_hist, [0, 180, 0, 256], 1)
# 对投影图像做一些处理
ele = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
cv2.filter2D(dst, -1, ele, dst)
ret, thresh = cv2.threshold(dst, 50, 255, cv2.THRESH_BINARY)
# threshcolor = cv2.merge((thresh, thresh, thresh))
threshcolor = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
result = cv2.bitwise_and(threshcolor, img)
result = np.hstack((img, threshcolor, result))
cv2.imshow("result", result)
# cv2.imshow("src", img)
cv2.imshow("patch", ground_patch)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.calcBackProject( images, channels, hist, ranges, scale[, dst] ) -> dst
计算直方图的反向投影,其中一个参数是目标的直方图,是需要查找的目标。目标的直方图在传入之前需要归一化,返回一个概率图。然后用个特殊的核进行卷积,并进行阈值化。
- images: 输入图像数组,是一个list
- channels: 用于计算反向投影的通道,必须与待计算直方图通道来源一致;
- hist: 输入的直方图(待检目标的直方图)
- ranges: 与
calcHist
意思相同- scale: 可选参数,越大越精确