Android: использование calcOpticalFlowPyrLK с MatOfPoint2f

Мне не удалось использовать calcOpticalFlowPyrLK с MatOfPoint2f. Я объявил свои типы следующим образом:

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

И используйте следующее, чтобы найти и отследить функции (Мой код основан на примере приложения оптического потока на C ++ от Роберта Лаганьера.)

// 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.

Однако я больше не хотел этого делать, потому что это преобразование из и в списки теряет соответствие между точками в initial и points. Я хочу сохранить это соответствие, чтобы я мог рисовать линии оптического потока, перебирая элементы в обеих матрицах одновременно.

К сожалению, теперь у меня есть следующая ошибка утверждения:

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_32F, ни с CvType.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?


person user1378489    schedule 24.09.2012    source источник
comment
Если вы копируете m в mPreviousGray перед оптическим потоком, разве это не одно и то же изображение, а не 2 последовательных изображения?   -  person Rui Marques    schedule 27.09.2012
comment
Да это потому что в первый раз mPreviousGray еще нет. По точкам... есть еще копия от m на mPreviousGray.   -  person user1378489    schedule 27.09.2012
comment
mMOP2fptsThisConverted = новый MatOfPoint2f(); mMOP2fptsPrevConverted = новый MatOfPoint2f(); mMOP2fptsPrev.convertTo(mMOP2fptsPrevConverted, CvType.CV_32FC2); mMOP2fptsThis.convertTo(mMOP2fptsThisConverted, CvType.CV_32FC2); Video.calcOpticalFlowPyrLK(matOpFlowPrev, matOpFlowThis, mMOP2fptsPrevConverted, mMOP2fptsThisConverted, mMOBStatus, mMOFerr); я все еще получаю ту же ошибку. кто-нибудь помогите в этом, пожалуйста   -  person Iftikar Urrhman Khan    schedule 23.08.2015


Ответы (2)


Параметры точки calcOpticalFlowPyrLK имеют тип MatOfPoint2f, который внутренне равен CV_32FC2.

Первым параметромsolvePnP является MatOfPoint3f, который внутренне равен CV_32FC3. Попробуйте преобразовать в это, чтобы увидеть, исправит ли это.

Некоторые функции opencv ожидают определенных типов Mat, я думаю, по соображениям эффективности вам нужно вручную выбирать правильные, вместо автоматического угадывания/преобразования opencv.

person Rui Marques    schedule 01.10.2012

у кого-то в другом потоке уже была эта проблема. Недавно у меня была эта проблема (утверждение) в функции оптического потока OpenCV4Android. это решение работает только тогда, когда вы не могли обработать предыдущую матрицу точек:

вместо использования метода convertTo() вы должны поместить каждый элемент массива Keypoint[], который вы получили из 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);
person Community    schedule 04.04.2013