传统目标跟踪——光流法

news2024/12/23 20:58:29

目录

一、光流法

二、LK光流法

2.1 实现原理

2.2 API

三、代码

四、总结


一、光流法

光流:空间运动物体在观察成像平面上像素运动的瞬时速度。

光流法利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。

通常将二维图像平面特定坐标点上的灰度瞬时变化率定义为光流矢量。

简单来说,光流就是瞬时速度,在时间间隔很小时,也等同于目标的位移,光流场是灰度图像的二维矢量场,它反映了图像上像素的变化趋势,可看成是带有灰度的像素点在图像平面上运动而产生的瞬时速度场,它包含的信息即是各像素点的瞬时运动速度矢量信息,既可以表现为物体运动的运动方向也可表现为物体运动的速率。

  • 稀疏光流法LK
  • 稠密光流法Gunner_Farnback

二、LK光流法

LK光流法有三个假设条件:

  1. 1:亮度恒定:对于灰度图像中运动目标,其像素点的亮度在相邻帧间不发生变化
  2. 2:时间连续或者运动足够小:在每次计算时,不会由于时间的变化而引起目标位置的剧烈变化,运动目标的像素点在相邻帧之间对应位置的变化比较小
  3. 3:空间一致:特征点附近所有相邻的像素点运动情况相似

LK光流法相比HS光流法避免了计算目标区域内所有像素点的光流,减小了运算开销,提高了程序的运行速度,但LK光流法的三个假设条件也会在应用稀疏光流法时产生一定的限制,比如当物体运动位移较大或者速度较快时,图像间的相关性较弱,并且较大的运动不满足泰勒公式的展开条件,导致无法求出最有匹配解而导致跟踪失败 

为了避免大位移运动跟踪失败的情况,在较大的尺度上进行跟踪时,将图像金字塔与LK光流法相结合,使图像分辨率降低到一定程度时,原本较大的运动位移变得足够小,利用图像金字塔来自上而下的计算来得到准确的光流。

2.1 实现原理

  1.  首先选取第一帧,在第一帧图像中检测Shi-Tomasi角点,
  2. 然后使用LK算法来迭代的跟踪这些特征点。迭代的方式就是不断向cv2.calcOpticalFlowPyrLK()中传入上一帧图片的特征点以及当前帧的图片。
  3. 函数会返回当前帧的点,这些点带有状态1或者0,如果在当前帧找到了上一帧中的点,那么这个点的状态就是1,否则就是0。

2.2 API

cv2.calcOpticalFlowPyrLK函数计算一个稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade 方法。

nextPts,status,err = cv2.calcOpticalFlowPyrLK(prevImg,   #上一帧图片
                                              nextImg,   #当前帧图片
                                              prevPts,   #上一帧找到的特征点向量 
                                              nextPts    #与返回值中的nextPtrs相同
                                              [, status[, err[, winSize
                                              [, maxLevel[, criteria
                                              [, flags[, minEigThreshold]]]]]]])

返回值:

  • nextPtrs 输出一个二维点的向量,这个向量可以是用来作为光流算法的输入特征点,也是光流算法在当前帧找到特征点的新位置(浮点数)
  • status 标志,在当前帧当中发现的特征点标志status==1,否则为0
  • err 向量中的每个特征对应的错误率

其他输入值:

  • status 与返回的status相同
  • err 与返回的err相同
  • winSize 在计算局部连续运动的窗口尺寸(在图像金字塔中)
  • maxLevel 图像金字塔层数,0表示不使用金字塔
  • criteria 寻找光流迭代终止的条件
  • flags 有两个宏,表示两种计算方法,
  • OPTFLOW_USE_INITIAL_FLOW表示使用估计值作为寻找到的初始光流,
  • OPTFLOW_LK_GET_MIN_EIGENVALS表示使用最小特征值作为误差测量
  • minEigThreshold 该算法计算光流方程的2×2规范化矩阵的最小特征值,除以窗口中的像素数; 如果此值小于minEigThreshold,则会过滤掉相应的功能并且不会处理该光流,因此它允许删除坏点并获得性能提升。

关键点(角点)追踪 goodFeaturesToTrack()

cv2.goodFeaturesToTrack(image,         #单通道
                        maxCorners,    #角点数目最大值,若检测的角点超过此值,则只返回前maxCorners个强角点
                        qualityLevel,  #角点的品质因子
                        minDistance,   #如果在其周围minDistance范围内存在其他更强角点,则将此角点删除 
                        corners        #存储所有角点
                        mask,          #指定感兴趣区,若无指定,寻找全图
                        blockSize,     #计算协方差矩阵时的窗口大小
                        useHarrisDetector,  #bool 是否使用Harris角点检测,如不指定,则计算shi-tomasi角点
                        k )           #Harris角点检测需要的k值

