楼主: 9143_cdabigdata
76 0

【20】目标追踪算法:Lucas-Kanade光流法原理与实现 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-4-14
最后登录
2018-4-14

楼主
9143_cdabigdata 发表于 2025-11-20 21:13:28 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

光流与Lucas-Kanade方法解析及实践

引言

光流(Optical Flow)作为计算机视觉中的核心概念,用于描述视频帧之间像素的移动情况,通过分析连续帧中像素的位置变化,生成二维运动矢量图。其中,Lucas-Kanade方法是较为经典的一种稀疏光流算法,它主要通过追踪图像中的特征点(例如Shi-Tomasi角点)来估算运动路径,被广泛应用于目标追踪、运动分割和视频稳定等领域。

本文将利用Python和OpenCV,逐步演示如何实现Lucas-Kanade光流的计算及其可视化,旨在帮助读者快速掌握光流的基本原理并进行实际操作。

光流与Lucas-Kanade方法的核心原理

在深入编程之前,我们先了解光流的基本假设以及Lucas-Kanade方法的求解思路。

1. 光流的基本假设

Lucas-Kanade方法依赖于以下两个基本假设:

  • 亮度不变假设:认为同一物体在连续帧中的像素亮度保持不变,即 \(I(x+u, y+v, t+1) ≈ I(x, y, t)\),其中 \(u, v\) 表示像素在x轴和y轴上的位移,\(t\) 是时间帧。
  • 局部平滑假设:假设相邻像素具有相同的运动方向和速度(即物体的局部区域进行刚体运动)。

2. 光流约束方程

基于亮度不变假设,通过泰勒级数展开(忽略高阶项),我们可以得到以下近似式:

\(I(x+u, y+v, t+1) ≈ I(x, y, t) + uI_x + vI_y + I_t\)

结合亮度不变假设 \(I(x+u, y+v, t+1) = I(x, y, t)\),简化后得到光流约束方程:

\(uI_x + vI_y + I_t = 0\)

其中,\(I_x = \frac{\partial I}{\partial x}\) 表示x方向的梯度,\(I_y = \frac{\partial I}{\partial y}\) 表示y方向的梯度,\(I_t = \frac{\partial I}{\partial t}\) 表示时间维度的梯度。

3. Lucas-Kanade的求解逻辑

由于光流约束方程是一个不定方程(包含两个未知数 \(u, v\) 和一个方程),因此不能直接求解。Lucas-Kanade方法通过在一个局部窗口(例如15×15像素的窗口)内选取多个像素点(通常是窗口内的所有像素点)来建立超定方程组,然后使用最小二乘法求解。

对于窗口内的每个像素点 \((x_i, y_i)\),光流约束方程可以表示为:

\(\begin{bmatrix} I_x(x_i, y_i) & I_y(x_i, y_i) \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} = -I_t(x_i, y_i)\)

将窗口内所有点的方程组合,形成线性方程组:

\(M \begin{bmatrix} u \\ v \end{bmatrix} = b\)

其中,矩阵 \(M = \sum_{i} \begin{bmatrix} I_x^2 & I_xI_y \\ I_xI_y & I_y^2 \end{bmatrix}\) 表示窗口内梯度的协方差矩阵;向量 \(b = -\sum_{i} \begin{bmatrix} I_xI_t \\ I_yI_t \end{bmatrix}\) 表示窗口内梯度与时间差的乘积之和。

通过最小二乘法求解,最终得到位移 \((u, v)\):

\(\begin{bmatrix} u \\ v \end{bmatrix} = (M^T M)^{-1} M^T b\)

实验步骤:从视频到光流可视化

接下来,我们将通过一系列步骤——下载测试视频、编写代码、运行并可视化——来完成光流实验。

1. 准备测试视频

首先,下载官方提供的测试视频(该视频场景为缓慢移动的交通,非常适合观察运动轨迹)。

下载视频:wget https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4

Lucas-Kanade光流追踪实现

我们将编写的代码命名为optical_flow_tracker.py,其核心逻辑包括以下几个步骤:

  • 读取视频文件并解析命令行参数;
  • 提取第一帧的Shi-Tomasi角点;
  • 循环计算后续帧的光流并绘制轨迹;
  • 保存可视化的追踪结果。

以下是经过优化的代码,其中变量名更具语义性,注释也更加清晰:

import numpy as np
import cv2
import argparse

