百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

视频分析与对象跟踪-基于光流算法的对象跟踪

toyiye 2024-07-05 01:26 11 浏览 0 评论


1. 基于光流算法的对象跟踪

通俗说,对于一个图片序列,把每张图像每个像素在连续帧之间的运动速度和方向(某像素点在连续两帧上的位移矢量)找出来就是光流场。在视频移动对象跟踪中,稀疏光流跟踪是一种经典的对象跟踪算法,可以绘制运动对象的跟踪轨迹与运行方向,是一种简单、实时高效的跟踪算法。

1. 1 算法介绍

例如在下面相邻的两帧 I 和 J 中,存在像素点的运动,也即是上一帧的像素点在下一帧中,其位置会有轻微的变动,这个变动就是位移向量,也就是像素点的光流,如下图,d 为像素点的光流。



要存在光流,即该光流能被计算出来,也就是KLT算法工作的三个假设前提条件:

  • 相邻帧之间的亮度恒定。
  • 短距离移动。
  • 空间一致性,即同一子图像的像素点具有相同的运动。

为什么要有这几个假设?如果判断一个视频的相邻两帧 I、J 在某局部窗口 w 上是一样的,则在窗口w 内有:I(x, y, t) = J(x', y', t+τ),亮度恒定的假设即为了保证其等号成立不受亮度的影响,假设2是为了保证KLT能够找到点,假设3则为以下原因假设(即对于同一个窗口中,所有点的偏移量都相等):

在窗口 w 上,所有(x, y)都往一个方向移动了(dx, dy),从而得到(x', y'),即 t 时刻的(x, y)点在 t+τ 时刻为(x+dx, y+dy),所以寻求匹配的问题可化为对以下的式子寻求最小值,或叫做最小化以下式子:



找角点的的方法一般用** Harris Shi-Tomasi **角点检测。

1. 2 图像的金字塔表示

特征跟踪器的两个关键的特性是准确性和鲁棒性,准确性是指跟踪结果的局部子像素的精度。为了不丢失图像中的细节,小窗口是更好的选择。尤其当图像中两个封闭区域有不同的运动适量时,这种选择就更有必要了。跟踪器的鲁棒性指跟踪性能对光照变化,运动大小等因素的敏感程度。比如,为了处理大运动的情况下,显然选择大的窗口是更合适的,这就要求在选择窗口大小的时候要权衡考虑局部准确性和鲁棒性,为了解决这个问题,提出了一种基于金字塔光流的改进跟踪算法。下图是金字塔光流法的原理示意图。先在图像金字塔的最顶层计算光流,用上层估计到的运动结果作为下一层金字塔的起始点,重复这样的估计直到金字塔的最底层。这样就将不满足运动假设(运动是小而连贯的)的情况转化为满足运动假设的情况来处理,实现对快而且长的运动进行跟踪。


光流跟踪的过程:(1)对一个连续的视频图像帧序列进行处理。(2)针对每一帧图像检测前景目标。(3)如果某一帧出现了前景目标,找到其具有代表性的特征点(一般利用角点来做特征点)。(4)对于之后的两个相邻视频帧,寻找上一帧中出现的特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置信息。(5)如此迭代进行,便可实现目标的跟踪。

例子代码:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

Mat frame, grayImg;  // 当前帧
Mat prev_frame,prev_grayImg;  //前一帧
vector<Point2f>features;  //Shi-Tomasi 焦点检测-特征数据
vector<Point2f>fpts[2];  //保证当前帧和前一帧的特征点位置
vector<Point2f>iniPoints;  //初始化特征数据
vector<uchar>status;  //特征点跟踪成功标志位
vector<float>errors;  //跟踪时候区域误差和

//Shi-Tomasi 焦点检测
void detectFeatures(Mat &inFrame, Mat &inGray){
    double maxCorners = 500;
    double qualitylevel = 0.01;
    double minDistance = 10;
    double blockSize = 3;
    double k = 0.04;

    // 算法很快,满足实时性要求
    goodFeaturesToTrack(inGray, features, maxCorners,
        qualitylevel, minDistance, Mat(), blockSize, false, k);
    cout << "detect features:" << features.size() << endl;
}

//绘制特征点
void drawFeature(Mat &inFrame){
    for (int i = 0; i < fpts[0].size(); i++)
    {
        circle(inFrame, fpts[0][i], 2, Scalar(0, 0, 255), 2);
    }
}
//在跟踪到的且移动了的特征点(光流)的开始跟踪的位置到当前跟踪到的位置之间绘制线段
void drawTrackLines(){
    for (int i = 0; i < fpts[1].size(); i++)
    {
        line(frame, iniPoints[i], fpts[1][i], Scalar(0, 255, 0), 2, 8, 0);  //绘制线段
        circle(frame, fpts[1][i], 2, Scalar(0, 0, 255), 2, 8, 0);
    }
}

// 稀疏光流法跟踪 KTL
void KLTrackFeature(){
    calcOpticalFlowPyrLK(prev_grayImg, grayImg, fpts[0], fpts[1], status, errors);
    int k = 0;  //保证跟踪到的特征点数,最后将特征点的尺寸重新设置为 k
    for (int i = 0; i < fpts[1].size(); i++)
    {
        double dist = abs(fpts[0][i].x - fpts[1][i].x) + abs(fpts[0][i].y - fpts[1][i].y);
        if (dist > 2 && status[i])  //跟踪到的特征点,且距离移动了 2 以上的
        {
            //将跟踪到的移动了的特征点在 vector 中连续起来,剔除掉损失的和静止不动的特征点(这些跟踪点在前面帧中)
            iniPoints[k] = iniPoints[i];
            fpts[1][k++] = fpts[1][i];  //同上,只是这些跟踪点在当前帧中
        }
    }
    //保存特征点并绘制跟踪轨迹
    iniPoints.resize(k);
    fpts[1].resize(k);
    drawTrackLines();

    swap(fpts[1], fpts[0]);  //交换,将此帧跟踪到特征点作为下一帧的待跟踪点
}
void test(){

    VideoCapture capture("Video.wmv");
    //VideoCapture capture(0);  //打开摄像头
    if (!capture.isOpened())
    {
        cout << "could not load video file...\n" << endl;
    }

    namedWindow("Result", CV_WINDOW_AUTOSIZE);

    while (capture.read(frame))
    {
        cvtColor(frame, grayImg, COLOR_BGR2GRAY);

        //跟踪40个特征点,如果跟踪的时候损失了一些特征点,重新检测,追加
        if (fpts[0].size() < 40)
        {
            detectFeatures(frame, grayImg);
            fpts[0].insert(fpts[0].end(), features.begin(), features.end());  //追加带跟踪的特征点
            iniPoints.insert(iniPoints.end(), features.begin(), features.end());
        }
        else
        {
            cout << "tracjing...\n" << endl;
        }

        if (prev_grayImg.empty())
        {
            grayImg.copyTo(prev_grayImg);
        }

        KLTrackFeature();  //稀疏光流跟踪 KLT
        drawFeature(frame);  //绘制特征点
        //更新前一帧的数据
        grayImg.copyTo(prev_grayImg);
        frame.copyTo(prev_frame);
        imshow("Result", frame);

        char c = waitKey(50);
        if (c == 27)
        {
            break;
        }
    }
    capture.release();
}
int main(){
    test();
    waitKey(0);
    return 0;
}

效果:


相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码