Проблемы с деформацией OpenCVПерспектива

0

Я работаю над проектом вычитания фона Android, с движущейся камерой. Я пытаюсь использовать сопоставление функций, findHomography и warpPerspective, чтобы найти перекрывающиеся пиксели между двумя кадрами. Однако вывод, который я получаю, немного некорректен. Я совершенно новичок в обработке изображений, поэтому я не знаком со всей терминологией. У меня есть 2 основных вопроса:

1) Результат warpPerspective чрезмерно искажен - например, изображение искажено, объекты на изображении перевернуты, скручены и т.д. Как это решить?

2) Иногда я получаю сообщение об ошибке "Ошибка с ошибкой OpenCV: ошибка присвоения", что приводит к сбою моего приложения. Эта ошибка отображается в warpPerspective. Примечания: размеры в image1 (предыдущий кадр) и image2 (текущий кадр) одинаковы. Я преобразую изображения в серый цвет до обнаружения функций (в настоящее время от RGB). Я иногда получал аналогичную ошибку с подтверждением OpenCV с помощью findHomography, но я узнал, что ей нужно как минимум 4 балла, поэтому добавление оператора if решило его, но не удалось решить проблему с помощью warpPerspective.

Ошибка, которую я получаю:

02-24 15:30:49.554: E/cv::error()(4589): OpenCV Error: Assertion failed (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) 
    in void cv::batchDistance(cv::InputArray, cv::InputArray, cv::OutputArray, int, cv::OutputArray, int, int, cv::InputArray, int, bool), 
    file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/core/src/stat.cpp, line 2473

Мой код:

void stitchFrames(){

    //convert frames to grayscale
    image1 = prevFrame.clone();
    image2 = currFrame.clone();

    if(colourSpace==1){ //convert from RGB to gray
        cv::cvtColor(image1, image1Gray,CV_RGB2GRAY);
        cv::cvtColor(image2, image2Gray,CV_RGB2GRAY);
    }
    else if(colourSpace==2){ //convert from HSV to gray
        cv::cvtColor(image1, image1Gray,CV_HSV2RGB);
        cv::cvtColor(image1Gray,image1Gray,CV_RGB2GRAY);
        cv::cvtColor(image2, image1Gray,CV_HSV2RGB);
        cv::cvtColor(image2Gray,image1Gray,CV_RGB2GRAY);
    }

    else if(colourSpace==3){ //no need for conversion
        image1Gray = image1;
        image2Gray = image2;
    }

    //----FEATURE DETECTION----

    //key points
    std::vector<KeyPoint> keypoints1, keypoints2;

    int minHessian;

    cv::FastFeatureDetector detector;

    detector.detect(image1Gray,keypoints1); //prevFrame
    detector.detect(image2Gray,keypoints2); //currFrame

    KeyPoint kp = keypoints2[4];
    Point2f p = kp.pt;
    float i = p.y;

    //---FEATURE EXTRACTION----

    //extracted descriptors
    cv::Mat descriptors1,descriptors2;

    OrbDescriptorExtractor extractor;
    extractor.compute(image1,keypoints1,descriptors1); //prevFrame
    extractor.compute(image2,keypoints2,descriptors2); //currFrame

    //----FEATURE MATCHING----

    //BruteForceMacher

    BFMatcher matcher;

    std::vector< cv::DMatch > matches; //result of matching descriptors
    std::vector< cv::DMatch > goodMatches; //result of sifting matches to get only 'good' matches

    matcher.match(descriptors1,descriptors2,matches);

    //----HOMOGRAPY - WARP-PERSPECTIVE - PERSPECTIVE-TRANSFORM----

    double maxDist = 0.0; //keep track of max distance from the matches
    double minDist = 80.0; //keep track of min distance from the matches

    //calculate max & min distances between keypoints
    for(int i=0; i<descriptors1.rows;i++){
        DMatch match = matches[i];

        float dist = match.distance;
        if (dist<minDist) minDist = dist;
        if(dist>maxDist) maxDist=dist;
    }

    //get only the good matches
    for( int i = 0; i < descriptors1.rows; i++ ){
        DMatch match = matches[i];
        if(match.distance< 500){
            goodMatches.push_back(match);
        }
    }

    std::vector< Point2f > obj;
    std::vector< Point2f > scene;

    //get the keypoints from the good matches
    for( int i = 0; i < goodMatches.size(); i++ ){

        //--keypoints from image1
        DMatch match1 = goodMatches[i];
        int qI1 = match1.trainIdx;
        KeyPoint kp1 = keypoints2[qI1];
        Point2f point1 = kp1.pt;
        obj.push_back(point1);

        //--keypoints from image2
        DMatch match2 = goodMatches[i];
        int qI2 = match2.queryIdx;
        KeyPoint kp2 = keypoints1[qI2];
        Point2f point2 = kp2.pt;
        scene.push_back(point2);

    }

    //calculate the homography matrix
    if(goodMatches.size() >=4){
        Mat H = findHomography(obj,scene, CV_RANSAC);

        warpPerspective(image2,warpResult,H,Size(image1.cols,image1.rows));
    }
}
  • 0
    Вы нашли какое-нибудь решение для этого? У меня похожая проблема.
