基于图像序列的目标光线追踪算法法如何确定算法的处理速度

视频跟踪:基于对比度分析的目标跟踪、基于匹配的目标跟踪和基于运动检测的目标跟踪& & &&基于对比度分析的目标跟踪:主要利用目标和背景的对比度差异实现目标的检测与跟踪。这类算法按照跟踪参考点的不同可以分为边缘跟踪# 形心跟踪和质心
& & & & & &&跟踪等。这类算法不适合复杂背景中的目标跟踪"但在空中背景下的目标跟踪中非常有效。
& & &基于匹配的目标跟踪:主要通过前后帧之间的特征匹配实现目标的定位。& & & & &
& & & & & 特征匹配:特征是目标可区别与其他事物的属性, 具有可区分性、可靠性、独立性和稀疏性。基于匹配的目标跟踪算法需要提取目标的特征,并在每一帧中寻找该特征。
& & & & & & & &寻找的过程就是特征匹配的过程。目标跟踪中用到的特征主要有几何形状、子空间特征、外形轮廓和特征点等, 其中特征点是匹配算法中常用的特征。目标特征的变
& & & & & & & &化具有随机性。这种随机变化可以采用统计数学的方法来描述。直方图是图像处理中天然的统计量。因此彩色和边缘方向直方图在跟踪算法中被广泛采用。& &
& & & && 贝叶斯跟踪:目标的运动往往是随机的,这样的运动过程可以采用随机过程来描述。随机过程的处理在信号分析领域较成熟,其理论和技术(如贝叶斯滤波)可以借鉴到目标跟踪中。
& & & & &核方法:核方法的基本思想是对相似度概率密度函数或者后验概率密度函数采用直接的连续估计,这样处理一方面可以简化采样, 另一方面可以采用估计的函数梯度有效定位采样粒子。
& & & & &采用连续概率密度函数可以减少高维状态空间引起的计算量问题, 还可以保证例子接近分布模式,避免粒子退化问题,核方法一般都采用彩色直方图作为匹配特征。
& & & &&基于运动检测的目标跟踪:主要根据目标运动和背景运动之间的差异实现目标的检测和跟踪。基于运动检测的目标跟踪算法通过检测序列图像中目标和背景的不同运动来发现目标存在的区域,
& & & & & & & 实现跟踪。这类算法不需要帧间的模式匹配,不需要在帧间传递目标的运动参数,只需要突出目标和非目标在时域或空域的区别即可。这类算法具有检测多个目标的能力,可用于多目标检
& & & & & & & 测和跟踪,这类运动目标检测方法主要有帧间图像差分法,背景估计法,能量积累法,运动场估计法等。
& & & & & & & & & 光流算法是基于运动检测的目标跟踪的代表性算法 ,光流是空间运动物体在成像面上的像素运动的瞬时速度,光流矢量是图像平面坐标点上的灰度瞬时变化率,光流的计算利用图像序列
& & & & & & &中的像素灰度分布的时域变化和相关性来确定各自像素位置的运动。研究图像灰度在时间上的变化与景象中物体结构及其运动的关系,将二维速度场与灰度相联系。引入光流约束方程,
& & & & & & &得到光流计算的基本算法。根据计算方法的不同,可以将光流算法分为基于梯度的方法,基于匹配的方法,基于能量的方法,基于相位的方法和基于神经动力学的方法。
& & & & & & & & & &&
& & & & & & & & &&前两类方法都是对单帧图像进行处理,基于匹配的跟踪方法需要在帧与帧之间传递目标信息,对比度跟踪不需要在帧与帧之间传递目标信息, 基于运动检测的跟踪需要对多帧图像进行处理。
& & & & & &另参考:/zjb0823/p/3806333.html
阅读(...) 评论()工具类服务
编辑部专用服务
作者专用服务
基于视频图像序列的运动目标检测与跟踪算法研究
计算机视觉与图像处理是当今计算机科学领域的一个热门研究方向之一,在交通视频监控、航空航天、机器人视觉、医学图像分析等领域有着很重要的应用,现如今相关领域的很多研究者都认为该学科具有很好的研究潜力,未来市场很广。对运动目标准确地检测与定位追踪是研究计算机视觉最基本相关的两个过程。实现目标的检测与定位追踪需首先要能精确的检测出目标和对前景的恢复构建,然后才能达到追踪稳定、有序。基于关键技术环节的分析研究,本文分为以下三个部分进行系统的研究:  一、对于移动物体检测的研究,主要对比实现了最基本的两种移动目标检测算法:帧间差分法和背景减除法,分别从相应的算法理论、算法操作以及算法验证仿真三个部分做了细致讨论,并讨论研究了每种算法的优劣之处。  二、对于移动物体定位追踪的研究,对最理论基础的Mean Shift物体定位方法进行了研究仿真。具体研究了Mean Shift原理及其改进之处,Mean Shift应用中彩色模型的选择以及运用Mean Shift目标定位方法的实现过程,并运用测试实验讨论了Mean Shift方法在目标处于不同是状况情景下的定位结果分析。测试结果可知基本Mean Shift定位方法在目标运动速度不快时,可以准确定位追踪。然而,目标快速移动或处于被干扰物体挡住时,此算法使用便无法实现目标。  三、解决对目标移动快以及目标处于被干扰状况下定位失效的问题,论文找到了一种新的结合两种定位算法的改进算法,这两种算法是Mean Shift物体追踪与Kalman滤波器定位方法。论文主要通过下述三个步骤进行逐步的研究:1、分析讲述了如何对Kalman滤波器构造模型,进而把它的预测特性引入目标定位里,便完成了两种方法的联合。2、为解决目标处于被干扰状况的无法定位难题,论文找出了利用巴式因子测试干扰及相关预测的办法;3、经过多次验证测试,给出了新算法在这两问题里的解决效果。在比较讨论了新算法与基本算法之后,可以证明新结合算法可以实现在以上两种情境下仍能稳定有效的定位,与原来的基本Mean Shift定位方法对照,论文提出算法有很好改善。  论文解决了目标移动速度很快时的传统定位算法无法达到的困境,实现了以种新的与Kalman滤波器联合的新算法,可以实现快速移动下也能很好的定位目标。同时,对另一个目标受到干扰的问题,实现了对此情况传下甄别干扰及相应应对的办法,能够改善目标受干扰下的定位效果。
学科专业:
授予学位:
学位授予单位:
导师姓名:
学位年度:
在线出版日期:
本文读者也读过
相关检索词
万方数据知识服务平台--国家科技支撑计划资助项目(编号:2006BAH03B01)(C)北京万方数据股份有限公司
万方数据电子出版社图像识别算法(46)

