直方图反向投影:
反向投影可以用来做图像分割,寻找感兴趣区间。它会输出与输入图像大小相同的图像,每一个像素值代表了输入图像上对应点属于目标对象的概率,简言之,输出图像中像素值越高的点越可能代表想要查找的目标。直方图投影经常与camshift(追踪算法)一起使用。
算法实现的方法:首先要为包含我们感兴趣区域的图像建立直方图(紫色衣服)。被查找的对象最好是占据整个图像上。最好使用颜色直方图,物体的颜色信息比灰度图像更容易被分割和识别。再将颜色直方图投影到输入图像查找目标,也就是找到输入图像中每一个像素点的像素值在直方图中对应的概率,这样就得到一个概率图像,最后设置适当的阈值对概率图像进行二值化。
反向投影图计算方法:
我们把感兴趣区域的图像称为小图,目标图像称为大图。
从左上角开始,截取和小图一样大小的图像,作为临时图–》计算临时图的直方图,与小图的直方图比较–》得出一个对比值–》将这个对比值填在当前左上角的像素点上。
注意:1、是直方图和直方图的比较,不是像素点和直方图的比较。
2、对比值不一定越大越相似,对比值的意义根据直方图比较算法的不同而不同
3、每个像素点上的对比值 ,代表了大图中这个位置的点,属于小图的概率
代码实现:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#直方图反向投影
def back_projection_demo():
sample = cv.imread("D:/javaopencv/sample.png")
target = cv.imread("D:/javaopencv/target.png")
roi_hsv = cv.cvtColor(sample, cv.COLOR_BGR2HSV)#转到hsv色彩空间
target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)
# show images
cv.imshow("sample", sample)
cv.imshow("target", target)
# 用calcHist来找直方图(也可以用np.histogram2d) ,[0, 1], 计算两个通道,[32, 32]:bins,可以通过调整它改变结果
roiHist = cv.calcHist([roi_hsv], [0, 1], None, [32, 32], [0, 180, 0, 256])#[0, 180, 0, 256]:h s的取值范围
# 归一化之后的直方图便于显示,归一化之后就成了 0 到 255 之间的数了。
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX)
dst = cv.calcBackProject([target_hsv], [0, 1], roiHist, [0, 180, 0, 256], 1)
cv.imshow("backProjectionDemo", dst)
#2d直方图
def hist2d_demo(image):
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
hist = cv.calcHist([image], [0, 1], None, [32, 32], [0, 180, 0, 256])
#cv.imshow("hist2d", hist)
plt.imshow(hist, interpolation='nearest')
plt.title("2D Histogram")
plt.show()
print("--------- Hello Python ---------")
src = cv.imread("D:/vcprojects/images/demo.png")
#hist2d_demo(src)
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
hist2d_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()