三、代码

实现流程:

  1. 加载视频。
  2. 调用 GoodFeaturesToTrack 函数寻找兴趣点(关键点)。
  3. 调用 CalcOpticalFlowPyrLK 函数计算出两帧图像中兴趣点的移动情况。
  4. 删除未移动的兴趣点。
  5. 在两次移动的点之间绘制一条线段。
import numpy as np
import cv2
import sys

cap = cv2.VideoCapture("E:\Python-Code/videodataset/test.mp4")

# ShiTomasi corner detection 角点检测的参数
feature_params = dict( maxCorners = 100,  # 角点数目最大值,若检测的角点超过此值,则只返回前maxCorners个强角点
                       qualityLevel = 0.3,  # 角点的品质因子
                       minDistance = 7,  # 如果在其周围minDistance范围内存在其他更强角点,则将此角点删除
                       blockSize = 7 # 计算协方差矩阵时的窗口大小
                       )

# LK光流法参数
# winSize 在计算局部连续运动的窗口尺寸(在图像金字塔中)
# maxLevel 为使用的图像金字塔层数
# criteria 寻找光流迭代终止的条件
lk_params = dict(winSize  = (15,15),
                 maxLevel = 2,
                 criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# # 创建随机生成的颜色
color = np.random.randint(0,255,(100,3))

ret, old_frame = cap.read()  # 取视频第一帧
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)  # 将第一帧灰度化
p0 = cv2.goodFeaturesToTrack(old_gray,
                             mask = None, # 指定感兴趣区,若无指定,寻找全图
                             **feature_params) # 选取好的特征点,返回特征点列表
mask = np.zeros_like(old_frame)  # 为绘制创建掩码图片

while(1):
    ret,frame = cap.read()
    if frame is None:
        break

    # 计算光流以获取点的新位置
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params) # 计算新的一副图像中相应的特征点d的位置
    # 选择good points
    good_new = p1[st==1]
    good_old = p0[st==1]

    # 绘制跟踪框
    for i,(new,old) in enumerate(zip(good_new,good_old)):
        a,b = new.ravel() #ravel()函数用于降维并且不产生副本
        c,d = old.ravel()
        # mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
        # frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
        mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)
        frame = cv2.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)
    img = cv2.add(frame,mask)


    cv2.imshow('frame',img)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)

cv2.destroyAllWindows()
cap.release()

四、总结

光流法对于动态背景环境的适应性通常比帧间差分法好,但是需要非常复杂的计算,并且提取的运动对象精度不高。
不用事先进行运动区域背景的提取,直接在实时运动中实现运动目标分割,可适当解决遮挡、重合等问题。
受光照影响大、计算复杂、运算时间长、抗噪声能力差,很难实现视频流的实时处理。

适用于复杂背景下且前景中有多个运动目标的分析问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

密码学_RSA

RSA是1977年由罗纳德李维斯特(Ron Rivest)、阿迪萨莫尔(Adi Shamir)和伦纳德阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 RSA是非…

dom截图的几种实现方式

前端要实现dom截图的功能,现在比较常用的是使用以下两个库 dom-to-image 使用svg技术实现html2canvas 使用canvas技术实现 如果想自己写一个dom截图的可以参考 dom-pointer 代码比较简单,非常适合拿来研究rasterizeHTML.js 目前rasterizeHTML.js已经被…

1231. 航班时间(恶心的输入处理 + 简单的数学)

题目如下: 题解 or 思路: 因为题目假设两次飞行时间是相同的,我们可以通过减法将时差消去。那么飞行时间就是: time1time22\frac{time_1 time2}{2}2time1​time2​ 题目的难点是处理输入,我们可以使用 sscanf 来进行处理&#x…

小程序开发经验分享(1)

账号搭建篇 1. 获取微信小程序的AppID 首先,我们需要拥有一个帐号,如果你能看到该文档,我们应当已经邀请并为你创建好一个帐号。注意不可直接使用服务号或订阅号的AppID。 利用提供的帐号,登录 https://mp.weixin.qq.com ,就可以在网站的“设置”-“开发者设置”中,查…

MySQL高级 SQL优化【插入数据主键优化】

目录 1:SQL优化 1.1:插入数据 1.1.1:insert 1). 优化方案一(批量插入数据) 2). 优化方案二(手动控制事务) 3). 优化方案三 (主键顺序插入,性能要高于乱序插入。) …

java应用集成HanLP进行中文自然语言分词详细完整案例以及demo

