在OpenCV中跟踪连续帧中的特性

Keeping track of features in successive frames in OpenCV

本文关键字:连续 OpenCV 跟踪      更新时间:2023-10-16

我写了一个程序,使用goodFeaturesToTrack和calcOpticalFlowPyrLK从一帧到另一帧跟踪特征。该程序可以可靠地工作,并且可以从前一帧估计Android相机上预览图像中的光流。下面是一些描述一般过程的代码片段:

goodFeaturesToTrack(grayFrame, corners, MAX_CORNERS, quality_level,
        min_distance, cv::noArray(), eig_block_size, use_harris, 0.06);

if (first_time == true) {
    first_time = false;
    old_corners = corners;
    safe_corners = corners;
    mLastImage = grayFrame;
} else {
    if (old_corners.size() > 0 && corners.size() > 0) {
        safe_corners = corners;
        calcOpticalFlowPyrLK(mLastImage, grayFrame, old_corners, corners,
                status, error, Size(21, 21), 5,
                TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30,
                        0.01));
    } else {
        //no features found, so let's start over.
        first_time = true;
    }
}

上面的代码在循环中一遍又一遍地运行,在每次迭代中捕获一个新的预览帧。Safe_corners、old_corners和corners都是类vector 。上面的代码工作得很好。

现在,对于我已经确定的每个特征,我希望能够分配关于该特征的一些信息…发现的次数,也许是特征的描述符,谁知道…我的第一个方法是:

class Feature: public Point2f {
private:
  //things about a feature that I want to track
public: 
  //getters and fetchers and of course:
  Feature() {
    Point2f();
  }
  Feature(float a, float b) { 
    Point2f(a,b);
  }
}

接下来,我所有的输出数组从vector 指向向量<在我自己扭曲的世界里,Feature>应该是有效的,因为Feature被定义为Point2f的后代类。多态应用,我想不出任何好的理由为什么这个会吐在我身上,除非我做了其他可怕的错误。

这是我得到的错误信息。

OpenCV错误:Assertion failed (func != 0) in void cv::Mat::convertTo(cv::OutputArray, int, double, double) const,文件/home/reports/ci/slave50- sdk/OpenCV/modules/core/src/convert.cpp,第1095行

所以,我对论坛的问题是,OpenCV函数是否真的需要一个Point2f向量,或者Point2f的后代类是否也能工作?下一步是让gdb与Android手机上的移动代码一起工作,并更准确地看到它在哪里崩溃,但是如果我的方法从根本上有缺陷,我不想走这条路。

或者,如果使用上述方法跨多个帧跟踪一个特征,每个点的内存地址是否会改变?

简短的回答是, OpenCV函数确实需要std::vector<cv::Point2f>作为参数。

注意,向量本身包含cv::Point2f对象,而不是指向cv::Point2f指针,因此没有多态行为。

此外,让Feature继承cv::Point2f可能不是理想的解决方案。在这种情况下使用组合会更简单,更不用说建模正确的关系(Feature has-a cv::Point2f)。

依赖对象在内存中的位置也可能不是一个好主意。相反,请仔细阅读您所选择的数据结构。

我刚刚进入OpenCV自己,所以不能解决代码的这方面,但你的问题可能是一个bug在你的代码,导致一个未初始化的基类(至少没有初始化你可能期望的)。你的代码应该像这样:

Feature()
  : Point2f()
{
}
Feature(float a, float b)
  : Point2f(a,b)
{
}

你的实现在构造函数中创建了两个临时的Point2f对象。这些临时对象不初始化Feature对象的Point2f基类,并且这些临时对象在构造函数的末尾被销毁。