自学内容网 自学内容网

OpenCV 之 实现基于Lucas-Kanade算法的光流追踪

引言

在计算机视觉中,光流是指物体、场景或摄像机之间的相对运动造成的像素变化。光流估计是计算机视觉中的一个基础课题,广泛应用于许多领域,比如自动驾驶汽车、机器人导航、手势识别等。OpenCV是一个开源的计算机视觉库,提供了许多功能强大的算法,其中包括光流算法。本文将介绍如何使用Python结合OpenCV来实现基于Lucas-Kanade算法的光流追踪,并展示如何在视频中追踪特征点的运动轨迹。

实现步骤

准备工作

首先,确保已经安装了numpyopencv-python库。如果尚未安装,可以使用pip命令进行安装:

pip install numpy opencv-python

代码解析

下面是一个使用Lucas-Kanade算法追踪视频中特征点并绘制轨迹的例子。我们将逐步解释代码的每一部分。

import numpy as np
import cv2

# 打开视频文件
cap = cv2.VideoCapture(r'picture_video\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)
    
    # 选择好的点(状态为1的点)
    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()  # 获得新点的坐标
        c, d = old.ravel()  # 获得旧点的坐标
        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(150) & 0xff
    if k == 27:  # 按下Esc键,退出循环
        break
    
    # 更新旧灰度图和旧特征点
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)  # 重新整理特征点为适合下次计算的形状

# 释放资源
cv2.destroyAllWindows()
cap.release()

代码解释

  1. 导入必要的库:导入numpy用于数值运算,导入cv2模块用于图像处理。
  2. 打开视频文件:使用cv2.VideoCapture来打开指定路径下的视频文件。
  3. 初始化颜色:随机生成一系列颜色,以便后续绘制轨迹。
  4. 读取第一帧并转换为灰度图:读取视频的第一帧,并将其转换成灰度图,因为光流算法通常在灰度图上进行。
  5. 特征点检测:使用cv2.goodFeaturesToTrack来检测特征点。
  6. 初始化掩模:创建一个与原图像同样大小的全零矩阵,作为绘制轨迹的画布。
  7. 定义光流参数:设置Lucas-Kanade算法所需的参数。
  8. 主循环:读取每一帧视频,计算光流向量,并绘制轨迹。
  9. 显示结果:在每一帧上叠加轨迹后显示图像。
  10. 更新状态:在每次循环结束时更新旧的灰度图像和特征点位置。
  11. 清理资源:最后,释放视频文件和关闭所有OpenCV窗口。

结论

通过以上代码,我们可以实现基于Lucas-Kanade算法的光流追踪,并在视频中可视化特征点的移动轨迹。这种方法不仅可以帮助我们理解视频中物体的运动情况,而且对于开发需要感知环境动态变化的应用来说也是非常有用的。希望这篇博客能对你有所帮助!


原文地址:https://blog.csdn.net/m0_73697499/article/details/142864276

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!