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

相关推荐
CoovallyAIHub21 小时前
语音AI Agent编排框架!Pipecat斩获10K+ Star,60+集成开箱即用,亚秒级对话延迟接近真人反应速度!
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
Moonshine:比 Whisper 快 100 倍的端侧语音识别神器,Star 6.6K!
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
速度暴涨10倍、成本暴降6倍!Mercury 2用扩散取代自回归,重新定义LLM推理速度
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
OpenClaw一脚踩碎传统CV?机器终于不再只是看世界
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
深度学习·算法·计算机视觉
IVEN_3 天前
Python OpenCV: RGB三色识别的最佳工程实践
python·opencv
CoovallyAIHub7 天前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub7 天前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub7 天前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉
CoovallyAIHub7 天前
强化学习凭什么比监督学习更聪明?RL的“聪明”并非来自算法,而是因为它学会了“挑食”
深度学习·算法·计算机视觉