meanshift追踪手动选框(python-opencv)
来源:互联网 发布:淘宝店铺处罚规则 编辑:程序博客网 时间:2024/05/29 16:30
在这篇文章里,我将会用python-opencv实现Meanshift,我将给出用鼠标框出追踪目标,实现追踪。
基于MeanShift的Camshift算法原理详解(整理)
meanshift算法思想其实很简单:利用概率密度的梯度爬升来寻找局部最优。它要做的就是输入一个在图像的范围,然后一直迭代(朝着重心迭代)直到满足你的要求为止。但是他是怎么用于做图像跟踪的呢?这是我自从学习meanshift以来,一直的困惑。而且网上也没有合理的解释。经过这几天的思考,和对反向投影的理解使得我对它的原理有了大致的认识。
在opencv中,进行meanshift其实很简单,输入一张图像(imgProb),再输入一个开始迭代的方框(windowIn)和一个迭代条件(criteria),输出的是迭代完成的位置(comp )。
这是函数原型:
int cvMeanShift( const void* imgProb, CvRect windowIn,
CvTermCriteria criteria, CvConnectedComp* comp )
但是当它用于跟踪时,这张输入的图像就必须是反向投影图了。
为什么必须是反向投影图呢?首先我们要理解什么是反向投影图。
简单理解它其实实际上是一张概率密度图。经过反向投影时的输入是一个目标图像的直方图(也可以认为是目标图像),还一个输入是当前图像就是你要跟踪的全图,输出大小与全图一样大,它上像素点表征着一种概率,就是全图上这个点是目标图像一部分的概率。如果这个点越亮,就说明这个点属于物体的概率越大。现在我们明白了这原来是一张概率图了。当用meanshift跟踪时,输入的原来是这样一幅图像,那也不难怪它可以进行跟踪了。
半自动跟踪思路:输入视频,用画笔圈出要跟踪的目标,然后对物体跟踪。
用过opencv的都知道,这其实是camshiftdemo的工作过程。
第一步:选中物体,记录你输入的方框和物体。
第二步:求出视频中有关物体的反向投影图。
第三步:根据反向投影图和输入的方框进行meanshift迭代,由于它是向重心移动,即向反向投影图中概率大的地方移动,所以始终会移动到目标上。
第四步:然后下一帧图像时用上一帧输出的方框来迭代即可。
全自动跟踪思路:输入视频,对运动物体进行跟踪。
第一步:运用运动检测算法将运动的物体与背景分割开来。
第二步:提取运动物体的轮廓,并从原图中获取运动图像的信息。
第三步:对这个信息进行反向投影,获取反向投影图。
第四步:根据反向投影图和物体的轮廓(也就是输入的方框)进行meanshift迭代,由于它是向重心移 动,即向反向投影图中概率大的地方移动,所以始终会移动到物体上。
第五步:然后下一帧图像时用上一帧输出的方框来迭代即可。
总结:用meanshift进行跟踪最重要的一点是输入图像的把握,也就是要让它的迭代能越来越迭代到目标上。这种图像也不一定就是反向投影图,只要是一幅反映当前图像中每个像素点含有目标概率图就可以了,其实反向投影图就是这样的一幅图而已。
meanShift算法用于视频目标跟踪时,采用目标的颜色直方图作为搜索特征,通过不断迭代meanShift向量使得算法收敛于目标的真实位置,从而达到跟踪的目的。
传统的meanShift算法在跟踪中有几个优势:
(1)算法计算量不大,在目标区域已知的情况下完全可以做到实时跟踪;
(2)采用核函数直方图模型,对边缘遮挡、目标旋转、变形和背景运动不敏感。
同时,meanShift算法也存在着以下一些缺点:
(1)缺乏必要的模板更新;
(2)跟踪过程中由于窗口宽度大小保持不变,当目标尺度有所变化时,跟踪就会失败;
(3)当目标速度较快时,跟踪效果不好;
(4)直方图特征在目标颜色特征描述方面略显匮乏,缺少空间信息;
由于其计算速度快,对目标变形和遮挡有一定的鲁棒性,所以,在目标跟踪领域,meanShift算法目前依然受到大家的重视。但考虑到其缺点,在工程实际中也可以对其作出一些改进和调整;例如:
(1)引入一定的目标位置变化的预测机制,从而更进一步减少meanShift跟踪的搜索时间,降低计算量;
(2)可以采用一定的方式来增加用于目标匹配的“特征”;
(3)将传统meanShift算法中的核函数固定带宽改为动态变化的带宽;
(4)采用一定的方式对整体模板进行学习和更新;
# -*- coding: utf-8 -*-import numpy as npimport cv2current_pos = Nonetl = Nonebr = None#鼠标事件def get_rect(im, title='get_rect'): mouse_params = {'tl': None, 'br': None, 'current_pos': None,'released_once': False} cv2.namedWindow(title) cv2.moveWindow(title, 100, 100) def onMouse(event, x, y, flags, param): param['current_pos'] = (x, y) if param['tl'] is not None and not (flags & cv2.EVENT_FLAG_LBUTTON): param['released_once'] = True if flags & cv2.EVENT_FLAG_LBUTTON: if param['tl'] is None: param['tl'] = param['current_pos'] elif param['released_once']: param['br'] = param['current_pos'] cv2.setMouseCallback(title, onMouse, mouse_params) cv2.imshow(title, im) while mouse_params['br'] is None: im_draw = np.copy(im) if mouse_params['tl'] is not None: cv2.rectangle(im_draw, mouse_params['tl'], mouse_params['current_pos'], (255, 0, 0)) cv2.imshow(title, im_draw) _ = cv2.waitKey(10) cv2.destroyWindow(title) tl = (min(mouse_params['tl'][0], mouse_params['br'][0]), min(mouse_params['tl'][1], mouse_params['br'][1])) br = (max(mouse_params['tl'][0], mouse_params['br'][0]), max(mouse_params['tl'][1], mouse_params['br'][1])) return (tl, br)cap = cv2.VideoCapture('Bolt.mp4')# 读取摄像头第一帧图像ret, frame = cap.read()while True: ret, frame = cap.read() if ret == True: break# 初始化位置窗口#r,h,c,w = 250,90,400,125 # simply hardcoded the valuesr,h,c,w=15,370,319,87 #初始位置#a1,a2 = get_rect(frame, title='get_rect') 手动选框#r,h,c,w = a1[1],a2[1]-a1[1],a1[0],a2[0]-a1[0] 手动选框track_window = (c,r,w,h)# 设置所要跟踪的ROIroi = frame[r:r+h, c:c+w]hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)# 设置终止条件term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )while(1): ret ,frame = cap.read() if ret == True: hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1) # apply meanshift to get the new location ret, track_window = cv2.meanShift(dst, track_window, term_crit) # Draw it on image x,y,w,h = track_window cv2.rectangle(frame, (x,y), (x+w,y+h), 255,2) cv2.imshow('img2',frame) k = cv2.waitKey(10) & 0xff if k == 27: break #else: # cv2.imwrite(chr(k)+".jpg",img2) else: breakcv2.destroyAllWindows()cap.release()
- meanshift追踪手动选框(python-opencv)
- CamShift、MeanShift运动追踪
- meanShift 追踪算法
- 目标追踪-meanshift算法
- Python+OpenCV学习(13)---meanshift目标跟踪
- python+opencv实现动态物体追踪
- Opencv之meanshift篇
- 对opencv MeanShift 融合矩形框的改进
- opencv中的meanshift图像分割
- OpenCV meanshift 图像分割代码
- OpenCV meanshift目标跟踪总结
- OpenCV之meanshift分割详解
- OpenCV meanshift目标跟踪总结
- python-opencv时间计算,视频物体追踪标记
- OPENCV运动追踪研究和PYTHON及JAVA实现
- meanshift算法学习(二):opencv中的meanshift
- opencv实现运动追踪
- opencv点目标追踪
- 详解spring 每个jar的作用
- UVa 12161 Ironman Race in Treeland(树分治)
- Leetcode--Two Sum
- lwip TCP client & FreeRTOS 打开TCP 的 保活机制 LWIP_TCP_KEEPALIVE==1
- CSU 1233: 病毒的复制 矩阵快速幂
- meanshift追踪手动选框(python-opencv)
- stl之双端队列deque
- hdu-6092-Rikka with Subset(思维)
- 散列查找
- CSU 1092: Barricade (dijkstra+heap)
- 如何正确地写出单例模式
- 图文混排
- CodeForces
- Maven分离配置、依赖