C++ 使用光流的 OpenCV 跟踪

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9701276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:11:11  来源:igfitidea点击:

OpenCV tracking using optical flow

c++opencvcomputer-visiontracking

提问by Alex Hoppus

I use this to functions as a base of my tracking algorithm.

我使用它作为我的跟踪算法的基础。

    //1. detect the features
    cv::goodFeaturesToTrack(gray_prev, // the image 
    features,   // the output detected features
    max_count,  // the maximum number of features 
    qlevel,     // quality level
    minDist);   // min distance between two features

    // 2. track features
    cv::calcOpticalFlowPyrLK(
    gray_prev, gray, // 2 consecutive images
    points_prev, // input point positions in first im
    points_cur, // output point positions in the 2nd
    status,    // tracking success
    err);      // tracking error

cv::calcOpticalFlowPyrLKtakes vector of points from the previous image as input, and returns appropriate points on the next image. Suppose I have random pixel (x, y) on the previous image, how can I calculate position of this pixel on the next image using OpenCV optical flow function?

cv::calcOpticalFlowPyrLK将上一张图像中的点向量作为输入,并在下一张图像上返回适当的点。假设我在上一张图像上有随机像素 (x, y),如何使用 OpenCV 光流函数计算下一张图像上该像素的位置?

回答by Chris

As you write, cv::goodFeaturesToTracktakes an image as input and produces a vector of points which it deems "good to track". These are chosen based on their ability to stand out from their surroundings, and are based on Harris corners in the image. A tracker would normally be initialised by passing the first image to goodFeaturesToTrack and obtaining a set of features to track. These features could then be passed to cv::calcOpticalFlowPyrLKas the previous points, along with the next image in the sequence and it will produce the next points as output, which then become input points in the next iteration.

在您编写时,cv::goodFeaturesToTrack将图像作为输入并生成它认为“适合跟踪”的点向量。这些是根据它们从周围环境中脱颖而出的能力来选择的,并且基于图像中的哈里斯角。通常通过将第一张图像传递给 goodFeaturesToTrack 并获取一组要跟踪的特征来初始化跟踪器。然后,这些特征可以cv::calcOpticalFlowPyrLK作为前一个点与序列中的下一个图像一起传递,它将产生下一个点作为输出,然后在下一次迭代中成为输入点。

If you want to try to track a different set of pixels (rather than features generated by cv::goodFeaturesToTrackor a similar function), then simply provide these to cv::calcOpticalFlowPyrLKalong with the next image.

如果您想尝试跟踪一组不同的像素(而不是由cv::goodFeaturesToTrack或类似函数生成的特征),那么只需将这些cv::calcOpticalFlowPyrLK与下一张图像一起提供即可。

Very simply, in code:

很简单,在代码中:

// Obtain first image and set up two feature vectors
cv::Mat image_prev, image_next;
std::vector<cv::Point> features_prev, features_next;

image_next = getImage();

// Obtain initial set of features
cv::goodFeaturesToTrack(image_next, // the image 
  features_next,   // the output detected features
  max_count,  // the maximum number of features 
  qlevel,     // quality level
  minDist     // min distance between two features
);

// Tracker is initialised and initial features are stored in features_next
// Now iterate through rest of images
for(;;)
{
    image_prev = image_next.clone();
    feature_prev = features_next;
    image_next = getImage();  // Get next image

    // Find position of feature in new image
    cv::calcOpticalFlowPyrLK(
      image_prev, image_next, // 2 consecutive images
      points_prev, // input point positions in first im
      points_next, // output point positions in the 2nd
      status,    // tracking success
      err      // tracking error
    );

    if ( stopTracking() ) break;
}

回答by MSeskas

cv::calcOpticalFlowPyrLK(..)function uses arguments :

cv::calcOpticalFlowPyrLK(..)函数使用参数:

cv::calcOpticalFlowPyrLK(prev_gray, curr_gray, features_prev, features_next, status, err);

cv::calcOpticalFlowPyrLK(prev_gray, curr_gray, features_prev, features_next, status, err);

cv::Mat prev_gray, curr_gray;
std::vector<cv::Point2f> features_prev, features_next;
std::vector<uchar> status;
std::vector<float> err;

simplest(partial) code to find pixel in next frame :

在下一帧中查找像素的最简单(部分)代码:

features_prev.push_back(cv::Point(4, 5));
cv::calcOpticalFlowPyrLK(prev_gray, curr_gray, features_prev, features_next, status, err);

If pixel was successfully found status[0] == 1and features_next[0]will show coordinates of pixel in next frame. Value information can be found in this example: OpenCV/samples/cpp/lkdemo.cpp

如果像素被成功找到status[0] == 1features_next[0]将在下一帧中显示像素的坐标。可以在此示例中找到值信息:OpenCV/samples/cpp/lkdemo.cpp