前言
- 光流利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。
- 本文主要展示代码以及代码解释,对于相对应的原理,以后有机会再写(下次一定)。
- 本文所用数据源于网上开源数据。找不到数据的小伙伴可以私我拿数据。
- 文章提供 python、c++ 代码。python 代码可以直接跑通。c++ 代码集成一个 class ,可以在自己工程中使用。
- 效果图:

一、代码流程与思路
- 输入:上一帧图片、preImage 上一帧图片检测框、image 当前帧图片。 输出:当前帧光流预测框
- 特征点提取。对上一帧图片 preImage 提取目标框里的特征点,这里采取的是 fast 角点检测。
- preImage、image 光流跟踪、在 image 中找出对应的特征点。
- 由特征点对应关系可以得出当前帧的目标框。
二、python 代码
2.1 代码详解
(1) fast 角点检测
fast = cv2.FastFeatureDetector_create(threshold=9, nonmaxSuppression=True, type=cv2.FastFeatureDetector_TYPE_9_16)
- threshold:边缘轨迹点和中心点的差值阈值。
- nonmaxSuppression:是否进行非极大值抑制
- type:提供轨迹范围。我们这里是从圆周轨迹16个点,当9个满足条件,此判定圆心像素点为特征点
我们这里只对检测框里的像素做特征点检测
def SelectPointByBox(img, det):
top_x, top_y, bottom_x, bottom_y = [int(_) for _ in det[:4]]
cutimg = img[max(0, top_y - 2):min(bottom_y + 2, 1080), max(0, top_x - 2):min(1920, bottom_x + 2)]
fast = cv2.FastFeatureDetector_create(threshold=9, nonmaxSuppression=True, type=cv2.FastFeatureDetector_TYPE_9_16)
kps = fast.detect(cutimg, 10) # Ip-t < Ip < Ip+t
kp = []
for p in kps:
t = []
t.append(np.float32(p.pt[0] + top_x))
t.append(np.float32(p.pt[1] + top_y))
kp.append(np.array(t).reshape(1, 2))
return np.array(kp)
(2) 追踪稀疏特征点
cv2.calcOpticalFlowPyrLK(preImgGray, gray, prePt, pt, **lkParms)
- preImgGray:前一帧图片灰度图。
- gray:当前帧图片灰度图
- prePt:前一帧图片的特征点
- pt:None
lkParms = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
- winSize: 每个金字塔级别上搜索窗口的大小
- maxLevel: 最大金字塔层数
- criteria:指定迭代搜索算法的终止条件,在指定的最大迭代次数 10 之后或搜索窗口移动小于 0.03
def OpticalFlowLk(preImg, curImg, prePt, pt):
lkParms = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
gray = cv2.cvtColor(curImg, cv2.COLOR_BGR2GRAY)
preImgGray = cv2.cvtColor(preImg, cv2.COLOR_BGR2GRAY)
# nextPts:前一帧图像的特征点跟踪后的点 st:特征点是否找到,找到状态为1,否则为0 err:每个特征点的误差,即前一帧和当前帧中特征点的位置差异
nextPts, st, err = cv2.calcOpticalFlowPyrLK(preImgGray, gray, prePt, pt, **lkParms)
# print("p1", nextPts, "st", st, "err", err)
goodNewPt = nextPts[st == 1] # 光流跟踪后特征点
goodOldPt = prePt[st == 1] # 上一帧特征点
return goodOldPt, goodNewPt
(3) 预测当前帧目标检测框
- 现在我们获取到了 prePt curPt pre_detect_box
- 由像素对应关系,我们可以求出 cur_detect_box
def CalculateShift(prePt, curPt):
x = curPt[:

本文介绍了如何使用Python和C++实现光流追踪技术,包括fast角点检测、特征点追踪和光流预测框计算。作者提供了详细的Python代码示例,并展示了c++类结构及其功能。
&spm=1001.2101.3001.5002&articleId=134691678&d=1&t=3&u=077093d95e2e4461ab402c4aafb1fdce)
2万+

被折叠的 条评论
为什么被折叠?



