目标跟踪算法 – CMT、TLD、KCF现成代码编译

  • Post author:
  • Post category:其他


本文章将统计多种目标跟踪算法,并编译运行,比较不同算法的优劣势。

下文我会将每个算法用到的环境都会仔细备注,以免有些算法对OpenCV版本挑剔。请先自行下载并配置好OpenCV环境,安装CMAKE。由于OpenCV网站有时候可能进不去或者是太慢,可以找找国内源,或者Github,当然Github也很慢。┑( ̄Д  ̄)┍  CMAKE也是同理。下载msi安装也可以,本人选择的是直接下载压缩文件直接使用了。

CMT算法

这个算法是通过摄像头拍摄的影响进行测试的,目前还没测试过本地视频。通过编译源代码,运行测试的。

优点:跟踪效果很好,也很快。

缺点:当物体消失并重新出现时候会跟丢或者框大小出现较大的变化。代码很多,是通过编译源代码进行测试的,不知道可不可以将库文件引入自己的程序。

环境:OpenCV 4.2.0 / Visual Studio 2017 / Windows 10 / cmake-3.16.5-win64-x64

其他版本的OpenCV没试过,但是说3.1版本不行,3.0版本可以。配置OpenCV环境时候有vc14和vc15两个文件夹,不懂的话全加了吧,像我一样。😂

在path环境变量里面添加:D:\App\OpenCV4.2.0\opencv\build\x64\vc14\bin
新建一个OpenCV_DIR变量,值为:D:\App\OpenCV4.2.0\opencv\build

全称是Clustering of Static-Adaptive Correspondences for Deformable Object Tracking,文章发表在CVPR2015上,官方的网址为:

http://www.gnebehay.com/cmt/

这个作者就是OpenTLD的C++版本的作者,包括ROS版的OpenTLD也是基于他的代码改的。

本算法参考博客:

https://blog.csdn.net/trustguan/article/details/51042558


步骤:

  • 从官网下载源码,解压到自己的目录。我的目录:D:\targetTracking\CMT (文件默认名为 CppMT-master)
  • 打开里面的fastcluster.cpp后,找到heapify()函数,修改成下面:

      void heapify() 
      {
        // Arrange the indices I and R so that H[i] := A[I[i]] satisfies the heap
        // condition H[i] < H[2*i+1] and H[i] < H[2*i+2] for each i.
        //
        // Complexity: Θ(size)
        // Reference: Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms,
        // 3rd ed., 2009, Section 6.3 “Building a heap”
       // t_index idx; 注释这里
        int_fast32_t idx;//添加这句
        for (idx=(size>>1); idx>0; ) {
          --idx;
          update_geq_(idx);
        }
      }

  • 在解压包同一目录里面新建一个BuildCppMT文件夹,用来存放适合VS2013工程文件。

  • 打开CMake,在压缩包里面是cmake-gui.exe这个名字。配置如下图:

  • 点击Configure,选择自己的编译器,我的是VS2017,点击Finish。如下图:

    如果出现Configuring done,那就是成功了,出现红色的字就是失败了,我的第一次出现一种错误,然后瞎倒腾了许久就可以了。具体忘了,我记得是倒腾了下配置的OpenCV环境就好了。

  • 点击Generate生成工程文件。

  • 用VS打开BuildCppMT文件夹里面的CMT.sln工程,我这里里面有三个解决方案,分别为ALL_BUILD、cmt和ZERO_CHECK。我在这里四种生成配置全部生成了。也可以只生成Release。记得配置VS的环境,右击cmt解决方法,在“配置属性→VC++目录→可执行文件目录”中添加OpenCV安装路径中的include和include\opencv2,有些旧版本OpenCV还需要include\opencv。例如我的是:

    D:\App\OpenCV4.2.0\opencv\build\include

    D:\App\OpenCV4.2.0\opencv\build\include\opencv2

    在库目录中添加lib,例如我的是:

    D:\App\OpenCV4.2.0\opencv\build\x64\vc14\lib

    D:\App\OpenCV4.2.0\opencv\build\x64\vc15\lib

    在“配置属性→C/C++→代码生成“中运行库对应改成:

    Debug、MinSizeRel、RelWithDebInfo生成配置下,选择 /MTd。Release生成配置下选择 /MT。

  • “配置属性→链接器→输入”中附加依赖项中添加上述lib目录下的例如这种文件D:\App\OpenCV4.2.0\opencv\build\x64\vc15\lib\opencv_world420d.lib。后面有d的时候Debug时候加载的,没有d的时候Release时候加载的。

  • 然后点击生成→生成解决方案(在这我是选择了打开配置管理器把三个解决方案全选上生成,默认只选了cmt和ZERO_CHEACK,不全选不知道可不可以,可以试试)。顺利就能成功,不顺利还是会报错。我这里报错的原因是这样的,OpenCV最新版有些参数的名字已经不一样了,比如出现未定义标识符 “CV_CAP_PROP_FRAMES“,是因为最新版本OpenCV已经不沿用这个命名了,而是改成了cv::CAP_PROP_FRAMES,把全部都换一下就可以了。再比如cvWaitKey()得把它改成从cv::waitKey()。当你把所有报错都改成功最后成功了以后,在BuildCppMT中会出现相应的四个生成配置的文件夹,点击去都会有cmt.exe,相机调试好能用了以后双击打开就能用了。(最好先用系统自带的相机试试自己的摄像头能否用。)(在我这里Release最流畅,Debug卡卡的,另外两个不能鼠标选取,以至于不能用)

  • 附一张测试图:

