基于 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 窗口

相关推荐
向哆哆3 小时前
100类中药材图像识别数据集分享(适用于目标检测任务)
人工智能·目标检测·计算机视觉
Knight_AL3 小时前
如何用 FFmpeg 处理 PCM 音频 & 判断 PCM 文件到底是什么格式
ffmpeg·音视频·pcm
shenxianasi3 小时前
【论文精读】Florence: A New Foundation Model for Computer Vision
人工智能·机器学习·计算机视觉·自然语言处理·transformer
有Li13 小时前
用于CBCT到CT合成的纹理保留扩散模型/文献速递-基于人工智能的医学影像技术
论文阅读·人工智能·深度学习·计算机视觉·文献
feasibility.15 小时前
yolo11-seg在ISIC2016医疗数据集训练预测流程(含AOP调loss函数方法)
人工智能·python·yolo·计算机视觉·健康医疗·实例分割·isic2016
社会零时工20 小时前
Ubuntu安装的OpenCV如何更换版本
linux·opencv·ubuntu
硅谷秋水1 天前
一个务实的VLA基础模型
人工智能·深度学习·机器学习·计算机视觉·语言模型·机器人
进击ing小白1 天前
OpenCv之图像颜色空间介绍
人工智能·opencv·计算机视觉
Hcoco_me1 天前
深挖 TBD 核心进阶点:深度学习匹配(目标关联的“智能指纹”)
人工智能·深度学习·目标检测·计算机视觉·目标跟踪