这次将介绍基于MeanShift的目标跟踪算法,首先谈谈简介,然后给出算法实现流程,最后实现了一个单目标跟踪的MeanShift算法【matlab/c两个版本】
&&&&& csdn贴公式比较烦,原谅我直接截图了…
&&&& 首先扯扯无参密度估计理论,无参密度估计也叫做非参数估计,属于数理统计的一个分支,和参数密度估计共同构成了概率密度估计方法。参数密度估计方法要求特征空间服从一个已知的概率密度函数,在实际的应用中这个条件很难达到。而无参数密度估计方法对先验知识要求最少,完全依靠训练数据进行估计,并且可以用于任意形状的密度估计。所以依靠无参密度估计方法,即不事先规定概率密度函数的结构形式,在某一连续点处的密度函数值可由该点邻域中的若干样本点估计得出。常用的无参密度估计方法有:直方图法、最近邻域法和核密度估计法。
&&&& MeanShift算法正是属于核密度估计法,它不需要任何先验知识而完全依靠特征空间中样本点的计算其密度函数值。对于一组采样数据,直方图法通常把数据的值域分成若干相等的区间,数据按区间分成若干组,每组数据的个数与总参数个数的比率就是每个单元的概率值;核密度估计法的原理相似于直方图法,只是多了一个用于平滑数据的核函数。采用核函数估计法,在采样充分的情况下,能够渐进地收敛于任意的密度函数,即可以对服从任何分布的数据进行密度估计。
&&&& 然后谈谈MeanShift的基本思想及物理含义:
&&& 此外,从公式1中可以看到,只要是落入Sh的采样点,无论其离中心x的远近,对最终的Mh(x)计算的贡献是一样的。然而在现实跟踪过程中,当跟踪目标出现遮挡等影响时,由于外层的像素值容易受遮挡或背景的影响,所以目标模型中心附近的像素比靠外的像素更可靠。因此,对于所有采样点,每个样本点的重要性应该是不同的,离中心点越远,其权值应该越小。故引入核函数和权重系数来提高跟踪算法的鲁棒性并增加搜索跟踪能力。
&&&&&&接下来,谈谈核函数:
&&& 核函数也叫窗口函数,在核估计中起到平滑的作用。常用的核函数有:Uniform,Epannechnikov,Gaussian等。本文算法只用到了Epannechnikov,它数序定义如下:
二、基于MeanShift的目标跟踪算法
&&&& 基于均值漂移的目标跟踪算法通过分别计算目标区域和候选区域内像素的特征值概率得到关于目标模型和候选模型的描述,然后利用相似函数度量初始帧目标模型和当前帧的候选模版的相似性,选择使相似函数最大的候选模型并得到关于目标模型的Meanshift向量,这个向量正是目标由初始位置向正确位置移动的向量。由于均值漂移算法的快速收敛性,通过不断迭代计算Meanshift向量,算法最终将收敛到目标的真实位置,达到跟踪的目的。
&&&& 下面通过图示直观的说明MeanShift跟踪算法的基本原理。如下图所示:目标跟踪开始于数据点xi0(空心圆点xi0,xi1,…,xiN表示的是中心点,上标表示的是的迭代次数,周围的黑色圆点表示不断移动中的窗口样本点,虚线圆圈代表的是密度估计窗口的大小)。箭头表示样本点相对于核函数中心点的漂移向量,平均的漂移向量会指向样本点最密集的方向,也就是梯度方向。因为
Meanshift 算法是收敛的,因此在当前帧中通过反复迭代搜索特征空间中样本点最密集的区域,搜索点沿着样本点密度增加的方向“漂移”到局部密度极大点点xiN,也就是被认为的目标位置,从而达到跟踪的目的,MeanShift 跟踪过程结束。
运动目标的实现过程【具体算法】:
三、代码实现
1.&&&&&& RGB颜色空间刨分,采用16*16*16的直方图
2.&&&&&& 目标模型和候选模型的概率密度计算公式参照上文
3.&&&&&& opencv版本运行:按P停止,截取目标,再按P,进行单目标跟踪
4.&&&&&& Matlab版本,将视频改为图片序列,第一帧停止,手工标定目标,双击目标区域,进行单目标跟踪。
matlab版本:
function&[]&=&select()&&close&&&clear&&&%%%%%%%%%%%%%%%%%%根据一幅目标全可见的图像圈定跟踪目标%%%%%%%%%%%%%%%%%%%%%%%&&I=imread('result72.jpg');&&figure(1);&&imshow(I);&&&&&&[temp,rect]=imcrop(I);&&[a,b,c]=size(temp);&&&&&&&&&%a:row,b:col&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%计算目标图像的权值矩阵%%%%%%%%%%%%%%%%%%%%%%%&&y(1)=a/2;&&y(2)=b/2;&&tic_x=rect(1)+rect(3)/2;&&tic_y=rect(2)+rect(4)/2;&&m_wei=zeros(a,b);%权值矩阵&&h=y(1)^2+y(2)^2&;%带宽&&&&&&for&i=1:a&&&&&&for&j=1:b&&&&&&&&&&dist=(i-y(1))^2+(j-y(2))^2;&&&&&&&&&&m_wei(i,j)=1-dist/h;&%epanechnikov&profile&&&&&&end&&end&&C=1/sum(sum(m_wei));%归一化系数&&&&&&%计算目标权值直方图qu&&%hist1=C*wei_hist(temp,m_wei,a,b);%target&model&&hist1=zeros(1,4096);&&for&i=1:a&&&&&&for&j=1:b&&&&&&&&&&%rgb颜色空间量化为16*16*16&bins&&&&&&&&&&q_r=fix(double(temp(i,j,1))/16);&&%fix为趋近0取整函数&&&&&&&&&&q_g=fix(double(temp(i,j,2))/16);&&&&&&&&&&q_b=fix(double(temp(i,j,3))/16);&&&&&&&&&&q_temp=q_r*256+q_g*16+q_b;&&&&&&&&&&&&%设置每个像素点红色、绿色、蓝色分量所占比重&&&&&&&&&&hist1(q_temp+1)=&hist1(q_temp+1)+m_wei(i,j);&&&&%计算直方图统计中每个像素点占的权重&&&&&&end&&end&&hist1=hist1*C;&&rect(3)=ceil(rect(3));&&rect(4)=ceil(rect(4));&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%读取序列图像&&myfile=dir('D:\matlab7\work\mean&shift\image\*.jpg');&&lengthfile=length(myfile);&&&&&&for&l=1:lengthfile&&&&&&Im=imread(myfile(l).name);&&&&&&num=0;&&&&&&Y=[2,2];&&&&&&&&&&&&&&&&&&%%%%%%%mean&shift迭代&&&&&&while((Y(1)^2+Y(2)^2&0.5)&num&20)&&&%迭代条件&&&&&&&&&&num=num+1;&&&&&&&&&&temp1=imcrop(Im,rect);&&&&&&&&&&%计算侯选区域直方图&&&&&&&&&&%hist2=C*wei_hist(temp1,m_wei,a,b);%target&candidates&pu&&&&&&&&&&hist2=zeros(1,4096);&&&&&&&&&&for&i=1:a&&&&&&&&&&&&&&for&j=1:b&&&&&&&&&&&&&&&&&&q_r=fix(double(temp1(i,j,1))/16);&&&&&&&&&&&&&&&&&&q_g=fix(double(temp1(i,j,2))/16);&&&&&&&&&&&&&&&&&&q_b=fix(double(temp1(i,j,3))/16);&&&&&&&&&&&&&&&&&&q_temp1(i,j)=q_r*256+q_g*16+q_b;&&&&&&&&&&&&&&&&&&hist2(q_temp1(i,j)+1)=&hist2(q_temp1(i,j)+1)+m_wei(i,j);&&&&&&&&&&&&&&end&&&&&&&&&&end&&&&&&&&&&hist2=hist2*C;&&&&&&&&&&figure(2);&&&&&&&&&&subplot(1,2,1);&&&&&&&&&&plot(hist2);&&&&&&&&&&hold&&&&&&&&&&&&&&&&&&&&&w=zeros(1,4096);&&&&&&&&&&for&i=1:4096&&&&&&&&&&&&&&if(hist2(i)~=0)&%不等于&&&&&&&&&&&&&&&&&&w(i)=sqrt(hist1(i)/hist2(i));&&&&&&&&&&&&&&else&&&&&&&&&&&&&&&&&&w(i)=0;&&&&&&&&&&&&&&end&&&&&&&&&&end&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%变量初始化&&&&&&&&&&sum_w=0;&&&&&&&&&&xw=[0,0];&&&&&&&&&&for&i=1:a;&&&&&&&&&&&&&&for&j=1:b&&&&&&&&&&&&&&&&&&sum_w=sum_w+w(uint32(q_temp1(i,j))+1);&&&&&&&&&&&&&&&&&&xw=xw+w(uint32(q_temp1(i,j))+1)*[i-y(1)-0.5,j-y(2)-0.5];&&&&&&&&&&&&&&end&&&&&&&&&&end&&&&&&&&&&Y=xw/sum_w;&&&&&&&&&&%中心点位置更新&&&&&&&&&&rect(1)=rect(1)+Y(2);&&&&&&&&&&rect(2)=rect(2)+Y(1);&&&&&&end&&&&&&&&&&&&&&&&&&%%%跟踪轨迹矩阵%%%&&&&&&tic_x=[tic_x;rect(1)+rect(3)/2];&&&&&&tic_y=[tic_y;rect(2)+rect(4)/2];&&&&&&&&&&&&v1=rect(1);&&&&&&v2=rect(2);&&&&&&v3=rect(3);&&&&&&v4=rect(4);&&&&&&%%%显示跟踪结果%%%&&&&&&subplot(1,2,2);&&&&&&imshow(uint8(Im));&&&&&&title('目标跟踪结果及其运动轨迹');&&&&&&hold&&&&&&&plot([v1,v1+v3],[v2,v2],[v1,v1],[v2,v2+v4],[v1,v1+v3],[v2+v4,v2+v4],[v1+v3,v1+v3],[v2,v2+v4],'LineWidth',2,'Color','r');&&&&&&plot(tic_x,tic_y,'LineWidth',2,'Color','b');&&&&&&&&&&&&&&end&&
function [] = select()
%%%%%%%%%%%%%%%%%%根据一幅目标全可见的图像圈定跟踪目标%%%%%%%%%%%%%%%%%%%%%%%
I=imread('result72.jpg');
figure(1);
imshow(I);
[temp,rect]=imcrop(I);
[a,b,c]=size(temp);
%a:row,b:col
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%计算目标图像的权值矩阵%%%%%%%%%%%%%%%%%%%%%%%
tic_x=rect(1)+rect(3)/2;
tic_y=rect(2)+rect(4)/2;
m_wei=zeros(a,b);%权值矩阵
h=y(1)^2+y(2)^2 ;%带宽
dist=(i-y(1))^2+(j-y(2))^2;
m_wei(i,j)=1-dist/h; %epanechnikov profile
C=1/sum(sum(m_wei));%归一化系数
%计算目标权值直方图qu
%hist1=C*wei_hist(temp,m_wei,a,b);%target model
hist1=zeros(1,4096);
%rgb颜色空间量化为16*16*16 bins
q_r=fix(double(temp(i,j,1))/16);
%fix为趋近0取整函数
q_g=fix(double(temp(i,j,2))/16);
q_b=fix(double(temp(i,j,3))/16);
q_temp=q_r*256+q_g*16+q_b;
%设置每个像素点红色、绿色、蓝色分量所占比重
hist1(q_temp+1)= hist1(q_temp+1)+m_wei(i,j);
%计算直方图统计中每个像素点占的权重
hist1=hist1*C;
rect(3)=ceil(rect(3));
rect(4)=ceil(rect(4));
%%%%%%%%%%%%%%%%%%%%%%%%%读取序列图像
myfile=dir('D:\matlab7\work\mean shift\image\*.jpg');
lengthfile=length(myfile);
for l=1:lengthfile
Im=imread(myfile(l).name);
%%%%%%%mean shift迭代
while((Y(1)^2+Y(2)^2&0.5)&num&20)
num=num+1;
temp1=imcrop(Im,rect);
%计算侯选区域直方图
%hist2=C*wei_hist(temp1,m_wei,a,b);%target candidates pu
hist2=zeros(1,4096);
q_r=fix(double(temp1(i,j,1))/16);
q_g=fix(double(temp1(i,j,2))/16);
q_b=fix(double(temp1(i,j,3))/16);
q_temp1(i,j)=q_r*256+q_g*16+q_b;
hist2(q_temp1(i,j)+1)= hist2(q_temp1(i,j)+1)+m_wei(i,j);
hist2=hist2*C;
figure(2);
subplot(1,2,1);
plot(hist2);
w=zeros(1,4096);
for i=1:4096
if(hist2(i)~=0) %不等于
w(i)=sqrt(hist1(i)/hist2(i));
%变量初始化
for i=1:a;
sum_w=sum_w+w(uint32(q_temp1(i,j))+1);
xw=xw+w(uint32(q_temp1(i,j))+1)*[i-y(1)-0.5,j-y(2)-0.5];
Y=xw/sum_w;
%中心点位置更新
rect(1)=rect(1)+Y(2);
rect(2)=rect(2)+Y(1);
%%%跟踪轨迹矩阵%%%
tic_x=[tic_x;rect(1)+rect(3)/2];
tic_y=[tic_y;rect(2)+rect(4)/2];
v1=rect(1);
v2=rect(2);
v3=rect(3);
v4=rect(4);
%%%显示跟踪结果%%%
subplot(1,2,2);
imshow(uint8(Im));
title('目标跟踪结果及其运动轨迹');
plot([v1,v1+v3],[v2,v2],[v1,v1],[v2,v2+v4],[v1,v1+v3],[v2+v4,v2+v4],[v1+v3,v1+v3],[v2,v2+v4],'LineWidth',2,'Color','r');
plot(tic_x,tic_y,'LineWidth',2,'Color','b');
&运行结果:
opencv版本:
#include&&stdafx.h&&&#include&&cv.h&&&#include&&highgui.h&&&#define&&u_char&unsigned&char&&#define&&DIST&0.5&&#define&&NUM&20&&&&&&bool&pause&=&false;&&bool&is_tracking&=&false;&&CvRect&drawing_&&IplImage&*&&double&*hist1,&*hist2;&&double&*m_&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&double&C&=&0.0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&void&init_target(double&*hist1,&double&*m_wei,&IplImage&*current)&&{&&&&&&IplImage&*pic_hist&=&0;&&&&&&int&t_h,&t_w,&t_x,&t_y;&&&&&&double&h,&&&&&&&int&i,&j;&&&&&&int&q_r,&q_g,&q_b,&q_&&&&&&&&&&&&t_h&=&drawing_box.&&&&&&t_w&=&drawing_box.&&&&&&t_x&=&drawing_box.x;&&&&&&t_y&=&drawing_box.y;&&&&&&&&h&=&pow(((double)t_w)/2,2)&+&pow(((double)t_h)/2,2);&&&&&&&&&&&&&&&&&&pic_hist&=&cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);&&&&&&&&&&&&&&&&&&&for&(i&=&0;i&&&t_w*t_h;i++)&&&&&&{&&&&&&&&&&m_wei[i]&=&0.0;&&&&&&}&&&&&&&&for&(i=0;i&4096;i++)&&&&&&{&&&&&&&&&&hist1[i]&=&0.0;&&&&&&}&&&&&&&&for&(i&=&0;i&&&t_h;&i++)&&&&&&{&&&&&&&&&&for&(j&=&0;j&&&t_w;&j++)&&&&&&&&&&{&&&&&&&&&&&&&&dist&=&pow(i&-&(double)t_h/2,2)&+&pow(j&-&(double)t_w/2,2);&&&&&&&&&&&&&&m_wei[i&*&t_w&+&j]&=&1&-&dist&/&h;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&C&+=&m_wei[i&*&t_w&+&j]&;&&&&&&&&&&}&&&&&&}&&&&&&&&&&&&&&for&(i&=&t_y;i&&&t_y&+&t_h;&i++)&&&&&&{&&&&&&&&&&for&(j&=&t_x;j&&&t_x&+&t_w;&j++)&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&q_r&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&2])&/&16;&&&&&&&&&&&&&&q_g&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&1])&/&16;&&&&&&&&&&&&&&q_b&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&0])&/&16;&&&&&&&&&&&&&&q_temp&=&q_r&*&256&+&q_g&*&16&+&q_b;&&&&&&&&&&&&&&hist1[q_temp]&=&&hist1[q_temp]&+&&m_wei[(i&-&t_y)&*&t_w&+&(j&-&t_x)]&;&&&&&&&&&&}&&&&&&}&&&&&&&&&&&&&&for&(i=0;i&4096;i++)&&&&&&{&&&&&&&&&&hist1[i]&=&hist1[i]&/&C;&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&double&temp_max=0.0;&&&&&&&&for&(i&=&0;i&&&4096;i++)&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&if&(temp_max&&&hist1[i])&&&&&&&&&&{&&&&&&&&&&&&&&temp_max&=&hist1[i];&&&&&&&&&&}&&&&&&}&&&&&&&&&&&&CvPoint&p1,p2;&&&&&&double&bin_width=(double)pic_hist-&width/4096;&&&&&&double&bin_unith=(double)pic_hist-&height/temp_&&&&&&&&for&(i&=&0;i&&&4096;&i++)&&&&&&{&&&&&&&&&&p1.x&=&i&*&bin_&&&&&&&&&&p1.y&=&pic_hist-&&&&&&&&&&&p2.x&=&(i&+&1)*bin_&&&&&&&&&&p2.y&=&pic_hist-&height&-&hist1[i]&*&bin_&&&&&&&&&&&&&&&&&&&&cvRectangle(pic_hist,p1,p2,cvScalar(0,255,0),-1,8,0);&&&&&&}&&&&&&cvSaveImage(&hist1.jpg&,pic_hist);&&&&&&cvReleaseImage(&pic_hist);&&}&&&&void&MeanShift_Tracking(IplImage&*current)&&{&&&&&&int&num&=&0,&i&=&0,&j&=&0;&&&&&&int&t_w&=&0,&t_h&=&0,&t_x&=&0,&t_y&=&0;&&&&&&double&*w&=&0,&*hist2&=&0;&&&&&&double&sum_w&=&0,&x1&=&0,&x2&=&0,y1&=&2.0,&y2&=&2.0;&&&&&&int&q_r,&q_g,&q_b;&&&&&&int&*q_&&&&&&IplImage&*pic_hist&=&0;&&&&&&&&t_w&=&drawing_box.&&&&&&t_h&=&drawing_box.&&&&&&&&&&&&pic_hist&=&cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);&&&&&&&&&&&hist2&=&(double&*)malloc(sizeof(double)*4096);&&&&&&w&=&(double&*)malloc(sizeof(double)*4096);&&&&&&q_temp&=&(int&*)malloc(sizeof(int)*t_w*t_h);&&&&&&&&while&((pow(y2,2)&+&pow(y1,2)&&&0.5)&&&(num&&&NUM))&&&&&&{&&&&&&&&&&num++;&&&&&&&&&&t_x&=&drawing_box.x;&&&&&&&&&&t_y&=&drawing_box.y;&&&&&&&&&&memset(q_temp,0,sizeof(int)*t_w*t_h);&&&&&&&&&&for&(i&=&0;i&4096;i++)&&&&&&&&&&{&&&&&&&&&&&&&&w[i]&=&0.0;&&&&&&&&&&&&&&hist2[i]&=&0.0;&&&&&&&&&&}&&&&&&&&&&&&for&(i&=&t_y;i&&&t_h&+&t_y;i++)&&&&&&&&&&{&&&&&&&&&&&&&&for&(j&=&t_x;j&&&t_w&+&t_x;j++)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&q_r&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&2])&/&16;&&&&&&&&&&&&&&&&&&q_g&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&1])&/&16;&&&&&&&&&&&&&&&&&&q_b&=&((u_char)current-&imageData[i&*&current-&widthStep&+&j&*&3&+&0])&/&16;&&&&&&&&&&&&&&&&&&q_temp[(i&-&t_y)&*t_w&+&j&-&t_x]&=&q_r&*&256&+&q_g&*&16&+&q_b;&&&&&&&&&&&&&&&&&&hist2[q_temp[(i&-&t_y)&*t_w&+&j&-&t_x]]&=&&hist2[q_temp[(i&-&t_y)&*t_w&+&j&-&t_x]]&+&&m_wei[(i&-&t_y)&*&t_w&+&j&-&t_x]&;&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&for&(i=0;i&4096;i++)&&&&&&&&&&{&&&&&&&&&&&&&&hist2[i]&=&hist2[i]&/&C;&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&double&temp_max=0.0;&&&&&&&&&&&&for&(i=0;i&4096;i++)&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&if&(temp_max&&&hist2[i])&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&temp_max&=&hist2[i];&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&CvPoint&p1,p2;&&&&&&&&&&double&bin_width=(double)pic_hist-&width/(4368);&&&&&&&&&&double&bin_unith=(double)pic_hist-&height/temp_&&&&&&&&&&&&for&(i&=&0;i&&&4096;&i++)&&&&&&&&&&{&&&&&&&&&&&&&&p1.x&=&i&*&bin_&&&&&&&&&&&&&&p1.y&=&pic_hist-&&&&&&&&&&&&&&&p2.x&=&(i&+&1)*bin_&&&&&&&&&&&&&&p2.y&=&pic_hist-&height&-&hist2[i]&*&bin_&&&&&&&&&&&&&&cvRectangle(pic_hist,p1,p2,cvScalar(0,255,0),-1,8,0);&&&&&&&&&&}&&&&&&&&&&cvSaveImage(&hist2.jpg&,pic_hist);&&&&&&&&&&&&&&&&for&(i&=&0;i&&&4096;i++)&&&&&&&&&&{&&&&&&&&&&&&&&if&(hist2[i]&!=&0)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&w[i]&=&sqrt(hist1[i]/hist2[i]);&&&&&&&&&&&&&&}else&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&w[i]&=&0;&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&sum_w&=&0.0;&&&&&&&&&&x1&=&0.0;&&&&&&&&&&x2&=&0.0;&&&&&&&&&&&&for&(i&=&0;i&&&t_h;&i++)&&&&&&&&&&{&&&&&&&&&&&&&&for&(j&=&0;j&&&t_w;&j++)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&sum_w&=&sum_w&+&w[q_temp[i&*&t_w&+&j]];&&&&&&&&&&&&&&&&&&x1&=&x1&+&w[q_temp[i&*&t_w&+&j]]&*&(i&-&t_h/2);&&&&&&&&&&&&&&&&&&x2&=&x2&+&w[q_temp[i&*&t_w&+&j]]&*&(j&-&t_w/2);&&&&&&&&&&&&&&}&&&&&&&&&&}&&&&&&&&&&y1&=&x1&/&sum_w;&&&&&&&&&&y2&=&x2&/&sum_w;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&drawing_box.x&+=&y2;&&&&&&&&&&drawing_box.y&+=&y1;&&&&&&&&&&&&&&&&&&}&&&&&&free(hist2);&&&&&&free(w);&&&&&&free(q_temp);&&&&&&&&&&&&cvRectangle(current,cvPoint(drawing_box.x,drawing_box.y),cvPoint(drawing_box.x+drawing_box.width,drawing_box.y+drawing_box.height),CV_RGB(255,0,0),2);&&&&&&cvShowImage(&Meanshift&,current);&&&&&&&&&&&&cvReleaseImage(&pic_hist);&&}&&&&void&onMouse(&int&event,&int&x,&int&y,&int&flags,&void&*param&)&&{&&&&&&if&(pause)&&&&&&{&&&&&&&&&&switch(event)&&&&&&&&&&{&&&&&&&&&&case&CV_EVENT_LBUTTONDOWN:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&drawing_box.x=x;&&&&&&&&&&&&&&drawing_box.y=y;&&&&&&&&&&&&&&break;&&&&&&&&&&case&CV_EVENT_LBUTTONUP:&&&&&&&&&&&&&&&&&&&&&&&&&&&&drawing_box.width=x-drawing_box.x;&&&&&&&&&&&&&&drawing_box.height=y-drawing_box.y;&&&&&&&&&&&&&&cvRectangle(current,cvPoint(drawing_box.x,drawing_box.y),cvPoint(drawing_box.x+drawing_box.width,drawing_box.y+drawing_box.height),CV_RGB(255,0,0),2);&&&&&&&&&&&&&&cvShowImage(&Meanshift&,current);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&hist1&=&(double&*)malloc(sizeof(double)*16*16*16);&&&&&&&&&&&&&&m_wei&=&&(double&*)malloc(sizeof(double)*drawing_box.height*drawing_box.width);&&&&&&&&&&&&&&init_target(hist1,&m_wei,&current);&&&&&&&&&&&&&&is_tracking&=&true;&&&&&&&&&&&&&&break;&&&&&&&&&&}&&&&&&&&&&return;&&&&&&}&&}&&&&&&&&int&_tmain(int&argc,&_TCHAR*&argv[])&&{&&&&&&CvCapture&*capture=cvCreateFileCapture(&test.avi&);&&&&&&current&=&cvQueryFrame(capture);&&&&&&char&res[20];&&&&&&int&nframe&=&0;&&&&&&&&while&(1)&&&&&&{&&&&&&&&&&&&&&&&&&&&&if(is_tracking)&&&&&&&&&&{&&&&&&&&&&&&&&MeanShift_Tracking(current);&&&&&&&&&&}&&&&&&&&&&&&int&c=cvWaitKey(1);&&&&&&&&&&&&&&&&&&&&if(c&==&'p')&&&&&&&&&&&{&&&&&&&&&&&&&&pause&=&true;&&&&&&&&&&&&&&cvSetMouseCallback(&&Meanshift&,&onMouse,&0&);&&&&&&&&&&}&&&&&&&&&&while(pause){&&&&&&&&&&&&&&if(cvWaitKey(0)&==&'p')&&&&&&&&&&&&&&&&&&pause&=&false;&&&&&&&&&&}&&&&&&&&&&cvShowImage(&Meanshift&,current);&&&&&&&&&&current&=&cvQueryFrame(capture);&&&&&&&}&&&&&&&&cvNamedWindow(&Meanshift&,1);&&&&&&cvReleaseCapture(&capture);&&&&&&cvDestroyWindow(&Meanshift&);&&&&&&return&0;&&}&&
#include &stdafx.h&
#include &cv.h&
#include &highgui.h&
u_char unsigned char
//全局变量
bool pause =
bool is_tracking =
CvRect drawing_
IplImage *
double *hist1, *hist2;
double *m_
//权值矩阵
double C = 0.0;
//归一化系数
void init_target(double *hist1, double *m_wei, IplImage *current)
IplImage *pic_hist = 0;
int t_h, t_w, t_x, t_y;
int q_r, q_g, q_b, q_
t_h = drawing_box.
t_w = drawing_box.
t_x = drawing_box.x;
t_y = drawing_box.y;
h = pow(((double)t_w)/2,2) + pow(((double)t_h)/2,2);
pic_hist = cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);
//生成直方图图像
//初始化权值矩阵和目标直方图
for (i = 0;i & t_w*t_h;i++)
m_wei[i] = 0.0;
for (i=0;i&4096;i++)
hist1[i] = 0.0;
for (i = 0;i & t_h; i++)
for (j = 0;j & t_w; j++)
dist = pow(i - (double)t_h/2,2) + pow(j - (double)t_w/2,2);
m_wei[i * t_w + j] = 1 - dist /
//printf(&%f\n&,m_wei[i * t_w + j]);
C += m_wei[i * t_w + j] ;
//计算目标权值直方
for (i = t_y;i & t_y + t_h; i++)
for (j = t_x;j & t_x + t_w; j++)
//rgb颜色空间量化为16*16*16 bins
q_r = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 2]) / 16;
q_g = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 1]) / 16;
q_b = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 0]) / 16;
q_temp = q_r * 256 + q_g * 16 + q_b;
hist1[q_temp] =
hist1[q_temp] +
m_wei[(i - t_y) * t_w + (j - t_x)] ;
//归一化直方图
for (i=0;i&4096;i++)
hist1[i] = hist1[i] / C;
//printf(&%f\n&,hist1[i]);
//生成目标直方图
double temp_max=0.0;
for (i = 0;i & 4096;i++)
//求直方图最大值,为了归一化
//printf(&%f\n&,val_hist[i]);
if (temp_max & hist1[i])
temp_max = hist1[i];
//画直方图
CvPoint p1,p2;
double bin_width=(double)pic_hist-&width/4096;
double bin_unith=(double)pic_hist-&height/temp_
for (i = 0;i & 4096; i++)
p1.x = i * bin_
p1.y = pic_hist-&
p2.x = (i + 1)*bin_
p2.y = pic_hist-&height - hist1[i] * bin_
//printf(&%d,%d,%d,%d\n&,p1.x,p1.y,p2.x,p2.y);
cvRectangle(pic_hist,p1,p2,cvScalar(0,255,0),-1,8,0);
cvSaveImage(&hist1.jpg&,pic_hist);
cvReleaseImage(&pic_hist);
void MeanShift_Tracking(IplImage *current)
int num = 0, i = 0, j = 0;
int t_w = 0, t_h = 0, t_x = 0, t_y = 0;
double *w = 0, *hist2 = 0;
double sum_w = 0, x1 = 0, x2 = 0,y1 = 2.0, y2 = 2.0;
int q_r, q_g, q_b;
IplImage *pic_hist = 0;
t_w = drawing_box.
t_h = drawing_box.
pic_hist = cvCreateImage(cvSize(300,200),IPL_DEPTH_8U,3);
//生成直方图图像
hist2 = (double *)malloc(sizeof(double)*4096);
w = (double *)malloc(sizeof(double)*4096);
q_temp = (int *)malloc(sizeof(int)*t_w*t_h);
while ((pow(y2,2) + pow(y1,2) & 0.5)&& (num & NUM))
t_x = drawing_box.x;
t_y = drawing_box.y;
memset(q_temp,0,sizeof(int)*t_w*t_h);
for (i = 0;i&4096;i++)
w[i] = 0.0;
hist2[i] = 0.0;
for (i = t_y;i & t_h + t_y;i++)
for (j = t_x;j & t_w + t_x;j++)
//rgb颜色空间量化为16*16*16 bins
q_r = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 2]) / 16;
q_g = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 1]) / 16;
q_b = ((u_char)current-&imageData[i * current-&widthStep + j * 3 + 0]) / 16;
q_temp[(i - t_y) *t_w + j - t_x] = q_r * 256 + q_g * 16 + q_b;
hist2[q_temp[(i - t_y) *t_w + j - t_x]] =
hist2[q_temp[(i - t_y) *t_w + j - t_x]] +
m_wei[(i - t_y) * t_w + j - t_x] ;
//归一化直方图
for (i=0;i&4096;i++)
hist2[i] = hist2[i] / C;
//printf(&%f\n&,hist2[i]);
//生成目标直方图
double temp_max=0.0;
for (i=0;i&4096;i++)
//求直方图最大值,为了归一化
if (temp_max & hist2[i])
temp_max = hist2[i];
//画直方图
CvPoint p1,p2;
double bin_width=(double)pic_hist-&width/(4368);
double bin_unith=(double)pic_hist-&height/temp_
for (i = 0;i & 4096; i++)
p1.x = i * bin_
p1.y = pic_hist-&
p2.x = (i + 1)*bin_
p2.y = pic_hist-&height - hist2[i] * bin_
cvRectangle(pic_hist,p1,p2,cvScalar(0,255,0),-1,8,0);
cvSaveImage(&hist2.jpg&,pic_hist);
for (i = 0;i & 4096;i++)
if (hist2[i] != 0)
w[i] = sqrt(hist1[i]/hist2[i]);
sum_w = 0.0;
for (i = 0;i & t_h; i++)
for (j = 0;j & t_w; j++)
//printf(&%d\n&,q_temp[i * t_w + j]);
sum_w = sum_w + w[q_temp[i * t_w + j]];
x1 = x1 + w[q_temp[i * t_w + j]] * (i - t_h/2);
x2 = x2 + w[q_temp[i * t_w + j]] * (j - t_w/2);
y1 = x1 / sum_w;
y2 = x2 / sum_w;
//中心点位置更新
drawing_box.x += y2;
drawing_box.y += y1;
//printf(&%d,%d\n&,drawing_box.x,drawing_box.y);
free(hist2);
free(q_temp);
//显示跟踪结果
cvRectangle(current,cvPoint(drawing_box.x,drawing_box.y),cvPoint(drawing_box.x+drawing_box.width,drawing_box.y+drawing_box.height),CV_RGB(255,0,0),2);
cvShowImage(&Meanshift&,current);
//cvSaveImage(&result.jpg&,current);
cvReleaseImage(&pic_hist);
void onMouse( int event, int x, int y, int flags, void *param )
if (pause)
switch(event)
case CV_EVENT_LBUTTONDOWN:
//the left up point of the rect
drawing_box.x=x;
drawing_box.y=y;
case CV_EVENT_LBUTTONUP:
//finish drawing the rect (use color green for finish)
drawing_box.width=x-drawing_box.x;
drawing_box.height=y-drawing_box.y;
cvRectangle(current,cvPoint(drawing_box.x,drawing_box.y),cvPoint(drawing_box.x+drawing_box.width,drawing_box.y+drawing_box.height),CV_RGB(255,0,0),2);
cvShowImage(&Meanshift&,current);
//目标初始化
hist1 = (double *)malloc(sizeof(double)*16*16*16);
(double *)malloc(sizeof(double)*drawing_box.height*drawing_box.width);
init_target(hist1, m_wei, current);
is_tracking =
int _tmain(int argc, _TCHAR* argv[])
CvCapture *capture=cvCreateFileCapture(&test.avi&);
current = cvQueryFrame(capture);
char res[20];
int nframe = 0;
/* sprintf(res,&result%d.jpg&,nframe);
cvSaveImage(res,current);
nframe++;*/
if(is_tracking)
MeanShift_Tracking(current);
int c=cvWaitKey(1);
if(c == 'p')
cvSetMouseCallback( &Meanshift&, onMouse, 0 );
while(pause){
if(cvWaitKey(0) == 'p')
cvShowImage(&Meanshift&,current);
current = cvQueryFrame(capture); //抓取一帧
cvNamedWindow(&Meanshift&,1);
cvReleaseCapture(&capture);
cvDestroyWindow(&Meanshift&);
运行结果:
初始目标直方图:
候选目标直方图:
把OpenCV上的光流法,meanshift和camshift算法等看完学习之后,突然间想去查查文献,看看现在关于目标跟踪的一些主流算法,下面就简单的总结下。
运动目标跟踪就是在一段视频序列图像中的每幅图像中实时的找到所感兴趣的运动目标。在目标跟踪的研究上,大致上可以看出有两种研究思路:
a.不依赖于先验知识,直接从图像序列中检测到运动目标,并进行目标识别,最终跟踪感兴趣的运动目标;
b.依赖于目标的先验知识,首先为运动目标建模,然后在图像序列中实时找到相匹配的运动目标。
围绕这样的两种思路,学者们提出了很多算法,但是在算法的鲁棒性、准确性和普适性还不是特别的理想。运动目标跟踪的难点主要在于:
a.复杂背景干扰:在对目标进行跟踪时,往往会受到许多不同的背景的干扰。比如纹理复杂的背景可能会使基于边缘的跟踪器失效;或者是背景中与目标颜色相似的物体可能使基于颜色的跟踪器偏离真正的目标。
b.目标外观的变化:视频目标跟踪通常是在非控制条件下进行的,许多因素都会导致目标外观的变化,比如:光照变化,目标的形变等,因此要想对目标进行长时间的跟踪,就需要合理的处理这些变化,同时能够针对这些变化提出有效的观测似然函数,这个难度就很大。
c.遮挡问题:被跟踪的目标在运动过程中可能会被其他物体部分遮挡或全部遮挡,如何解决遮挡问题,这部分的研究一直是视频跟踪领域的研究的热点之一。
d.计算的有效性:视频跟踪是以帧速率进行的,这必然涉及到对大量的图像数据进行处理,要想进行实时处理,也要面临很大的数据处理问题。
对于不依赖先验知识的目标跟踪来讲,运动检测是实现跟踪的第一步。运动检测即为从序列图像中将变化区域从背景图像中提取出来。运动目标检测根据目标和摄像机之间的关系,可以分为静态背景下运动检测和动态背景下运动检测。下面简单的罗列下,如果感兴趣的话,可以查阅相关文献对照。
1.背景差分法
2.帧间差分法
动态背景跟踪
1.基于区域的跟踪算法
2.基于特征的跟踪算法
3.基于轮廓的跟踪算法
上面就是大致的写了下算法分类的标准,其实这部分的算法有很多,都有特定的适用条件,我还在看相关的文献。
#include &opencv2/video/tracking.hpp&
#include &opencv2/imgproc/imgproc.hpp&
#include &opencv2/highgui/highgui.hpp&
#include &iostream&
#include &ctype.h&
bool backprojMode = //表示知否进入反向投影,true进入反向投影
bool selectObject =
int trackObject = 0; //跟踪目标数目
bool showHist =//是否显示直方图
P//鼠标第一次单击时的位置
R//鼠标选择的矩形框
int vmin = 10, vmax = 256, smin = 30;
static void onMouse( int event, int x, int y, int, void* )
if( selectObject )
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = std::abs(x - origin.x);
selection.height = std::abs(y - origin.y);
selection &= Rect(0, 0, image.cols, image.rows);
switch( event )
case CV_EVENT_LBUTTONDOWN://鼠标左键按下,选择跟踪物体
origin = Point(x,y);
selection = Rect(x,y,0,0);
selectObject =
case CV_EVENT_LBUTTONUP://左键松开,完成选择跟踪物体
selectObject =
if( selection.width & 0 && selection.height & 0 )
trackObject = -1;
static void ShowHelpText()
cout && &\n\n\t操作说明: \n&
&\t\t用鼠标框选对象来初始化跟踪\n&
&\t\tESC - 退出程序\n&
&\t\tc - 停止追踪\n&
&\t\tb - 开/关-投影视图\n&
&\t\th - 显示/隐藏-对象直方图\n&
&\t\tp - 暂停视频\n&;
const char* keys =
&{1| &| 0 | camera number}&
int main( int argc, const char** argv )
ShowHelpText();
Rect trackW
int hsize = 16;
float hranges[] = {0,180};
const float* phranges =
cap.open(0);
if( !cap.isOpened() )
cout && &不能初始化摄像头\n&;
namedWindow( &Histogram&, 0 );
namedWindow( &CamShift Demo&, 0 );
setMouseCallback( &CamShift Demo&, onMouse, 0 );
createTrackbar( &Vmin&, &CamShift Demo&, &vmin, 256, 0 );
createTrackbar( &Vmax&, &CamShift Demo&, &vmax, 256, 0 );
createTrackbar( &Smin&, &CamShift Demo&, &smin, 256, 0 );
Mat frame, hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3),
bool paused =
if( !paused )
if( frame.empty() )
frame.copyTo(image);
if( !paused )
cvtColor(image, hsv, COLOR_BGR2HSV);
if( trackObject )
int _vmin = vmin, _vmax =
& & & & & & & & & & & & & & & &/*inRange()检查元素的取值范围是否在两个矩阵的像素取值之间,这里利用好了hsv的3个通道,h:0-180,s:smin-256,v:MIN(_vmin,_vmax)-
& & & & & & & & & & & & & & & & & & & & & MAX(_vmin, _vmax)*/
inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),
Scalar(180, 256, MAX(_vmin, _vmax)), mask);
int ch[] = {0, 0};
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
if( trackObject & 0 )
Mat roi(hue, selection), maskroi(mask, selection);
calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);//计算直方图
normalize(hist, hist, 0, 255, CV_MINMAX);
trackWindow =
trackObject = 1;
histimg = Scalar::all(0);
int binW = histimg.cols /
Mat buf(1, hsize, CV_8UC3);
for( int i = 0; i & i++ )
buf.at&Vec3b&(i) = Vec3b(saturate_cast&uchar&(i*180./hsize), 255, 255);
cvtColor(buf, buf, CV_HSV2BGR);
& & & & & & & & & & & & & & & & & & & &//绘制直方图
for( int i = 0; i & i++ )
int val = saturate_cast&int&(hist.at&float&(i)*histimg.rows/255);
rectangle( histimg, Point(i*binW,histimg.rows),
Point((i+1)*binW,histimg.rows - val),
Scalar(buf.at&Vec3b&(i)), -1, 8 );
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);//计算反向投影
backproj &=
RotatedRect trackBox = CamShift(backproj, trackWindow,
TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ));
if( trackWindow.area() &= 1 )
int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
Rect(0, 0, cols, rows);
if( backprojMode )
cvtColor( backproj, image, COLOR_GRAY2BGR );
ellipse( image, trackBox, Scalar(0,0,255), 3, CV_AA );
else if( trackObject & 0 )
if( selectObject && selection.width & 0 && selection.height & 0 )
Mat roi(image, selection);
bitwise_not(roi, roi);
imshow( &CamShift Demo&, image );
imshow( &Histogram&, histimg );
char c = (char)waitKey(10);
if( c == 27 )
backprojMode = !backprojM
trackObject = 0;
histimg = Scalar::all(0);
showHist = !showH
if( !showHist )
destroyWindow( &Histogram& );
namedWindow( &Histogram&, 1 );
paused = !
程序流程:
1、打开摄像头
2、显示帮助信息:
3、鼠标响应:当鼠标左键按下时,保存此时的坐标origion=&Pont(x,y),并且
&&&selectObject=1;执行if里面的语句,selection保存鼠标选择区域,当鼠
&&&标松开时,selectObject=0,trackObject=-1。
4、如果没有按下暂停键”c”,图像由BGR转化为HSV,inRange()将HSV中的
&&&(0-180,30-256,10-256)保存在mask中,分离H通道并保存在hue中。
5、如果鼠标选择区域松开后,根据鼠标的选择区域计算直方图并且归一化到
&&&0-255,将selection区域保存在trackWindow中,且track&Object=1。
6、绘制目标区域的方向投影的直方图:创建buf(1*16的3通道矩阵,并赋值
&&&为(0-168,255,255),以这个渐变的颜色作为直方图的色彩显示。)
7、计算反向投影,,就是首先计算图像中的某一特征,然后根据特征寻找图像中
&&&存在的特征。
8、目标跟踪:CamShift函数返回一个有方向角度的矩阵。该函数的实现首先是
&&&利用meanshift算法计算出要跟踪的中心,然后调整初始窗口的大小位置和方
&&&向角度。在camshift内部调用了meanshift算法计算目标的重心。
9、如果跟踪的矩形框的面积小于1,重新定义跟踪窗口,否则保持不变
10、转化为BGR,并绘制出椭圆形状,如果继续跟踪,转到步奏8。
函数解释:
1、inRange(hsv,Scalar(0,smin,MIN(_vmin,-vmax)),Scalar(180,256,MAX(_vmin,-vm
&&&ax)),mask):检查元素的取值范围是否在另两个矩阵的元素取值之间,返回ma
&&&sk验证矩阵。
2、mixChannels(&hsv,1,&hue,1.ch,1):抽取&hsv图像中的通道0
&&&&hsv:一系列输入图像的数组,&被拷贝的通道的来源
&&&&&&1:输入数组中图像的数目
&&&&&&&hue:一系列目的图像的数组,&储存拷贝的通道
&&&&&&1:目的数组中图像的数目
&&&&&&ch[]&=&{0,0}:通道索引对的数组,指示如何将输入图像的某一通道拷贝到目的
&&&图像的某一通道。在这里,&hsv图像的Hue(0)&通道被拷贝到&hue图像(单
&&&通道)的0&通道。
&&&&&&&1:通道索引对德数目
3、roi(hue,selection):设置中的感兴趣区域,如果设置了感兴趣区域,那么在使
用函数的时候,只会对区域操作,其它区域忽略。
4、maskroi(mask,selection):掩码
5、calcHist(&roi,1,0,maskroi,hist,1,&hist,&phranges):计算直方图
&roi:输入图像
1:第一个参数中存放了多少张图像
0:需要统计的通道索引
maskroi:输入图像的,可选的操作掩码,这里的非零掩码元素用于标记出统计直方图的数组元素数据
hist:,输出的目标直方图
1:需要计算的直方图的维度
&hist:存放每个维度的直方图尺寸的数组
&phranges:每一维数取值范围。
6、normalize(hist,hist,0,255,CV_MINMAX):归一化
7、Rectangle(histimg,Point(i*binW,histimg.rows),Point((i+1)*binW),histimg.rows-val),S
calar(buf.at&Vec3b&(i),-1,8);
C++:&void&rectangle(Mat&&img,Point&pt1,&Pointpt2,&const&Scalar&color,&intthickness=1,intlineType=8,&intshift=0)
C++:&void&rectangle(Mat&&img,Rect&rec,&const&Scalar&color,&intthickness=1,&intlineType=8,intshift=0&)
img&–&画矩形的对象&
pt1&–&矩形的一个顶点,左上角的.
pt2&–&另一个顶点,右下角的.&
rec&–&确定矩形的另一种方式,给左上角坐标和长宽&
color&–&指定矩形的颜色或亮度(灰度图像)
thickness&–&矩形边框的粗细.&负值()表示要画一个填充的矩形&
lineType&–&边框线型.&
8&(or&0)&-&8-connected&line(邻接)连接线。4&-&4-connected&line(4邻接)连接线。CV_AA&-&antialiased&线条。
8、calcBackProject(&hue,1,0,hist,backProj,&phranges)
Hue:输入图像
1:输入图像的个数
0:需要统计的通道索引
Hist:输入的直方图
backProj:目标反向投影阵列,必须为单通道
Phranges:每一个维度数组的边界
9、CamShift(backProj,trackWindow,TerCriteria(CV_TERMCRIT_EPS&|&
CV_TERMCRIT_ITER,10,1))
backProj:输入图像直方图的反向投影图
trackWindow:跟踪目标的初始位置矩形框
TerCriteria(CV_TERMCRIT_EPS&|&CV_TERMCRIT_ITER,10,1):算法结束条件
TLD算法:作者展示算法的效果,。下面这个csdn博客里有人做的相关总结,感觉挺好的,收藏了!下面有个Compressive
Tracking的网址,提供的代码很少,但实时性很好,matlab代码下下来就能用。
----------------------------------------------------------------------------------------------------------------------------------------------
以下博文转自:
TLD是一种算法的简称,原作者把它叫做Tracking-Learning-Detection。搞视觉的人看到这个名字都会吓一跳,很ambitious的计划。是09年的工作,不算太久,不过也不太新。网上关于这个的资源其实很多,很大程度和作者开放源代码有关。
学习过程中碰到的第一个问题就是资源太多---当然是相对这个领域而言,一般能找到一个忠实再现算法的源码就已经很好了。所以把找到的list一下,虽然有点浪费时间,希望可以对其他人有所帮助。具体的细节就不多说了,有很多很棒的分析也列在下面,比如写的源码注释,实在不能再详细了。如果硬要找茬,那就是大段的文字让人头晕,也没怎么排版。
补充3个博客资料和一个框架图
http://blog.csdn.net/tiandawenwu/article/details/
写的很不错。侧重点在learning 和随机森林的构建上。可惜读的人少的可怜,多数人都只想着怎么把程序跑起来,然后呢。。。
http://blog.csdn.net/muzi198783/article/details/7392255
写的相当简单。懂的人可以借鉴
http://blog.csdn.net/wood_water/article/details/9017681
又是一系列文章 。这个TLD都被嚼烂了,还是去玩Deep Learning吧。。。作者的博客也不错,后生可畏。。。
9. &_TLD框架图
/dpool/blog/s/blog_8ff949cf0100yfog.html?cre=blogpagew&mod=f&loc=3&r=ar&rfunc=9
真的够了。。。。
源代码资源:
1. 原作者 Zdenek Kalal
作者主页: http://info.ee.surrey.ac.uk/Personal/Z.Kalal/
源代码页:&/zk00006/OpenTLD
编程语言:Matlab + C
2.&Alan Torres版
源代码页:/alantrrs/OpenTLD
实现语言:C++
3. arthurv版
源代码页:/arthurv/OpenTLD
实现语言:C++
注:和上面的没有发现任何区别
源代码页:/jmfs/OpenTLD
实现语言:C++
注:和上面两个没有区别,只不过加入了VS2010工程文件,理论上可以直接在Windows下编译通过。不过opencv检测不到作者的webcam(!!!),所以他用了另一个VideoInput类来handle摄像头输入。
This is an adaptation of arthurv's fork of OpenTLD ()
to be immeadiately runnable in Visual Studio 2010.
5. Georg Nebehay版 (终于有个不一样的了。。。。)
源代码页:/OpenTLD/
注1:这个的好处是提供可执行文件下载(Ubuntu 10.04和Windows)。BUT, as you would expect,基本上到了你的机器上都跑不了。还是自己老老实实build吧。
注2:这个版本需要安装Qt。不过好像作者关掉了Qt的选项(相关代码还在),所以可以编译,但无法显示结果
注3:CSDN下载上有个“openTLD Qt 版“,就是这个版本。不过加了VS的工程文件---在我的机器上还是不能PnP, don't bother
http://download.csdn.net/download/muzi1915
6. Paul Nader版(又一个Qt 版!)
QOpenTLD: http://qopentld.sourceforge.net/
源代码页: http://sourceforge.net/projects/qopentld/
注1:需要OpenCV和Qt。 原系统要求Qt 4.3.7OpenCV 2.2。
注2:Windows和Linux下都提供了编译工程或makefile。估计也是唯一一个移植到Android平台下的TLD!
7. Ben Pryke版(又一个student project!)
源代码页:/Ninjakannon/BPTLD
注:依然是Matlab+C/C++的混合实现。亮点是有很详细的Documentation(8页),介绍了算法的理解和实现细节。可以帮助理解原算法
博客资源(中文):
1.&&庖丁解牛TLD (yang_xian521)
http://blog.csdn.net/yang_xian521/article/details/6952870
注1:从文章看作者是基于原作者的matlab版分析的。从函数名看上面的2/3/4应该是matlab---&C++的&直译&,函数名都没变。这样最好,可以和下面的对照着看,同时学matlab和C++
2.&&TLD(Tracking-Learning-Detection)学习与源码理解 (zouxy09)
http://blog.csdn.net/zouxy09/article/details/7893011
注1: 用的是&&arthurv版&&,前面说过,不能再详细了!
注2: 下面三个是从这篇copy的
3. 《再谈PN学习》:
http://blog.csdn.net/carson2005/article/details/7647519
4. 《比微软kinect更强的视频跟踪算法--TLD跟踪算法介绍》
http://blog.csdn.net/carson2005/article/details/7647500
5. 《TLD视觉跟踪技术解析》
.cn/number/n-50168.shtml
想说的话:
1. 分享:前段时间把 TLD::init(...)看完了,本想一鼓作气,其他的事太多只好放下。不过我对detection和tracking比较熟,init中已经把learning作了一遍,看懂了剩下的就容易了。现在重新捡起,无意中发现了zouxy09的注释,省了太多力气,半天就看完了。很多细节不用自己去抠--- 我们常抱怨这资源那文档太少,羡慕老外能力强,动作快,和他们愿意分享关系太大。经常看到一些不错的文章收藏起来,过几天去看居然删了!
可以理解可能是开公司要保密,但如果害怕别人知道了自己的思路就做不下去,那还是不要在这个领域做了。算法只是思想,谁也垄断不了。算法也一定是不断更新的, 抱着一个算法不放也存活不了几年。原作者也基于这个技术开公司了,也没见他们基于这个限制别人使用。SIFT,SURF都patent了也没听说赚了大钱,kinect告诉你算法也实现不了。要保密的是实现细节
2. 比较: 终于看完了实现,总的感觉这个算法还是更象工程应用(engineering)而不是理论突破(也不能要求太多了是不是)。感觉这么结合后并不一定会比单个的跟踪(tracking)或检测(detection-by-classification)模块作的更好,毕竟还是没有解决外观(appearence)和尺度(scale)变化这两个根本难题。 不过这种框架反而应该在实际中非常实用,因为----------可调的参数太多了!
TLD相信很多人都试过了,实时性很多人都在抱怨,而且拿到自己的视频上总要调些参数效果才好。
比较起来更喜欢今年ECCV上Kaihua Zhang的Compressive Tracking:理论高深的吓人(开玩笑),源码简单的吓人。而且是目前为止我试过的off-the-shelf的tracker中跟踪效果最好的,不用调任何参数,绝对实时----代码那么少,想不实时都难吧(顺便说一句作者的blog就在上面提到过)。这才是做研究的方法,有个强大的理论做支撑,实现可以很简单却不会影响效果。所以如果搞数学的人愿意做应用,很多人都会下岗
p.polyu.edu.hk/~cslzhang/CT/CT.htm
另一个PWP(Pixel-Wise Posteriors),publish时间和TLD差不多,性能看上去也很美,不过作者说要开源,一直没有兑现。是个遗憾。个人觉得level set对部分遮挡效果应该很好,做到实时也不是难事
http://www.robots.ox.ac.uk/~cbibby/research_pwp.shtml
3. 总结:TLD其实是一个非常合适的入门和进阶算法:
a.&有理论,有高质量的paper(BMVC, CVPR, ICPR, 最后PAMI)
b.&有源代码!Matlab, C++, Windows, Linux, .....你还想要啥?
c.&有不同大牛小牛分享的详细的介绍和详细的代码注释(几乎每一行都解释到了)!
4.&牵涉面广,涉及到detection, tracking, classifcation,传统的视觉技术就是这么硬梆梆的划分的三大类。研究完了对每一部分多少能有点心得。

参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:47580次
积分:1000
积分:1000
排名:千里之外
原创:14篇
转载:227篇
(38)(14)(17)(20)(31)(22)(47)(47)(17)(1)}

我要回帖

更多关于 光线追踪算法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信