TLD算法

这个算法是通过本地视频进行测试的,实时摄像头影响还没测试过。通过编译源代码,运行测试的。

优点:跟踪效果好,目标出现小的被遮挡或者消失重新出现时候还能继续跟踪。

缺点:原作者推荐CMT算法,TLD算法已经不进行更新了,只支持 OpenCV 2.X 版本,如果需要新版本的OpenCV那就得对源代码进行修改。

环境:OpenCV 2.4.13 / Visual Studio 2017 / Windows 10

TLD(Tracking-Learning-Detection)是英国萨里大学的一个捷克籍博士生Zdenek Kalal(CMT也是他写的,不过现在已经停止更新了,原作者推荐使用CMT算法,不过还是要编译一下它比较一下两个有什么不同。因为TLD算法停止更新的时候还是OPenCV2.X。)在其攻读博士学位期间提出的一种新的单目标长时间(long term tracking)跟踪算法。

关于这个算法的详细解释可以看这个网站:

https://www.cnblogs.com/liuyihai/archive/2018/01/20/8320279.html

用前一个CMT算法的博主下一个博客也可以进行TLD算法的测试,但是OpenTLD包在OpenCV3的时候已经不支持了,所以需要进行源代码的改动,博主并没有给出改源代码的步骤,只是给出了改好的源代码的下载链接,穷如我,怎么可能下的起。所以另觅良处,找到了此博客

https://yq.aliyun.com/articles/31157


