基于OpenCV C++实现的光流法目标检测,包含运动跟踪和目标区域提取功能:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// 全局变量
VideoCapture cap;
Mat gray, prevGray;
vector<Point2f> prevPts, nextPts;
vector<uchar> status;
vector<float> err;
Mat mask;
int maxCount = 500;
double qLevel = 0.01;
double minDist = 10.0;
TermCriteria termcrit(TermCriteria::COUNT + TermCriteria::EPS, 10, 0.03);
// 初始化视频
void initVideo(const string& videoFile) {
cap.open(videoFile);
if(!cap.isOpened()) {
cerr << "Error opening video file" << endl;
exit(-1);
}
cap >> prevGray;
cvtColor(prevGray, prevGray, COLOR_BGR2GRAY);
}
// 光流跟踪处理
void processFrame(Mat& frame) {
Mat currentGray;
cvtColor(frame, currentGray, COLOR_BGR2GRAY);
// 检测新特征点
if(prevPts.size() <= 10) {
goodFeaturesToTrack(currentGray, prevPts, maxCount, qLevel, minDist);
}
// 计算光流
calcOpticalFlowPyrLK(prevGray, currentGray, prevPts, nextPts, status, err,
Size(21,21), 3, termcrit);
// 筛选有效点
int k = 0;
for(size_t i = 0; i < nextPts.size(); i++) {
if(status[i] &&
(abs(prevPts[i].x - nextPts[i].x) + abs(prevPts[i].y - nextPts[i].y)) > 2) {
prevPts[k] = prevPts[i];
nextPts[k++] = nextPts[i];
}
}
prevPts.resize(k);
nextPts.resize(k);
// 绘制跟踪结果
mask.setTo(Scalar::all(0));
for(size_t i = 0; i < nextPts.size(); i++) {
line(mask, nextPts[i], prevPts[i], Scalar(0,255,0), 2);
circle(frame, nextPts[i], 3, Scalar(0,0,255), -1);
}
frame = frame & mask + Scalar(0,0,0);
add(frame, mask, frame);
// 更新参考帧
prevGray = currentGray.clone();
}
int main() {
string videoFile = "input.mp4";
initVideo(videoFile);
Mat frame, result;
while(cap.read(frame)) {
if(frame.empty()) break;
processFrame(frame);
imshow("Optical Flow Tracking", frame);
if(waitKey(30) == 27) break; // ESC退出
}
cap.release();
destroyAllWindows();
return 0;
}
关键功能说明
特征点检测
使用Shi-Tomasi角点检测算法初始化跟踪点:
goodFeaturesToTrack(gray, points, maxCount, qLevel, minDist);
maxCount
:最大检测点数(500)qLevel
:质量等级(0.01)minDist
:点间最小距离(10像素)
金字塔光流计算
采用LK光流算法处理大位移:
calcOpticalFlowPyrLK(prevGray, currentGray, prevPts, nextPts, status, err, Size(21,21), 3);
- 窗口大小:21x21
- 最大金字塔层数:3
目标区域提取
通过形态学处理强化运动区域:
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5,5)); morphologyEx(mask, mask, MORPH_CLOSE, kernel);
轨迹可视化
绘制运动轨迹线并叠加到原图:
line(mask, prevPts[i], nextPts[i], Scalar(0,255,0), 2); circle(frame, nextPts[i], 3, Scalar(0,0,255), -1);
性能优化参数
参数 | 推荐值 | 作用说明 |
---|---|---|
maxLevel |
3 | 金字塔层数,影响大位移处理 |
winSize |
21x21 | 搜索窗口大小,平衡精度与速度 |
minEigenValue |
0.01 | 特征点筛选阈值 |
maxTrackBars |
500 | 最大跟踪点数 |
典型应用场景
车辆轨迹跟踪
// 添加轨迹绘制函数 void drawTrajectory(vector<Point2f> points) { for(size_t i=1; i<points.size(); i++) { line(mask, points[i-1], points[i], Scalar(rand()%256,rand()%256,rand()%256), 2); } }
异常行为检测
// 检测突然加速 float speed = norm(nextPts[0] - prevPts[0]); if(speed > 50) { // 阈值可根据场景调整 cout << "异常运动检测!" << endl; }
多目标分离
// 基于区域的分割 vector<vector<Point>> contours; findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); for(auto& cnt : contours) { Rect rect = boundingRect(cnt); if(rect.area() > 100) { rectangle(frame, rect, Scalar(255,0,0), 2); } }
调试建议
可视化调试
分阶段显示中间结果:
imshow("Gray Frame", currentGray); imshow("Optical Flow", flow); imshow("Tracking Mask", mask);
性能监控
double t = (double)getTickCount(); processFrame(frame); t = ((double)getTickCount() - t)/getTickFrequency(); cout << "处理时间: "<< t << "秒" << endl;
参数动态调整
通过滑动条实时调整参数:
createTrackbar("Quality Level", "Control", &qLevel, 100, [](int, void*){ }); createTrackbar("Min Distance", "Control", &minDist, 50, [](int, void*){ });
扩展功能实现
目标分类集成
结合HOG特征进行目标分类:
HOGDescriptor hog; hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); vector<Rect> found; hog.detectMultiScale(frame, found);
深度信息融合
使用RGB-D相机数据:
Mat depthMap; cap >> depthMap; // 假设深度图与彩色图对齐 for(auto& pt : nextPts) { float d = depthMap.at<uint16_t>(pt); if(d > 500) { // 过滤近距离噪声 // 处理有效点 } }
GPU加速版本
启用CUDA加速:
#include <opencv2/cudafeatures2d.hpp> Ptr<cuda::OpticalFlowDual_TVL1> opticalFlow = cuda::OpticalFlowDual_TVL1::create(); opticalFlow->calc(prevGray_gpu, currentGray_gpu, flow_gpu);
参考代码 基于光流法的目标检测算法 www.youwenfan.com/contentalf/72539.html
注意事项
光照变化处理
添加直方图均衡化:
equalizeHist(gray, gray);
遮挡处理
实现特征点重检测机制:
if(count%30 == 0) { // 每30帧重检测 goodFeaturesToTrack(gray, newPoints, 100, 0.01, 7); points[0].insert(points[0].end(), newPoints.begin(), newPoints.end()); }
实时性优化
使用多线程处理:
#include <thread> void captureThread() { while(running) { cap >> frame; // 预处理 } } thread capThr(captureThread);