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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 《Effective C++ 》学习笔记——规定10「建议收藏」

    《Effective C++ 》学习笔记——规定10

    2022年1月17日
    49
  • springboot实现Web系统License授权认证

    springboot实现Web系统License授权认证在我们做系统级框架的时候,我们要一定程度上考虑系统的使用版权,不能随便一个人拿去在任何环境都能用,所以我们需要给我们系统做一个授权认证机制,只有上传了我们下发的lic文件并验证通过,才能正常使用,下面就开始一步一步实现这个功能1.生成机器码我们首先要做的就是对软件部署的环境的唯一性进行限制,这里使用的是macadderss,当然你也可以换成cpu序列编号,并无太大影响,先上代码pri…

    2022年7月26日
    46
  • Could not get any response postman报错 但是浏览器可以访问

    Could not get any response postman报错 但是浏览器可以访问答案在最后一张图片案例分析把postman报错的信息复制再这里,你去翻译一下CouldnotgetanyresponseTherewasanerrorconnectingtohttp://118.xxx.xxx.10:11134/api-customer/…

    2022年5月31日
    83
  • opencv保存图片小bug

    opencv保存图片小bug错误:cv2.error:OpenCV(4.4.0)C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-6sxsq0tp\opencv\modules\imgcodecs\src\loadsave.cpp:667:error:(-2:Unspecifiederror)couldnotfindawriterforthespecifiedextensioninfunction’cv::imwrite_’图片路径不对,

    2022年6月23日
    30
  • 计算机病毒简介[通俗易懂]

    计算机病毒简介[通俗易懂]1、计算机病毒的特征1,繁殖性计算机病毒可以像生物病毒一样进行繁殖,当正常程序运行时,它也进行运行自身复制,是否具有繁殖、感染的特征是判断某段程序为计算机病毒的首要条件。2,破坏性计算机中毒后,可能会导致正常的程序无法运行,把计算机内的文件删除或受到不同程度的损坏。破坏引导扇区及BIOS,硬件环境破坏。3,传染性计算机病毒传染性是指计算机病毒通过修改别的程序将自身的复制品或其变体传染到…

    2022年6月5日
    32
  • Java定时任务Schedule实现的4种方式

    Java定时任务Schedule实现的4种方式java实现定时任务Schedulehttps://blog.csdn.net/java_2017_csdn/article/details/780602042017年09月22日10:30:52Java_2017_csdn阅读数:3306java实现定时任务Schedule标签:java实现定时任务Schedulejava实现定时任务javaSchedule2…

    2025年6月1日
    3

发表回复

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

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