步骤:

  • OpenTLD源码下载

    https://github.com/arthurv/OpenTLD/tree/master
  • OpenCV下载及配置环境。这里不细说配置环境的详细操作了,跟上文一样,但是!这里不能用新版的OpenCV,我在这里用的是OpenCV 2.4.13。因为有些库文件在OpenCV新版本已经丢掉了,比如在这个源码中所用到的,比如我再做到一半发现opencv2\legacy\legacy.hpp 这个我就没找到,所以才发现是OpenCV版本的原因。最近发布的OpenCV 2.X就是这个OpenCV 2.4.13,因此他能支持VC14,不然以前的这个版本的OpenCV可能只支持VC10/VC11等,到时候就会提示,找不到 xxxxxx.dll了。但是记得注意下载跟自己电脑位数对应的版本,我是64位。
  • 将下载好的源码放到自己喜欢的目录下,比如我这里是 D:\targetTracking\TLD 。然后打开Visual Studio,我的是Visual Studio 2017,也就是VC15(VS版本和VC版本对应关系可以自行百度)。新建空项目,我在这里将他名为OpenCvTLD,目录选在跟解压包同一个目录,D:\targetTracking\TLD 。
  • 然后我们要在VS中配置环境。右击解决方案,点击”属性→配置属性→VC++目录“,在下面的包含目录(include、include\opencv、include\opencv2这三个目录)和库目录(这里不仅要添加lib,还要添加跟lib同级的staticlib目录,应该是旧版本OpenCV有的库目录)配置好OpenCV 2.4.13的环境,具体方法跟上文一样。然后在”配置属性→链接器→输入“下面附加依赖项里面添加OpenCV 2.4.13的库文件,在我这里在 D:\App\OpenCV2.4.13\opencv\build\x64\vc14\lib 目录下。怕麻烦就可以把里面的库文件全加进去,如果要用Release配置,那就加没有d的,要用Debug,那就添加有d的。我照着博主的截图添加了库文件,并没有全添加,后来报错了,也就是LNK2001这类报错,然后把全部库文件.lib文件全加进去就没事了。
  • 将OpenTLD源代码包里的头文件和源文件复制到VS当前工作目录(这个我理解的是D:\targetTracking\TLD\OpenCvTLD\OpenCvTLD这个目录,也可能是这个的上一级,应该没什么影响。)OpenTLD-master\include目录下面的是头文件,OpenTLD-master\src目录下面的是源文件。



  • 然后右击解决方案→添加→现有项,然后选择刚刚复制过来的九个文件,添加进去,他们会自动分类成头文件和源文件的。


  • 接下来就需要修改源文件了。将四个头文件的#include <>都修改成 #include “”。(在这我遇到了个傻瓜问题,以为都修改成双引号,然后我添加新的引用的时候#include “opencv2″却找不到,很纳闷,然后用#include <opencv2>就找到了。害,我目前也不懂这是为啥,为啥源代码可以,我自己新添加就不行。


  • 然后TLD.h中我们会发现PatchGenerator会出错,如下图

    在TLD.h中引用 #include <opencv2\legacy\legacy.hpp>就没事了。

  • 添加round函数,因为这个函数在VS中并没有自带,而OpenTLD用到了这个函数。在TLD.h中如下图所示的位置中添加下行代码。

    int round(float f);


    然后在下图所示位置中,添加如下代码:

    int TLD::round(float f)
    { 
    	if ((int)f+0.5>f) 
    		return (int)f; 
    	else 
    		return (int)f + 1; 
    }


    此时在我这里TLD.cpp文件里全是红色波浪线,但是好像对结果并没有影响,能正常运行。

  • 将VS工程下的四个头文件复制到VS的安装路径。他这里说完成上面步骤之后发现找不到头文件,需要将这四个头文件复制到VS的安装路径,但是在我这里只是将他原本 #include <TLD.h> 改成了 #include “TLD.h” 就没事了。但是我不知道还需不需要按这个博主的方式来做,我是因为我的cpp文件全是波浪线所以复制了一下,发现波浪线还是存在。所以并没有试过不复制可不可以这个事情。VS安装路径的话在我这里是这样的,可以照着去在自己的电脑里找一找。C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include ,就在这个include底下复制进去。

  • ceil错误和floor错误的修改(对于这两个错误我也没有遇到,可能是因为VS编译器版本不同的原因吧,因为我是VS2017,博主是VS2010,但是至少不会多余的,可以按这个改一下。

    高亮的那两行加了double(),做了下类型转换。floor也是一样的,如下图高亮部分。

    可以看打开的文件,找到相应行对比着修改。

  • 攻台数据分配错误的解决方法。(至于这个的话,我也没注意在我VS2017上有没有报错。)注释掉原有代码,添加下面代码。如下图所示:

    	float *L = new float [c-1]; //Level
    	int **nodes = new int *[c-1];
    	for(int i = 0; i < 2 ;i ++)
    		nodes[i] = new int [c-1];
    	int *belongs = new int [c];


    然后不要忘记将动态内存释放掉,如下图位置添加以下代码,在 return 1 前面。

    	delete [] L;
    	L = NULL;
    	for (int i = 0; i < 2; ++i)
    	{
    		delete [] nodes[i];
    		nodes[i] = NULL;
    	}
    	delete []nodes;
    	nodes = NULL;
    	delete [] belongs;
    	belongs = NULL;



  • 然后,编译,编译成功!

  • 不使用DEMO直接运行,利用摄像头影像时候,当选取方框的时候就会卡死,然后结束运行,我也不知道为什么,以后有时间在去研究。

  • 所以在这里也写一下怎么使用DEMO,首先将OpenTLD下的datasets文件夹和parameters.yml复制到当前工程目录中,然后修改主函数的代码,读取视频,然后就可以框选物体,进行目标跟踪了。如下图所示,注释一部分代码,并添加一部分代码:


  • 最后附上DEMO效果图:

KCF算法

这个算法是通过本地视频进行测试的,还没进行过实时摄像头影响的测试。代码短,不需要下载源代码压缩包,就一个Cpp文件百行代码就可以。

优点:简单,利用OpenCV只需要短短的代码就可以了。速度快。

缺点:辩认度不高,比不上前两个,容易跟丢,稍微有点遮挡就会跟丢,而且跟踪不上去;或者物体移动过快也会跟丢,但是有时候能重新跟踪上来;快速变形也会很容易跟丢;跟踪丢了以后框不消失(应该可以通过代码改进这个问题)。

环境:windows 10 / OpenCV 4.2.0 / OpenCV_contrib 4.2.0 /  Visual Studio 2017

KCF(核相关滤波算法,kernel correlation filter),详细原理信息请参考下面网址:


https://www.cnblogs.com/jins-note/p/10215511.html

刚开始进行查资料时候发现大多数KCF源代码都是Python代码,后来找到了C++的实现文章。


步骤:

  • 本算法需要的环境比前两个要复杂一点,需要OpenCV扩展包,因为OpenCV后来在新版本中不再将扩展包一起安装,而是需要的人单独下载,所以需要我们自己去下载配置。陷下载需要的OpenCV、OpenCV_contrib、CMake的版本。在这里注意OpenCV和OpenCV_contrib的版本必须是一致的。可以去OpenCV的github上下载。CMake的话如果下载压缩包那就不用安装,只需要解压就可以用了,是bin文件夹里面的cmake_gui这个文件。
  • 解压下载的OpenCV,双击exe,下载到自己的目录,比如我的目录是 D:\App\OpenCV4.2.0_withContrib ,然后将OpenCV_contrib解压以后放到这个文件夹里来。
  • 在OpenCV目录下新建一个目录放编译文件,我这里是这样的 D:\App\OpenCV4.2.0_withContrib\opencv\new_build ,我将它命名为new_build,可以随意起名,但是最好在OpenCV目录下,打开CMake,路径选择图下图所示(按自己的目录来进行相应的修改),然后点击configure,选择自己Visual Studio版本,我的是Visual Studio 2017也就是VS15,在第二个下拉框选择处理器位数,我的是64位,所以选择x64,然后点击Finish,这过程需要挺久的时间,期间会显示downloading xxxxx 然后有时候可能会变成红色下载失败,但是没事,等他继续下去,直到出现configure done。

  • 配置完成后在中间的框里找OPENCV_EXTRA_MODULES_PATH,将Opencv_contrib的modules目录放进去,同时保证WITH_CUDA未被勾选,我的默认是不勾选的。然后再点击一次Configure等待,再次出现Configure done就成功了。如下图,参考我的目录进行相应的修改:


  • 点击Generate,等待配置完成,出现Generate done就成功了,然后打开openCV的项目,可以直接点击面板上的Open project,也可以自己去在new_build下找OpenCV.sln双击打开。然后可以把CMake关掉了。
  • 在Visual Studio中选择自己的配置,也就是x64还是x86,32位电脑就选x86(也可能写的是win32),我的是64位所以选择x64,然后下面的操作要在Debug和Release模式下各进行一次。先点击“生成→生成解决方案”,然后右击CMakeTargets中的INSTALL选择“仅限于项目→仅生成INSTALL,等待成功就行了,但是千万记得上面两个步骤Debug和Release各进行一次。
  • 配置环境变量:在Path中添加bin目录,我的是 D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install\x64\vc14\bin 。添加OPENCV变量,变量值是D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install 。
  • 打开Visual Studio,新建空白项目,添加一个空白的cpp源文件,自己命名。
  • 配置项目环境,右击解决方案,”属性→配置属性→VC++目录“中包含目录中添加(前提是要选好自己的配置属性,比如你是x86还是x64,是要Debug还是Release,都需要的话都一个一个用下面的办法设置一边),我的是

    D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install\include

    D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install\include\opencv2

    有些版本OpenCV可能还会又opencv这个文件夹,有的话也要添加进去,新版本没有,只有opencv2这个文件夹。

    在库目录长添加自己的库目录,我的是

    D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install\x64\vc15\lib

    有些旧版本的OpenCV也会有staticlib这个文件夹,有的话也要添加进去,VC14和VC15等目录的话要看自己的编译器,不知道的话全加进去吧。
  • 在”属性→配置属性→链接器→输入“中附加依赖项中吧lib文件夹和static文件夹中的附加依赖项添加自己需要的库,如果不知道的话全添加进去,依赖项太多一个一个写太麻烦的话可以用如下 *.lib 这种方式全添加进去:

    D:\App\OpenCV4.2.0_withContrib\opencv\new_build\install\x64\vc15\lib\*.lib

    如果有static文件夹的话也是一样的。
  • 然后将下面代码复制到cpp文件中。

    
    #include <opencv2/core/utility.hpp>
    #include <opencv2/tracking.hpp>
    #include <opencv2/videoio.hpp>
    #include <opencv2/highgui.hpp>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    using namespace cv;
    
    int main() {
    	// declares all required variables
    	//! [vars]
    	Rect2d roi;
    	Mat frame;
    	//! [vars]
    
    	// create a tracker object
    	//Ptr<Tracker> tracker = Tracker::create("KCF");         //新版本OpenCV不再用这个Tracker
    	//! [create]
    	Ptr<TrackerKCF> tracker = TrackerKCF::create();//高版本一般是这样创建KCF的
    
    	// set input video
    	//! [setvideo]
    	std::string video = "D:\\targetTracking\\KCF\\car.mpg";
    	VideoCapture cap(video);
    	//! [setvideo]
    
    	//added by Ujig
    	if (!cap.isOpened())
    	{
    		return 0;
    	}
    	cout << "press c to leap current Image" << endl;
    	cout << "press q to slect current Image" << endl;
    	cout << "press empty key to start track RIO Object" << endl;
    	//end added
    
    	// get bounding box
    	//! [getframe]
    	cap >> frame;
    	//! [getframe]
    
    
    	//added by Ujig
    	while (1)
    	{
    		char key = waitKey(1);
    		if (key == 'c')  // 按c键跳帧
    		{
    			cap >> frame;
    		}
    		if (key == 'q')  // 按q键退出跳帧
    		{
    			break;
    		}
    		imshow("first", frame);
    	}
    
    	cv::destroyWindow("first");
    	//end added
    
    
    	//! [selectroi]选择目标roi以GUI的形式
    	roi = selectROI("tracker", frame);
    	//! [selectroi]
    
    	//quit if ROI was not selected
    	if (roi.width == 0 || roi.height == 0)
    		return 0;
    
    	// initialize the tracker
    	//! [init]
    	tracker->init(frame, roi);
    	//! [init]
    
    	// perform the tracking process
    	printf("Start the tracking process\n");
    	for (;; ) {
    		// get frame from the video
    		cap >> frame;
    
    		// stop the program if no more images
    		if (frame.rows == 0 || frame.cols == 0)
    			break;
    
    		// update the tracking result
    		//! [update]
    		tracker->update(frame, roi);
    		//! [update]
    
    		//! [visualization]
    		// draw the tracked object
    		rectangle(frame, roi, Scalar(255, 0, 0), 2, 1);
    
    		// show image with the tracked object
    		imshow("tracker", frame);
    		//! [visualization]
    		//quit on ESC button
    		//if (waitKey(1) == 27)  //by Ujig
    		//	break;
    
    		//added by Ujig
    		if (char(waitKey(1)) == 'q') {
    			cv::destroyWindow("tracker");
    			break;
    		}
    	}
    
    	return 0;
    }

    其中

    Ptr<Tracker> tracker = Tracker::create(“KCF”);

    这行代码是在新版OpenCV中已经不这么用了,所以这么写的话出现报错Tracker没有create方法,换成我上面代码中的那样就可以了,说到这个原因是能看懂OpenCV源码的话遇到这种错误就能靠自己去解决。

  • 将代码中的视频的路径改成自己的视频就能进行测试了。运行以后点击c能一个一个帧去调整视频,等到自己需要跟踪的目标出现以后点击q,然后点击鼠标将目标框起来,然后按下空格就能继续播放视频了。在框选完了以后点击c就会退出程序。

  • 最后附上效果图:




MIL算法

MIL(在线多实例学习,全称Online Multiple Instance Learning)。相关论文《Robust Object Tracking with Online Multiple Instance Learning》。

目前找到的源码资源是基于Visual Studio 2009、OpenCV 1.0 和 intel IPP 6.0,由于版本太老了,一大堆错误,目前还没调试成功,但是环境已经调通了,剩下的错误可能是C++本身或者编译器版本的原因。

WMIL算法

WMIL(加权在线多实例学习,全称 weighted multiple instance learning)。是对于MIL算法的改进算法,他在样本距离目标的位置相应的赋上了权值,以此获得更好的结果。

至于原理的话可以百度找找。这有个博客

https://blog.csdn.net/app_12062011/article/details/52239820

,这个博主有很多目标跟踪算法的原理阐述文章。


此博客到此结束,原因是我发现了这些算法OpenCV只用一句话就能实现。白费了三天功夫,好了,转入下一个博客了。



版权声明:本文为weixin_44330072原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。