def main():
    # 打开视频文件
    video_path = "slow_traffic_small.mp4"
    video_capture = cv2.VideoCapture(video_path)
    if not video_capture.isOpened():
        print(f"无法打开视频文件: {video_path}")
        return
    
    # 获取视频分辨率,初始化视频写入器(用于保存结果)
    frame_width = int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH))
    frame_height = int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
    output_video = cv2.VideoWriter(
        'optical_flow_result.mp4',
        cv2.VideoWriter_fourcc(*'mp4v'),
        30,  # 输出视频的帧率
        (frame_width, frame_height)
    )
    
    # 1. 配置Shi-Tomasi角点检测参数(用于提取初始特征点)
    shi_tomasi_params = {
        'maxCorners': 100,  # 最多检测100个角点
        'qualityLevel': 0.3,  # 角点质量阈值,用于过滤低质量点
        'minDistance': 7,  # 角点间的最小距离,防止点过于密集
        'blockSize': 7  # 计算梯度的窗口大小
    }
    
    # 2. 配置Lucas-Kanade光流算法参数
    lucas_kanade_params = {
        'winSize': (15, 15),  # 追踪窗口大小,提供局部平滑效果
        'maxLevel': 2,  # 金字塔层数,处理不同尺度的变化
        'criteria': (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)  # 终止条件:迭代10次或误差小于0.03
    }
    
    # 生成随机颜色,用于标记不同的追踪轨迹
    colors = np.random.randint(0, 255, (100, 3))  # 100个角点对应100种颜色
    
    # 3. 处理第一帧:提取初始角点
    success, previous_frame = video_capture.read()
    if not success:
        print("无法读取视频帧")
        return
    previous_gray = cv2.cvtColor(previous_frame, cv2.COLOR_BGR2GRAY)  # 将图像转换为灰度图,以便进行光流计算
    initial_corners = cv2.goodFeaturesToTrack(previous_gray, mask=None, **shi_tomasi_params)  # 提取角点
    tracking_mask = np.zeros_like(previous_frame)  # 创建掩码图像,用于绘制追踪轨迹
    
    # 4. 循环处理后续帧
    while video_capture.isOpened():
        success, current_frame = video_capture.read()
        if not success:
            break  # 视频结束
        
        current_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
        
        # 计算光流:追踪initial_corners在current_frame中的位置
        new_corners, status, errors = cv2.calcOpticalFlowPyrLK(
            previous_gray, current_gray, initial_corners, None, **lucas_kanade_params
        )
        
        # 过滤出有效的追踪点(status=1表示追踪成功)
        if new_corners is not None:
            valid_new = new_corners[status == 1]
            valid_old = initial_corners[status == 1]
            
            # 绘制追踪轨迹:使用掩码记录所有轨迹
            for i, (new, old) in enumerate(zip(valid_new, valid_old)):
                new_x, new_y = new.ravel()
                old_x, old_y = old.ravel()
                # 绘制从old到new的轨迹线
                
optical_flow_tracker.py

mask = cv2.line(mask, (int(curr_x), int(curr_y)), (int(prev_x), int(prev_y)), color[i].tolist(), 2)

# 在当前帧上绘制当前角点(实心圆)

curr_frame = cv2.circle(curr_frame, (int(curr_x), int(curr_y)), 5, color[i].tolist(), -1)

# 将当前帧与轨迹掩模合并

result_frame = cv2.add(curr_frame, mask)

# 保存结果帧到输出文件

out.write(result_frame)

# 更新前一帧和前一个点,以便在下一个循环中使用

prev_gray = curr_gray.copy()

prev_points = valid_curr.reshape(-1, 1, 2) # 调整点的形状以满足 calcOpticalFlowPyrLK 的要求

# 释放使用的资源

cap.release()

out.release()

cv2.destroyAllWindows()

print("光流计算完成,结果已保存为:optical_flow_result.mp4")

if __name__ == "__main__":

main()

3. 代码关键部分解析

Shi-Tomasi 角点检测

cv2.goodFeaturesToTrack

该步骤从图像中提取角点,这些角点作为光流追踪的“锚点”。由于角点在运动过程中相对稳定,因此适合用于光流追踪。

光流计算

cv2.calcOpticalFlowPyrLK

这是 OpenCV 实现的 Lucas-Kanade 光流算法,采用金字塔技术来处理不同尺度的变化。该函数返回当前帧的角点位置

curr_points

以及追踪状态

status

(1 表示成功,0 表示失败)。

轨迹绘制

使用

mask

图像来记录所有的轨迹线,避免每帧都重新绘制。通过

cv2.add

将轨迹与当前帧合并,生成可视化的结果。

四、光流的应用场景

Lucas-Kanade 光流作为一种经典的稀疏光流方法,在计算机视觉领域有广泛的应用:

  • 目标跟踪:追踪视频中的特定对象,例如人脸或车辆。
  • 运动分割:将视频中的前景(移动的物体)和背景(静态场景)分开。
  • 视频稳像:纠正因相机抖动引起的视频模糊。
  • 动作识别:分析人体关节的运动轨迹,例如手势识别或步态分析。

六、总结

本文介绍了如何使用 Python 和 OpenCV 实现 Lucas-Kanade 光流的计算与可视化。主要步骤包括:

  1. 使用 Shi-Tomasi 检测器提取初始角点;
  2. 循环计算帧间的光流(使用 Lucas-Kanade 方法);
  3. 绘制并保存轨迹的可视化结果。

光流是视频分析的基础工具,掌握它可以让你更好地理解视频中的运动信息。如果你希望进一步深入研究,可以尝试以下方向:

  • 使用密集光流方法(如 Farneback)计算所有像素的运动;
  • 结合深度学习模型(如 FlowNet)提高光流估计的准确性;
  • 将光流应用于实际项目,例如视频中的异常行为检测。

希望本文能对你的光流实践有所帮助!

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Lucas Luc CAS previous Criteria

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2026-1-9 08:14