安卓:使用calcOpticalFlowPyrLK与MatOfPoint2f(Android: Us

2019-09-22 21:06发布

我一直无法使用calcOpticalFlowPyrLK与MatOfPoint2f。 我宣布我的类型如下:

private Mat mPreviousGray;                  // previous gray-level image
private List<MatOfPoint2f> points;          // tracked features
private MatOfPoint initial;                 // initial position of tracked points

并使用以下查找和跟踪特征(我的代码是基于在C ++中由Robert Laganiere样品光流的应用程序。)

// Called whenever a new frame m is captured
private void OpticalFlow(Mat m, int maxDetectionCount, double qualityLevel,
    double minDistance) {

    if (points.get(0).total() < maxDetectionCount/2)                // Check if new points need to be added
    {
        // maxDetectionCount = 500
        // qualityLevel = 0.01
        // minDistance = 10
        Imgproc.goodFeaturesToTrack(m, initial, maxDetectionCount, qualityLevel, minDistance);

        // add the detected features to the currently tracked features
        points.get(0).push_back(initial);
        // Have checked length of points.get(0), is not zero.
    }

    // for first image of the sequence
    if(mPreviousGray.empty())
        m.copyTo(mPreviousGray);

    if( points.get(0).total() > 0 )   // EMG - 09/22/11 - fix optical flow crashing bug 
    {       
        // 2. track features
        Video.calcOpticalFlowPyrLK(mPreviousGray, m, // 2 consecutive images
                points.get(0), // input point position in first image
                points.get(1), // output point postion in the second image
                status,    // tracking success
                error);      // tracking error
    }

    ...

    m.copyTo(mPreviousGray);

    ...
}

此前,变points为类型List<List<Point>> ,我会通过实例化一个MatOfPoint2f同类型之间的转换fromList ,并把它们递过来calcOpticalFlowPyrLK。

不过,我想不再做,因为并列出了此转换损失在点之间的对应initialpoints 。 我想保持这种对应关系,这样我就可以通过遍历同时在两个矩阵的项目画光流线。

不幸的是,现在我有以下断言失败:

09-24 10:04:30.400: E/cv::error()(8216): OpenCV Error: Assertion failed ((npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0) in void cv::calcOpticalFlowPyrLK(const cv::_InputArray&, const cv::_InputArray&, const cv::_InputArray&, const cv::_OutputArray&, const cv::_OutputArray&, const cv::_OutputArray&, cv::Size, int, cv::TermCriteria, int, double), file X:\Dev\git\opencv-2.4\modules\video\src\lkpyramid.cpp, line 593
09-24 10:04:30.400: E/AndroidRuntime(8216): FATAL EXCEPTION: Thread-321
09-24 10:04:30.400: E/AndroidRuntime(8216): CvException [org.opencv.core.CvException: X:\Dev\git\opencv-2.4\modules\video\src\lkpyramid.cpp:593: error: (-215) (npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0 in function void cv::calcOpticalFlowPyrLK(const cv::_InputArray&, const cv::_InputArray&, const cv::_InputArray&, const cv::_OutputArray&, const cv::_OutputArray&, const cv::_OutputArray&, cv::Size, int, cv::TermCriteria, int, double)
09-24 10:04:30.400: E/AndroidRuntime(8216): ]
09-24 10:04:30.400: E/AndroidRuntime(8216):     at org.opencv.video.Video.calcOpticalFlowPyrLK_2(Native Method)
09-24 10:04:30.400: E/AndroidRuntime(8216):     at org.opencv.video.Video.calcOpticalFlowPyrLK(Video.java:445)

奇怪的是,如果我添加了这一说法我自己,呼吁calcOpticalFlowPyrLK之前,它不会失败。

我希望有人能帮助我找出其中真正的问题在于,我怎么能保存帧之间的履带点之间的这种关系。

编辑 :我发现什么需要做,以避免这种说法的错误,然后应用程序行为正确,但是:

  • 我不知道为什么
  • 我现在有一个类似的问题了Calib3d.solvePnP,但应用的ConvertTo到imagePoints和objectPoints这里不解决这个问题,也没有用CvType.CV_32FC2 ,也不CvType.CV_32FCvType.CV_64F

以校正断言故障的情况下calcOpticalFlowPyrLK ,我已经改变points.get(0).push_back(initial); 以下几点:

Imgproc.goodFeaturesToTrack(m, initial, maxDetectionCount, qualityLevel, minDistance);

MatOfPoint2f initial2f = new MatOfPoint2f();
initial.convertTo(initial2f, CvType.CV_32FC2);
// add the detected features to the currently tracked features
trackedpoints.get(0).push_back(initial2f);

所以我的问题已更改为:一个人能解释一般情况下对我来说,让我知道如何与Calib3d.solvePnP也解决我的问题?

Answer 1:

calcOpticalFlowPyrLK点参数的类型MatOfPoint2f在内部是CV_32FC2的。

solvePnP第一个参数是MatOfPoint3f在内部是CV_32FC3。 尝试转换到看它是否解决。

一些OpenCV函数期待特定类型的垫子,我想你必须手动选择是正确的猜测/自动转换效率的原因,而不是OpenCV的。



Answer 2:

有人在另一个线程之前有这个问题。 我最近在OpenCV4Android的光流功能这个问题(断言)。 此解决方案仅适用,当你处理不了以前的点矩阵:

代替使用的ConvertTo()方法你应该把关键点[]数组的您从matOfKeyPoints.ToArray(拿到)的每个元素到matOfPoints2f阵列。

其原因是在解释这个页面 :

    KeyPoint[] arrayOfkp = keypoints.toArray();
    org.opencv.core.Point[] arrayOfp = new org.opencv.core.Point[arrayOfkp.length];
    for(int j =0;j<arrayOfkp.length;j++)
    {
        arrayOfp[j] = new org.opencv.core.Point(0, 0);
        arrayOfp[j].x = (int) arrayOfkp[j].pt.x;
        arrayOfp[j].y = (int) arrayOfkp[j].pt.y;
    }
    prevPts.fromArray(arrayOfp);


文章来源: Android: Using calcOpticalFlowPyrLK with MatOfPoint2f