基于 Lucas-Kanade 光流法实现视频特征点追踪

光流法是计算机视觉领域中用于分析物体运动的经典算法,而 Lucas-Kanade(LK)光流法作为稀疏光流的代表,因其计算高效、易于实现的特点,被广泛应用于视频目标追踪、运动分析等场景。

一、实现流程

1.读取视频文件,获取第一帧并提取特征角点;

2.逐帧读取后续视频帧,计算特征点的 LK 光流;

3.筛选出追踪成功的特征点,绘制特征点运动轨迹;

4.实时展示追踪结果,支持手动退出。

二、总体代码

python 复制代码
import numpy as np
import cv2
# 打开视频文件
cap = cv2.VideoCapture('test.avi')
#随机生成颜色,用于绘制轨迹
color = np.random.randint(0,255,(100,3))
#读取视频的第一顿
ret, old_frame = cap.read()
#将第一顿转换为灰度图像
old_gray = cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)
# 定义特征点检测参数
feature_params=dict(maxCorners=100,#最大角点数量
qualityLevel=0.3,#角点质量的阀值
minDistance=7)#最小距离,用于分散角点

p0=cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)#**:关键字参数解包,用于将字典解包为关键字参数。
#创建一个与当前帧大小相同的全零掩模,用于绘制轨迹
mask=np.zeros_like(old_frame)
#定义Lucas-Kanade光流参数
lk_params =dict(winSize=(15,15), maxLevel=2) #金字塔层数
#主循环,处理视频的每一顿
while True:
    # 读取下一帧
    ret,frame = cap.read()
    # 检查是否成功读取到帧
    if not ret:
        break
    # 将当前帧转换为灰度图像
    frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
   
    p1,st,err = cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0, None, **lk_params)
    # 选择好的点(状态为的点)
    good_new = p1[st == 1]
    good_old = p0[st == 1]
    # 绘制轨迹
    for i,(new,old) in enumerate(zip(good_new,good_old)):
        a,b = new  # 获取新点的坐标或者[a,b]=new
        c,d = old  # 获取旧点的坐标
        a,b,c,d = int(a),int(b),int(c),int(d)  # 转换为整数
        # 在掩模上绘制线段,连接新点和旧点
        mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
        cv2.imshow('mask',mask)
        # 将掩模添加到当前帧上,生成最终图像
        img = cv2.add(frame,mask)
        # 显示结果图像
        cv2.imshow( 'frame',img)
        # 等待150ms,检测是否按下了Esc键(键码为27)
        k = cv2.waitKey(10)
        if k == 27: # 按下Esc键,退出循环
            break
        # 更新旧灰度图和旧特征点
        old_gray = frame_gray.copy()
        p0 = good_new.reshape(-1,1,2) # 重新整理特征点为适合下次计算的形状(38,2)-->(38,1,2)

cap.release()
cv2.destroyAllWindows()

三、模块解析

(1)视频初始化与特征点检测

python 复制代码
# 打开视频文件
cap = cv2.VideoCapture('test.avi')
# 读取第一帧
ret, old_frame = cap.read()
# 转换为灰度图
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 检测特征角点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
  • cv2.VideoCapture:打开视频文件 / 摄像头,支持本地视频(如 avi/mp4)或摄像头设备(参数传 0);

  • goodFeaturesToTrack:Shi-Tomasi 角点检测算法,用于提取图像中具有代表性的特征点(角点),是 LK 光流的追踪基础。

(2)LK 光流计算

python 复制代码
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
  • 输入参数:前一帧灰度图、当前帧灰度图、前一帧特征点、空值(自动计算新特征点)、光流参数

  • 输出参数:

    • p1:当前帧特征点的新坐标

    • st:追踪状态(1 表示追踪成功,0 表示特征点丢失)

    • err:追踪误差(数值越小,追踪越准确)

(3)轨迹绘制与结果展示

python 复制代码
# 筛选有效特征点
good_new = p1[st == 1]
good_old = p0[st == 1]
# 绘制轨迹
mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
img = cv2.add(frame, mask)
cv2.imshow('LK光流特征点追踪', img)
  • 仅保留追踪成功的特征点(st == 1),过滤丢失的点

  • cv2.line:在掩模上绘制新旧特征点的连线(轨迹)

  • cv2.add:将轨迹掩模叠加到原始帧上,实现轨迹与视频画面的融合展示

(4)循环更新与资源释放

python 复制代码
# 更新追踪基准
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1, 1, 2)
# 释放资源
cap.release()
cv2.destroyAllWindows()
  • 每次循环后更新 "前一帧" 为当前帧,"前一帧特征点" 为当前有效特征点

  • reshape(-1, 1, 2):将特征点格式从(N,2)转为(N,1,2),适配光流函数的输入要求

  • 视频处理结束后,必须释放VideoCapture资源并关闭所有 OpenCV 窗口

相关推荐
不才小强12 小时前
macOS 屏幕录制开发完全指南:ScreenCaptureKit与音频采集实战
macos·音视频
我材不敲代码13 小时前
OpenCV 光流估计实战:Lucas-Kanade 算法实现运动目标跟踪
opencv·算法·目标跟踪
禄亿萋13 小时前
基于多维协同注意力和特征融合的小目标检测方法
人工智能·目标检测·计算机视觉
咏&志13 小时前
目标检测Faster-RCNN论文简读
人工智能·目标检测·计算机视觉
卖报的大地主13 小时前
视觉生成底层技术发展脉络与研究图谱
人工智能·深度学习·计算机视觉
CV实验室17 小时前
Meta引爆3D革命!SAM 3D 发布:单张图秒建3D模型,AR/VR、游戏圈炸锅!
计算机视觉·3d·meta·ar·vr
RFdragon17 小时前
分享本周所学——三维重建算法3D Gaussian Splatting(3DGS)
人工智能·线性代数·算法·机器学习·计算机视觉·矩阵·paddlepaddle
轻口味1 天前
HarmonyOS 6 NDK开发系列1:音视频播放能力介绍
华为·音视频·harmonyos
小小数媒成员1 天前
Shader中的光照模型
人工智能·计算机视觉
有Li1 天前
一种病理学内容感知变速率学习图像压缩框架 (PathoLIC)/文献速递-多模态应用技术
人工智能·深度学习·算法·计算机视觉·医学生