引言
在计算机视觉中,光流是指物体、场景或摄像机之间的相对运动造成的像素变化。光流估计是计算机视觉中的一个基础课题,广泛应用于许多领域,比如自动驾驶汽车、机器人导航、手势识别等。OpenCV是一个开源的计算机视觉库,提供了许多功能强大的算法,其中包括光流算法。本文将介绍如何使用Python结合OpenCV来实现基于Lucas-Kanade算法的光流追踪,并展示如何在视频中追踪特征点的运动轨迹。
实现步骤
准备工作
首先,确保已经安装了numpy
和opencv-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()
代码解释
- 导入必要的库:导入
numpy
用于数值运算,导入cv2
模块用于图像处理。 - 打开视频文件:使用
cv2.VideoCapture
来打开指定路径下的视频文件。 - 初始化颜色:随机生成一系列颜色,以便后续绘制轨迹。
- 读取第一帧并转换为灰度图:读取视频的第一帧,并将其转换成灰度图,因为光流算法通常在灰度图上进行。
- 特征点检测:使用
cv2.goodFeaturesToTrack
来检测特征点。 - 初始化掩模:创建一个与原图像同样大小的全零矩阵,作为绘制轨迹的画布。
- 定义光流参数:设置Lucas-Kanade算法所需的参数。
- 主循环:读取每一帧视频,计算光流向量,并绘制轨迹。
- 显示结果:在每一帧上叠加轨迹后显示图像。
- 更新状态:在每次循环结束时更新旧的灰度图像和特征点位置。
- 清理资源:最后,释放视频文件和关闭所有OpenCV窗口。
结论
通过以上代码,我们可以实现基于Lucas-Kanade算法的光流追踪,并在视频中可视化特征点的移动轨迹。这种方法不仅可以帮助我们理解视频中物体的运动情况,而且对于开发需要感知环境动态变化的应用来说也是非常有用的。希望这篇博客能对你有所帮助!