计算机视觉基础 第14章|Lucas-Kanade金字塔光流法跟踪
目录
2.2 Shi‑Tomasi 角点检测参数配置,提取初始跟踪点
前言
在视频序列中,目标跟踪的核心任务是捕捉特征点在连续帧之间的运动轨迹。光流表征图像中像素随时间变化的运动矢量,能够描述物体的移动方向与位移距离。本章采用金字塔 Lucas‑Kanade 光流算法,先通过 Shi‑Tomasi 算子提取图像角点作为跟踪特征,再利用calcOpticalFlowPyrLK完成前后帧特征点匹配,绘制运动轨迹,实现视频特征点的持续跟踪。
一、实验需求
读取视频文件,在视频首帧检测高质量角点作为待跟踪特征;在后续每一帧使用金字塔 LK 光流计算特征点新位置;筛选有效跟踪点,在画布上绘制特征点的运动轨迹;将轨迹图与原始视频叠加可视化,完成长序列特征跟踪。
二、原理与代码分步讲解
2.1 库导入、视频读取与初始化
- 导入 OpenCV 与数值计算库 numpy。
- 创建视频读取对象,加载测试视频。
- 预定义随机颜色数组,保证每个特征点的轨迹拥有独立配色,可视化效果更清晰。
- 提取视频首帧并转换为灰度图像,角点检测与光流运算均基于灰度图完成,降低计算量。
2.2 Shi‑Tomasi 角点检测参数配置,提取初始跟踪点
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)
- maxCorners=100:最多提取 100 个优质角点;
- qualityLevel=0.3:角点可接受的最低质量阈值;
- minDistance=7:两个角点之间最小间隔像素,避免特征点扎堆;
- cv2.goodFeaturesToTrack即 Shi‑Tomasi 角点检测算法,返回初始待跟踪特征点坐标p0;
- mask为全黑空白图像,专门用来绘制光流运动轨迹,不污染原始画面。
2.3 LK 金字塔光流配置参数
lk_params = dict(
winSize = (15,15),
maxLevel = 2
)
- winSize=(15,15):计算光流时每个特征点对应的局部搜索窗口大小;
- maxLevel=2:金字塔层数,多层金字塔可以处理更大幅度的目标运动,解决大位移下光流跟踪失败的问题。
2.4 逐帧循环,执行光流计算
while True:
ret,frame = cap.read()
if not ret:
break
frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# LK金字塔光流计算
p1,st,err = cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)
API功能详解:cv2.calcOpticalFlowPyrLK()
该函数是金字塔Lucas-Kanade稀疏光流算法的核心接口,专门用于实现连续视频帧间的特征点跟踪。基于灰度不变假设与局部窗口纹理匹配原理,依托图像金字塔分层迭代机制,精准计算指定特征点在相邻帧中的位移位置,适配小幅度、大幅度的目标运动场景,是稀疏特征跟踪的核心函数。
函数输入:依次传入前一帧灰度图像、当前帧灰度图像、上一帧有效特征点坐标,结合预设的光流窗口尺寸、金字塔层数等参数,为特征点匹配运算提供数据与规则支撑。
函数返回值解析:
- p1(更新后特征点坐标):输出当前帧中所有特征点迭代匹配后的最新坐标,是目标位置实时更新的核心依据。算法通过比对特征点邻域窗口的灰度纹理相似度,求解最优位移矢量,从而更新特征点位置。
- st(跟踪状态标记数组):全局二值判定标识,用于区分特征点跟踪状态。数值为1表示该特征点邻域纹理匹配成功、跟踪有效;数值为0表示纹理匹配失效,因遮挡、形变、光照突变、超量程位移等问题导致特征点跟踪丢失,后续不再参与迭代跟踪。
- err(匹配误差数组):对应每个特征点的灰度匹配误差,量化表征前后帧特征窗口的纹理差异程度。误差数值越小,代表窗口纹理相似度越高,匹配结果越精准;误差过大则判定为匹配无效,辅助筛选有效跟踪点。
2.5 筛选有效点,绘制运动轨迹
good_new = p1[st==1]
good_old = p0[st==1]
for i ,(new,old) in enumerate(zip(good_new,good_old)):
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)
- 通过st==1过滤,只保留跟踪成功的特征点;
- 遍历成功匹配的新旧坐标,在 mask 画布上绘制线段,连接同一特征点在上一帧与当前帧的位置;
- cv2.add(frame,mask)把原始视频画面和轨迹画布叠加显示,直观看到物体运动路径。
2.6 更新迭代与退出逻辑
k = cv2.waitKey(60)
if k == 27:
break
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cap.release()
cv2.destroyAllWindows()
- 将当前帧灰度图作为下一轮运算的旧帧;
- 将本轮成功跟踪的新坐标赋值给p0,作为下一帧的跟踪起点,实现持续追踪;
- 按下 ESC 键结束程序,释放资源关闭窗口。
三、完整可运行代码
import numpy as np
import cv2
cap = cv2.VideoCapture(r"D:\pythoncode2\bigdata_ai40\data\test.avi")
color = np.random.randint(0,255,(100,3))
ret,old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)
# Shi‑Tomasi角点检测参数
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)
# LK金字塔光流参数
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
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)
img = cv2.add(frame,mask)
cv2.imshow("frame",img)
k = cv2.waitKey(60)
if k == 27:
break
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cap.release()
cv2.destroyAllWindows()

四、核心 API 说明
- cv2.goodFeaturesToTrack():Shi‑Tomasi 角点检测,提取适合跟踪的稳定特征点。
- cv2.calcOpticalFlowPyrLK():金字塔 Lucas‑Kanade 稀疏光流,计算特征点在下一帧的位置。
- np.random.randint():随机生成 RGB 颜色值,用于区分不同特征轨迹。
- cv2.line():在空白 mask 画布上绘制特征点运动轨迹。
- cv2.add():将原图与轨迹图层叠加融合显示。
五、实验现象与问题分析
- 跟踪效果:物体移动时画面上会留下彩色轨迹线条,直观展示角点的运动路径;
- 跟踪丢失:当目标快速移动、被遮挡或者旋转过大时,部分特征点状态st=0,该点停止跟踪;
- 稀疏光流特点:只跟踪少量角点,计算速度快;对比稠密光流,不会计算整张图像每个像素的运动;
- 金字塔作用:多层图像缩放,可以处理更大幅度的位移,提升大运动场景下的跟踪鲁棒性。
六、本章小结
稀疏金字塔 LK 光流跟踪完整流程:
读取首帧 → Shi‑Tomasi 提取初始角点 → 设置光流窗口与金字塔层数 → 逐帧迭代计算光流 → 筛选跟踪有效的特征点 → 在画布绘制运动轨迹 → 更新特征点实现持续跟踪。
Lucas‑Kanade 属于稀疏光流,仅跟踪少量高稳定性角点,实时性较好;缺点是目标遮挡、剧烈形变时容易丢失跟踪。后续可以对比稠密光流 Farneback 算法,观察全像素运动矢量的可视化效果。
更多推荐
所有评论(0)