OpenCV-Python系列之直方图反投影

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OpenCV-Python系列之直⽅图反投影
OpenCV-Python系列之直⽅图反投影
本次教程我们将介绍OpenCV直⽅图部分的最后⼀个知识点——直⽅图反投影。

反向投影可以⽤来做图像分割,寻找感兴趣区间,类似于我们前⾯讲过的ROI区域分割。

它会输出与输⼊图像⼤⼩相同的图像,每⼀个像素值代表了输⼊图像上对应点属于⽬标对象的概率,简⾔之,输出图像中像素值越⾼的点越可能代表想要查找的⽬标。

直⽅图投影经常与camshift(追踪算法)算法⼀起使⽤。

更通俗⼀点,反向投影可以通过颜⾊直⽅图来理解,我们检测图像中某个像素点的颜⾊是否位于直⽅图中,如果位于则将颜⾊加亮,通过对图像的检测,得出结果图像,结果图像⼀定和直⽅图像匹配。

那么对于图像颜⾊的取样点越多,越能更好的找出⽬标图形。

这⾥直⽅图的作⽤在于提供⼀个⽐较标准(也就是模版),即对于要检测的图像来说,需要给它提供⼀个模版,⽤于识别出和模版相应的特征。

算法实现的⽅法,⾸先要为包含我们感兴趣区域的图像建⽴直⽅图。

被查找的对象最好是占据整个图像。

最好使⽤颜⾊直⽅图,物体的颜⾊信息⽐灰度图像更容易被分割和识别。

再将颜⾊直⽅图投影到输⼊图像查找⽬标,也就是找到输⼊图像中每⼀个像素点的像素值在直⽅图中对应的概率,这样就得到⼀个概率图像,最后设置适当的阈值对概率图像进⾏⼆值化。

经过上⾯的分析,下⾯给出反向投影的作⽤:反向投影⽤于在输⼊图像(通常较⼤)中查找特定图像(通常较⼩或者仅1个像素,以下将其称为模板图像)最匹配的点或者区域,也就是定位模板图像出现在输⼊图像的位置。

反向投影查找原理:查找的⽅式就是不断的在输⼊图像中切割跟模板图像⼤⼩⼀致的图像块,并⽤直⽅图对⽐的⽅式与模板图像进⾏⽐较。

假设我们有⼀张100x100的输⼊图像,有⼀张10x10的模板图像,查找的过程是这样的:
(1)从输⼊图像的左上⾓(0,0)开始,切割⼀块(0,0)⾄(10,10)的临时图像;
(2)⽣成临时图像的直⽅图;
(3)⽤临时图像的直⽅图和模板图像的直⽅图对⽐,对⽐结果记为c;
(4)直⽅图对⽐结果c,就是结果图像(0,0)处的像素值;
(5)切割输⼊图像从(0,1)⾄(10,11)的临时图像,对⽐直⽅图,并记录到结果图像;
(6)重复(1)~(5)步直到输⼊图像的右下⾓。

反向投影的结果包含了:以每个输⼊图像像素点为起点的直⽅图对⽐结果。

可以把它看成是⼀个⼆维的浮点型数组,⼆维矩阵,或者单通道的浮点型图像。

可以这样理解:对于calcBackProjectPatch,也就是是基于块的反向投影形式,利⽤直⽅图做匹配,类似于模板匹配,只不过这些模板转换为直⽅图,⽽原图中以某点为基准,抠出来作对⽐的部分也转换为直⽅图,两个直⽅图作匹配,匹配的结果作为此点的值,结果会是⼀张灰度图。

如果输⼊图像和模板图像⼀样⼤,那么反向投影相当于直⽅图对⽐。

如果输⼊图像⽐模板图像还⼩,那么则⽆法进⾏反向投影。

OpenCV提供了⼀个内置函数cv.calcBackProject()。

它的参数与cv.calcHist()函数⼏乎相同。

此外,在传递给Backproject函数之前,应该对象直⽅图进⾏标准化。

它返回概率图像,然后我们将图像与内核卷积并应⽤阈值。

接下来我们进⾏演⽰,模板图⽚:
原图:
来看代码:
def Back():
# roi图⽚,就想要找的的图⽚
roi = cv2.imread('temp.jpg')
hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
# ⽬标搜索图⽚
target = cv2.imread('cat.jpg')
hsvt = cv2.cvtColor(target, cv2.COLOR_BGR2HSV)
# 计算⽬标直⽅图
roihist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
# 归⼀化,参数为原图像和输出图像,归⼀化后值全部在2到255范围
cv2.normalize(roihist, roihist, 0, 255, cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt], [0, 1], roihist, [0, 180, 0, 256], 1)
# 卷积连接分散的点
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
dst = cv2.filter2D(dst, -1, disc)
ret, thresh = cv2.threshold(dst, 50, 255, 0)
# 使⽤merge变成通道图像
thresh = cv2.merge((thresh, thresh, thresh))
# 蒙板
res = cv2.bitwise_and(target, thresh)
# 矩阵按列合并,就是把target,thresh和res三个图⽚横着拼在⼀起
res = np.hstack((target, thresh, res))
cv2.imwrite('res.jpg', res)
# 显⽰图像
cv2.imshow('1', res)
cv2.waitKey(0)
这就是直⽅图反投影的应⽤,其从本质上来讲,原理类似于模板匹配,我们在之前讲过的轮廓特征⾥也有这种模板和原图的匹配的应⽤,这些我们综合起来联系看更加有趣。

截⾄到本次教程为⽌,OpenCV基础篇的应⽤就到此结束了,从下⼀个教程开始,我们将进⼊OpenCV进阶篇的学习,后⾯的内容会较之前复杂,但也更为有趣,同时功能更加强⼤。

相关文档
最新文档