OpenCV学习笔记-直方图反向投影

直方图反向投影:
反向投影可以用来做图像分割,寻找感兴趣区间。它会输出与输入图像大小相同的图像,每一个像素值代表了输入图像上对应点属于目标对象的概率,简言之,输出图像中像素值越高的点越可能代表想要查找的目标。直方图投影经常与camshift(追踪算法)一起使用。

算法实现的方法:首先要为包含我们感兴趣区域的图像建立直方图(一个硬币)。被查找的对象最好是占据整个图像(一堆硬币)。最好使用颜色直方图,物体的颜色信息比灰度图像更容易被分割和识别。再将颜色直方图投影到输入图像查找目标,也就是找到输入图像中每一个像素点的像素值在直方图中对应的概率,这样就得到一个概率图像,最后设置适当的阈值对概率图像进行二值化。

反向投影图怎么计算呢?
我们把感兴趣区域的图像称为小图,目标图像称为大图。
从左上角开始,截取和小图一样大小的图像,作为临时图--》计算临时图的直方图,与小图的直方图比较--》得出一个对比值--》将这个对比值填在当前左上角的像素点上。

注意:1、是直方图和直方图的比较,不是像素点和直方图的比较。
          2、对比值不一定越大越相似,对比值的意义根据直方图比较算法的不同而不同
          3、每个像素点上的对比值    ,代表了大图中这个位置的点,属于小图的概率

具体代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

#roi图片,就是想要找的图片
roi = cv.imread('img/coins.png')
roi_hsv = cv.cvtColor(roi, cv.COLOR_BGR2HSV)

#目标搜索图片
target = cv.imread('img/target.jpg')
target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)

#计算目标直方图
roiHist = cv.calcHist([roi_hsv], [0, 1], None, [180, 256], [0, 180, 0 ,256])
#归一化,参数为原图像和输出图像,归一化后值全部在0到255的范围
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX)
dst = cv.calcBackProject([target_hsv], [0, 1], roiHist, [0, 180, 0, 256], 1)

#卷积连接分散的点
disc = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
dst = cv.filter2D(dst, -1, disc)

ret, thresh = cv.threshold(dst, 50, 255, 0)
#使用merge变成通道图像
thresh = cv.merge((thresh, thresh, thresh))

#蒙版
res = cv.bitwise_and(target,thresh)
#矩阵按列合并,就是把target。thresh和res三个图像横着拼在一起
res = np.hstack((target, thresh, res))

cv.imshow('img',res)
cv.waitKey(0)
cv.destroyAllWindows()

效果图:

原理部分参考:https://blog.csdn.net/tengfei461807914/article/details/77075567
                         walker1222的评论

猜你喜欢

转载自blog.csdn.net/qq_36387683/article/details/80319755