Теги:
opencv
image-processing
feature-detection

2 ответа

0

Что касается (1), то я предполагаю, что гомография, которую вы оцениваете, основана на плохих матчах.

Сначала я начну с использования ORB-детектора вместо FAST, а затем измените параметр findHomography ransacReprojThreshold. Значение по умолчанию - 3, подробности:

ransacReprojThreshold:

Максимально допустимая ошибка перепрограммирования для обработки пары точек как более интенсивной (используется только в методе RANSAC). То есть, если:

| dstPoints_i - convertPointsHomogeneous (H * srcPoints_i) | > ransacReprojThreshold

то точка я считается выбросом. Если srcPoints и dstPoints измеряются в пикселях, обычно имеет смысл установить этот параметр где-то в диапазоне от 1 до 10.

Другими словами, если предположить, что по умолчанию 3 пикселя, если после применения гомографии к srcPoint его расстояние до dstPoint составляет более 3 пикселей, эта пара считается более медленной (то есть: хорошей).

Это только начало, это также поможет вам найти лучший фильтр для хороших матчей и хорошую гомографию, вы найдете несколько ответов на эти вопросы:

OpenCV Orb не находит совпадений.

Как вы можете определить, приемлема ли матрица гомографии или нет?

  • 0
    Спасибо за ваш ответ. Я попробовал ваше предложение, но, к сожалению, оно не сильно изменилось. Действительно, я сначала попробовал на 2 изображениях, но деформация была не идеальна - так что неудивительно, что в прямом эфире видео выход не такой, как ожидалось. Я пробовал несколько комбинаций алгоритмов, но я не думаю, что это имеет большое значение (кроме, возможно, скорости). Я также ограничен отсутствием доступа к SURF / SIFT на OpenCV Android. Я буду исследовать темы, которые вы связали.
  • 0
    Но варп всегда не прав? По крайней мере, некоторые кадры видео должны быть в порядке.
Показать ещё 2 комментария
0

Что касается вашего первого вопроса, я думаю, что искажение, о котором вы говорите, связано с тем, что:

  • вы оцениваете гомографию H отображающую координаты в image1, для координат на изображении 2. Когда вы делаете Mat H = findHomography(obj,scene, CV_RANSAC); , obj - координаты точки на изображении 1, а scene - координаты точки на изображении 2.

  • вы затем использовать H в функции warpPerspective, как если бы это было отображение координат в образе 2 координатам в изображении 1, так как вы ожидаете, чтобы превратить image2 в warpResult, который я предполагаю, должен быть пришита к image1.

Следовательно, вы должны оценить гомографию H следующим образом: Mat H = findHomography(scene, obj, CV_RANSAC); ,

Что касается вашего второго вопроса, я думаю, что это вызвано этой инструкцией:

matcher.match(descriptors1,descriptors2,matches);

Ошибка говорит, что выражение

(type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U))

было признано ложным, тогда как функция должна работать. Аналогичная проблема была решена здесь: перед вызовом match функции, необходимо вручную проверить, верно следующее:

(descriptors1.type()==descriptors2.type() && descriptors1.cols==descriptors2.cols)
  • 0
    Спасибо за ваш ответ. Ваше предложение на 2-й вопрос работает - я не вижу больше ошибки. Тем не менее, проблема в 1-м вопросе все еще остается, после вашего предложения Mat H = findHomography(scene, obj, CV_RANSAC);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню