opencv视频跟踪「建议收藏」

什么是对象跟踪?简而言之,在视频的连续帧中定位对象称为跟踪。该定义听起来很直接,但在计算机视觉和机器学习中,跟踪是一个非常广泛的术语,涵盖概念上相似但技术上不同的想法。例如,通常在对象跟踪下研究以下所有不同但相关的想法密集光流:这些算法有助于估计视频帧中每个像素的运动矢量。 稀疏光流:这些算法,如Kanade-Lucas-Tomashi(KLT)特征跟踪器,跟踪图像中几个特征点的位置…

大家好,又见面了,我是你们的朋友全栈君。

什么是对象跟踪?

简而言之,在视频的连续帧中定位对象称为跟踪。

该定义听起来很直接,但在计算机视觉和机器学习中,跟踪是一个非常广泛的术语,涵盖概念上相似但技术上不同的想法。例如,通常在对象跟踪下研究以下所有不同但相关的想法

  1. 密集光流:这些算法有助于估计视频帧中每个像素的运动矢量。
  2. 稀疏光流:这些算法,如Kanade-Lucas-Tomashi(KLT)特征跟踪器,跟踪图像中几个特征点的位置。
  3. 卡尔曼滤波:一种非常流行的信号处理算法,用于根据先前的运动信息预测运动物体的位置。该算法的早期应用之一是导弹制导!还提到这里,“是指导阿波罗11号登月舱的降落到月球车载计算机有一个卡尔曼滤波器”。
  4. Meanshift和Camshift:这些是用于定位密度函数的最大值的算法。它们也用于跟踪。
  5. 单个对象跟踪器:在此类跟踪器中,第一帧使用矩形标记,以指示我们要跟踪的对象的位置。然后使用跟踪算法在后续帧中跟踪对象。在大多数实际应用中,这些跟踪器与物体检测器结合使用。
  6. 多个对象跟踪查找算法:在我们有快速对象检测器的情况下,检测每个帧中的多个对象然后运行跟踪查找算法来识别一个帧中的哪个矩形对应于下一帧中的矩形是有意义的。

跟踪与检测

如果你曾经玩过OpenCV人脸检测,你知道它可以实时工作,你可以轻松地检测每一帧中的脸部。那么,为什么你需要首先进行跟踪?让我们探讨一下您可能想要跟踪视频中对象的不同原因,而不仅仅是重复检测。

  1. 跟踪比检测更快:通常跟踪算法比检测算法更快。原因很简单。当您跟踪在前一帧中检测到的对象时,您对该对象的外观了解很多。您还可以知道前一帧中的位置以及其运动的方向和速度。因此,在下一帧中,您可以使用所有这些信息来预测下一帧中对象的位置,并围绕对象的预期位置进行小搜索,以准确定位对象。一个好的跟踪算法将使用它对该对象的所有信息,而检测算法总是从头开始。因此,在设计有效系统时,通常每隔n 次运行一次物体检测在其间的n-1帧中采用跟踪算法的帧。为什么我们不直接检测第一帧中的对象并随后跟踪?确实,跟踪可以从它拥有的额外信息中受益,但是当它们长时间落在障碍物后面时,或者如果它们移动速度太快以至于跟踪算法无法赶上时,您也可能会失去对象的跟踪。跟踪算法累积错误也很常见,跟踪对象的边界框会慢慢偏离其正在跟踪的对象。为了通过跟踪算法解决这些问题,每隔一段时间运行一次检测算法。检测算法在对象的大量示例上进行训练。因此,他们对对象的一般类有更多的了解。另一方面,
  2. 当检测失败时,跟踪可以提供帮助:如果您在视频上运行人脸检测器并且人脸被对象遮挡,则人脸检测器很可能会失败。另一方面,良好的跟踪算法将处理某种程度的遮挡。在下面的视频中,您可以看到MIL跟踪器的作者Boris Babenko博士演示MIL跟踪器如何在遮挡下工作。
  3. 跟踪保留标识:对象检测的输出是包含对象的矩形数组。但是,该对象没有附加标识。例如,在下面的视频中,检测红点的检测器将输出对应于它在帧中检测到的所有点的矩形。在下一帧中,它将输出另一个矩形数组。在第一帧中,特定点可以由阵列中位置10处的矩形表示,并且在第二帧中,它可以在位置17处。当在帧上使用检测时,我们不知道哪个矩形对应于哪个对象。另一方面,跟踪提供了一种字面连接点的方法!

#include <opencv2/opencv.hpp>

#include <opencv2/tracking.hpp>

#include <opencv2/core/ocl.hpp>

 

using namespace cv;

using namespace std;

 

// Convert to string

#define SSTR( x ) static_cast< std::ostringstream & >( \

( std::ostringstream() << std::dec << x ) ).str()

 

int main(int argc, char **argv)

