稀疏光流跟踪(KLT)详解
在视频移动对象跟踪中,稀疏光流跟踪是一种经典的对象跟踪算法,可以绘制运动对象的跟踪轨迹与运行方向,是一种简单、实时高效的跟踪算法,这个算法最早是有Bruce D. Lucas and Takeo Kanade两位作者提出来的,所以又被称为KLT。KLT算法工作有三个假设前提条件:
亮度恒定
短距离移动
空间一致性
亮度恒定
对象中任意像素点p(x,y)亮度值,在t-1时候的值,在t时刻移动(u, v)之后亮度值保持不变
空间一致性
假设对像素点p(x, y)来说,周围的像素点都保持相同的移动距离(u, v) 假设窗口大小为5x5,则对于25个窗口内的像素点来说,就会如下等式成立:
得到下面的过约束等式,根据最小二乘可以求解(u, v):
这样我们就得到了KLT光流等式与该窗口的的Hessian矩阵
空间尺度不变性
通过建立每一帧的图像金字塔,实现尺度空间窗口目标对象搜索
OpenCV中KLT演示代码实现
OpenCV中KLT算法API及其参数解释如下:
void cv::calcOpticalFlowPyrLK( InputArray prevImg, // 前一帧图像 InputArray nextImg, // 后一帧图像 InputArray prevPts, // 前一帧的稀疏光流点 InputOutputArray nextPts, // 后一帧光流点 OutputArray status, // 输出状态,1 表示正常该点保留,否则丢弃 OutputArray err, // 表示错误 Size winSize = Size(21, 21), // 光流法对象窗口大小 int maxLevel = 3, // 金字塔层数,0表示只检测当前图像,不构建金字塔图像 TermCriteria criteria = TermCriteria(TermCriteria::EPS, 30, 0.01), // 窗口搜索时候停止条件 int flags = 0, // 操作标志 double minEigThreshold = 1e-4 // 最小特征值响应,低于最小值不做处理 )
特征点检测与绘制的代码实现如下:
// detect first frame and find corners in it Mat old_frame, old_gray; capture.read(old_frame); cvtColor(old_frame, old_gray, COLOR_BGR2GRAY); goodFeaturesToTrack(old_gray, featurePoints, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k);
特征点绘制
void draw_goodFeatures(Mat &image, vectorgoodFeatures) { for (size_t t = 0; t < goodFeatures.size(); t++) { circle(image, goodFeatures[t], 2, Scalar(0, 255, 0), 2, 8, 0); } }
KLT跟踪代码如下
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 0.01); double derivlambda = 0.5; int flags = 0; bool ret = capture.read(frame); if (!ret) break; imshow("frame", frame); roi.x = 0; frame.copyTo(result(roi)); cvtColor(frame, gray, COLOR_BGR2GRAY); // calculate optical flow calcOpticalFlowPyrLK(old_gray, gray, pts[0], pts[1], status, err, Size(31, 31), 3, criteria, derivlambda, flags);
特征点状态检查与匹配的代码如下
size_t i, k; for (i = k = 0; i < pts[1].size(); i++) { // 距离与状态测量 double dist = abs(pts[0][i].x - pts[1][i].x) + abs(pts[0][i].y - pts[1][i].y); if (status[i] && dist > 2) { pts[0][k] = pts[0][i]; initPoints[k] = initPoints[i]; pts[1][k++] = pts[1][i]; circle(frame, pts[1][i], 3, Scalar(0, 255, 0), -1, 8); } } // resize 有用特征点 pts[1].resize(k); pts[0].resize(k); initPoints.resize(k);
绘制跟踪轨迹的代码如下
// 绘制跟踪轨迹 draw_lines(frame, initPoints, pts[1]);
该方法实现如下:
void draw_lines(Mat &image, vectorpt1, vector pt2) { if (color_lut.size() < pt1.size()) { for (size_t t = 0; t < pt1.size(); t++) { color_lut.push_back(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255))); } } for (size_t t = 0; t < pt1.size(); t++) { line(image, pt1[t], pt2[t], color_lut[t], 2, 8, 0); } }
运行效果:
左侧是视频的原始每一帧、右侧视频是每一帧中KLT算法实时轨迹绘制
车辆运行轨迹跟踪
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !