您现在的位置是:首页 >技术教程 >基于光流方法实时跟踪目标在图像中的运动轨迹(python和C++实现)网站首页技术教程

基于光流方法实时跟踪目标在图像中的运动轨迹(python和C++实现)

高自期许 2023-05-21 16:00:02
简介基于光流方法实时跟踪目标在图像中的运动轨迹(python和C++实现)

光流方法是通过跟踪图像中的特征点(角点,边缘点等),分析这些点在帧与帧之间的运动,来计算物体运动轨迹和速度。具体实现目标如下:
1、选取图像中的易被识别的特征点,如Harris角点,FAST角点。
2、为每个特征点选取一个领域窗口,跟踪该窗口在连续视频帧中的变化。
3、计算窗口中每个像素在两帧之间的光流,也就是像素位移量,常用的光流计算方法有Lucas-Kanada法、Gunner Farneback法等。
4、根据窗口中的光流情况判断该特征点的位移量。可以采取投票机制或窗口内光流的中值作为该点的移动量。
5、 根据特征点的移动向量就可以计算出物体运动的速度和方向。 通过跟踪多个特征点并做平均可以得到更精确的运动速度估计。
6、结合物体在三维空间的位置信息,可以将二维图像平面上的特征点轨迹还原出三维空间中的运动路径。
7、当特征点消失或运动过快时,需要选取图像中新的特征点进行跟踪,确保在每一帧中有足够的特征点对物体进行跟踪。
8、根据目标的运动趋势,可以预测其未来的移动位置和速度。为了实现精确定位,预测结果需要与实时检测结果进行融合。
以上是使用光流方法实现目标跟踪的基本思路和技术步骤。通过选取图像中的特征点,分析其在连续视频帧之间的运动变化,实现对目标运动的检测、跟踪和预测。在实际实现中存在光流计算的准确性与速度问题,这需要选择适合的算法与优化方法。

python版domo
这个Demo通过Opencv的calcOpticalFlowFarneback()方法计算两帧图像之间的光流。然后绘制光流向量和场,实现了基本的目标运动跟踪和显示。
在实际项目中,可以根据光流分析得到的目标移动信息,预测其未来位置,并结合三维位置实现精确跟踪。如果光流无法准确跟踪,还需要选取新的特征点进行跟踪。
这只是一个基本Demo,实际项目实现会更加复杂。但基本思路与步骤仍然适用。请根据具体需求对代码进行完善和优化。

import cv2
import numpy as np

cap = cv2.VideoCapture('input.mp4')  # 读取视频文件
ret, frame1 = cap.read()  # 读取第一帧
prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY) # 转换为灰度图像

while(1):
    ret, frame2 = cap.read()  # 读取后续帧
    next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY) # 转化为灰度图像

    # 计算光流
    flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

    # 计算光流的角度和幅值
    h, w = next.shape[:2]
    y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
    fx, fy = flow[y,x].T
    
    # 绘制光流场和向量
    lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
    lines = np.int32(lines + 0.5)
    vis = cv2.cvtColor(next, cv2.COLOR_GRAY2BGR)
    for (x1, y1), (x2, y2) in lines:
        cv2.line(vis, (x1, y1), (x2, y2), (0, 255, 0), 1)
        cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
    #显示图像
    cv2.imshow('frame2', vis)
    prvs = next # 更新前一帧
    
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

C++版demo
该代码完成了视频中目标的光流跟踪。主要步骤为:

  1. 对第一帧图像检测Harris角点作为特征点。
  2. 读取第二帧图像,同样检测特征点。
  3. 利用calcOpticalFlowPyrLK函数计算第一帧和第二帧特征点之间的光流,获得新的特征点位置。
  4. 在图像上绘制光流跟踪结果,并更新特征点用于下一帧跟踪。
  5. 不断读取新帧并重复以上步骤,实现对目标运动的连续跟踪。
    该实现较为简单,主要目的在于演示光流方法的基本思想和步骤。实际项目中会根据具体应用对算法进行优化和改进。
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() 
{
    // 读取视频文件
    VideoCapture cap("input.avi"); 
    // 获取第一帧
    Mat frame1, frame2;
    cap >> frame1;

    // 对第一帧检测Harris角点 
    vector<Point2f> points1;
    cornerHarris(frame1, points1, 2, 3, 0.04, 3, 0);

    while (cap.read(frame2)) {
        // 对第二帧进行角点检测
        vector<Point2f> points2;
        cornerHarris(frame2, points2, 2, 3, 0.04, 3, 0);
       
        // 光流跟踪
        vector<Point2f> newPoints; 
        calcOpticalFlowPyrLK(frame1, frame2, points1, newPoints);
       
        // 显示跟踪结果 
        for (int i = 0; i < points1.size(); i++) 
        {  
            line(frame1, points1[i], newPoints[i], Scalar(0,255,0), 1.5);  
            circle(frame1, newPoints[i], 3, Scalar(0,0,255), -1); 
        }
       
        // 更新帧和跟踪角点 
        points1 = newPoints; 
        frame1 = frame2.clone();
       
        // 显示视频 
        imshow("Tracking", frame1);
       
        if (waitKey(30) == 27) break; 
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。