{

    // List of tracker types in OpenCV 3.4.1

    string trackerTypes[8] = {
"BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "GOTURN", "MOSSE", "CSRT"};

    // vector <string> trackerTypes(types, std::end(types));

 

    // Create a tracker

    string trackerType = trackerTypes[2];

 

    Ptr<Tracker> tracker;

 

    #if (CV_MINOR_VERSION < 3)

    {

        tracker = Tracker::create(trackerType);

    }

    #else

    {

        if (trackerType == "BOOSTING")

            tracker = TrackerBoosting::create();

        if (trackerType == "MIL")

            tracker = TrackerMIL::create();

        if (trackerType == "KCF")

            tracker = TrackerKCF::create();

        if (trackerType == "TLD")

            tracker = TrackerTLD::create();

        if (trackerType == "MEDIANFLOW")

            tracker = TrackerMedianFlow::create();

        if (trackerType == "GOTURN")

            tracker = TrackerGOTURN::create();

        if (trackerType == "MOSSE")

            tracker = TrackerMOSSE::create();

        if (trackerType == "CSRT")

            tracker = TrackerCSRT::create();

    }

    #endif

    // Read video

    VideoCapture video("videos/chaplin.mp4");

     

    // Exit if video is not opened

    if(!video.isOpened())

    {

        cout << "Could not read video file" << endl;

        return 1;

    }

 

    // Read first frame

    Mat frame;

    bool ok = video.read(frame);

 

    // Define initial bounding box

    Rect2d bbox(287, 23, 86, 320);

 

    // Uncomment the line below to select a different bounding box

    // bbox = selectROI(frame, false);

    // Display bounding box.

    rectangle(frame, bbox, Scalar( 255, 0, 0 ), 2, 1 );

 

    imshow("Tracking", frame);

    tracker->init(frame, bbox);

     

    while(video.read(frame))

    {    

        // Start timer

        double timer = (double)getTickCount();

         

        // Update the tracking result

        bool ok = tracker->update(frame, bbox);

         

        // Calculate Frames per second (FPS)

        float fps = getTickFrequency() / ((double)getTickCount() - timer);

         

        if (ok)

        {

            // Tracking success : Draw the tracked object

            rectangle(frame, bbox, Scalar( 255, 0, 0 ), 2, 1 );

        }

        else

        {

            // Tracking failure detected.

            putText(frame, "Tracking failure detected", Point(100,80), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255),2);

        }

         

        // Display tracker type on frame

        putText(frame, trackerType + " Tracker", Point(100,20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50,170,50),2);

         

        // Display FPS on frame

        putText(frame, "FPS : " + SSTR(int(fps)), Point(100,50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50,170,50), 2);

 

        // Display frame.

        imshow("Tracking", frame);

         

        // Exit if ESC pressed.

        int k = waitKey(1);

        if(k == 27)

        {

            break;

        }

 

    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127650.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Linux操作系统基础

    Linux操作系统基础Linux简介Linux是一种自由和开放源码的操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、台式计算机Linux介绍Linux出现于1991年,是由芬兰赫尔辛基大学学生LinusTorvalds和后来加入的众多爱好者共同开发完成Linux特点多用户,多任务,丰富的网络功能…

    2022年4月29日
  • mysql 窗口函数排序[通俗易懂]

    mysql 窗口函数排序[通俗易懂]窗口函数rank,dense_rank,row_numberselect*,rank()over(orderby成绩desc)asranking,dense_rank()over(orderby成绩desc)asdese_rank,row_number()over(orderby成绩desc)asrow_numfrom班级

    2022年9月26日
  • WSGI服务器

    WSGI服务器

    2021年6月30日
  • Framework7 Vue 教程 入门 学习

    Framework7 Vue 教程 入门 学习网上关于Framework7的博客、学习资料少之又少,所以我想把我学习Framework7Vue的入门记录一下。Framework7Framework7是一个开源免费的框架可以用来开发混合移动应用(原生和HTML混合)或者开发iOS&Android风格的WEBAPP。也可以用来作为原型开发工具,可以迅速创建一个应用的原型。Framework7最主要的功能是可以…

    2022年6月3日
  • electron调用go_opencv scalar

    electron调用go_opencv scalarglub一般都是很轻量的编译。go太重了,改一小个部分,就编译的话,多数是编译失败。而且很消耗性能,还没想到完美的优化办法。暂时用个定时器监听2秒,停止1秒,如此循环,会减少些“无效”的编译varwatch=require(‘glob-watcher’);varexec=require(‘child_process’).exec;varsys…

    2022年10月25日
  • web端功能测试怎么测_web的主要功能是什么

    web端功能测试怎么测_web的主要功能是什么一、功能测试1.1链接测试链接是web应用系统的一个很重要的特征,主要是用于页面之间切换跳转,指导用户去一些不知道地址的页面的主要手段,链接测试一般关注三点:1)链接是否按照既定指示那样,确实链

    2022年8月1日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号