本文可以作为上一篇《mysql/mariadb 实现全文检索》的补充,实现对字符串分词的逻辑 什么是自然语言,什么是自然语言分词及例子 什么是自然语言 狭义地讲,利用计算机进行语言分析的研究是一门语言学与计算机科学的交叉学科,学术界…

CTFSHOW新手杯MISC部分WriteUp

引文 之前复现了CTFSHOW新人杯的WEB方向部分题目,今天就复现一下MISC为主的题目,可能有些读者不太明白MISC方向是什么意思,简单来说就是"杂项",包括:隐写,压缩包处理,流量分析,攻击取…

电容基础知识

电解电容负极有标识标有耐压值(400V 450WV) 容量 (68UF) 温度(105摄氏度)等 电容容量判断方法:直标法:上图,容量68微法,耐压值400V。数字表示法:方…

如何在公司审计中保持安全

如何在公司审计中保持安全 如今,财务弹性是决定您的公司能否在不确定时期适应和发展的主要属性之一。这可能令人很惊讶,但您的年度业务审计可以成为您提高业务敏捷性的秘密武器。它通过确定内部控制和财务报告的效果以及哪些流程改进应该在您的优先级列…

蓝桥杯Python练习题15-区间k大数查询

资源限制   内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 问题描述   给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。 输入格式   第一行包含一个数n&#xf…

黑马Hive+Spark离线数仓工业项目-任务流调度工具AirFlow(2)

Oracle与MySQL调度方法 目标:了解Oracle与MySQL的调度方法 实施 Oracle调度:参考《oracle任务调度详细操作文档.md》 - step1:本地安装Oracle客户端 - step2:安装AirFlow集成Oracle库 - step3:创建Oracle连接 - ste…

ODT在手,DDR5布线可以任性走?

作者:一博科技高速先生成员 姜杰 ODT是On Die Termination的缩写,又叫片内端接,顾名思义,就是把端接电阻放在了芯片内部。作为一种端接,ODT可以减小反射,对信号质量的改善显而易见,SI攻城狮很…

家用宽带搭建个人服务器(二)

本文主要详记免费二级域名注册和免费DDNS解析 写在前头 近几年国内注册域名需要备案,域名解析服务商都陆续需要收费了,对于我这种想简单玩玩的人来说实在是太麻烦了(主要是费钱),花了点时间找到了免费域名注册和DDNS解析 本文基于…

Android绘制原理【通透版】

概述 Android 的显示过程可以简单概括为:Android 应用程序把经过测量、布局、绘制后的surface 缓存数据,通过 SurfaceFlinger 把数据渲染到显示屏幕上,通过 Android 的刷新机制 来刷新数据。也就是说应用层负责绘制,系统层负责渲…

豪掷千亿的卡塔尔,为什么建造可回收的足球场?

作者:木环 来自世界六大洲的八强,正为大力神杯做最后的角逐。在精彩的比赛之外,这届世界杯还留下了很多破圈元素:卡塔尔的两千亿、逗笑的饺子皮表情包、推迟到冬季举办的赛事、围困啤酒赞助商的禁酒令。 以及,一个标…

Jackson 自定义序列化器的使用

注意:从简单的例子去延伸使用,内容紧凑,排版就这样了哈 举例:自定义序列化器,让输出json的指定字段金额10 public class testMain {public static void main(String[] args) throws JsonProcessingException {Bill b…

【BP靶场portswigger-服务端5】业务逻辑漏洞-11个实验(全)

目录 一、业务逻辑漏洞 1、意义 2、业务逻辑漏洞的产生 3、产生的影响 二、过度信任客户端控件 1、简述 实验1:过度信任客户端控件 三、未处理非常规输入 1、简述 实验2:高级逻辑漏洞 实验5:低级逻辑缺陷 实验6:异常输入处…

服务器防勒索病毒经验分享

场景描述 互联网飞速发展,各企业均搭建了自己的服务器。包括文件服务器、代码服务器、业务系统服务器、数据库服务器等。目前大多数企业使用的服务器系统以Windows Server和Linux(Centos)居多,但随着国产操作系统的崛起&#xff…

Altium Designer 20 凡亿教育视频学习-03

第三部分学习 封装具备的元素 紫色部分就是阻焊部分,阻焊作用:防止绿油覆盖 封装制作 Tab键调出属性菜单 当放置焊盘的时候,按Tab键,可以打开属性面板,并且更改是贴片还是插孔的 测量距离 Ctrl M 测量功能 测量…

Day 17-其它 Composition API_ 依赖注入provide / inject

Provide / Inject 当我们需要从父组件向子组件传递数据时,我们使用 props可以实现! 想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 props 沿着组件链逐级…