OpenCV findHomography и WarpPerspective не дают хороших результатов

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

vector<Point2f> obj, scene, objCorners, TransformedObjCorners;

scene.push_back(Point2f(324,21));
scene.push_back(Point2f(388,4));
scene.push_back(Point2f(392,110));
scene.push_back(Point2f(322,111));
obj.push_back(Point2f(21,18));
obj.push_back(Point2f(79,45));
obj.push_back(Point2f(76,128));
obj.push_back(Point2f(13,118));
objCorners.push_back(Point2f(0,0));
objCorners.push_back(Point2f(400,0));
objCorners.push_back(Point2f(400,300));
objCorners.push_back(Point2f(0,300));

cv::Mat H = findHomography(obj, scene);

perspectiveTransform(objCorners, TransformedObjCorners, H);
cout << "Transformed object corners are :" << endl;
cout << TransformedObjCorners << endl;

и мой результат:

Transformed object corners are :
  [309.14066, 18.626106;
  -2.5252595, 298.53754;
   31.930698, 9.6980038;
   319.43829, 279.87805]

Координаты черного ящика:

введите описание изображения здесь

введите описание изображения здесь

И вы можете увидеть, что здесь он аномально деформирован из-за отрицательных координат:

введите описание изображения здесь

Я часами пытался отследить проблему. Любая помощь / указатели в направлении записи будут очень полезны. Спасибо

Как сшить левое изображение? если я сшиваю три изображения вместе, что будет лучшим подходом? Итак, я пробую слева и посередине, а ниже мой результат, но очень слабый:

введите описание изображения здесь


person Badi8beach    schedule 07.07.2015    source источник
comment
что не так с этим изображением? матрица преобразования в порядке. Единственная проблема, которую я вижу, заключается в том, что движение камеры не дает идеального отношения гомографии между изображениями. И если вы попытаетесь исправить 3D-сцену на 2D-плоскость, вы, очевидно, получите некоторые искажения ...   -  person Micka    schedule 07.07.2015


Ответы (1)


Я использовал ваш код, адаптировал расположение точек (потому что у ваших изображений есть строка заголовка) и исказил одно из изображений.

это входные изображения с точками:

введите описание изображения здесь

введите описание изображения здесь

это код

    int main()
{
    cv::Mat input1 = cv::imread("../inputData/panoA.png");
    cv::Mat input2 = cv::imread("../inputData/panoB.png");

    cv::Mat result;


    std::vector<cv::Point2f> obj, scene, objCorners, transformedObjCorners;

    std::vector<cv::Point2f> transObj, transScene;


    // had to adjust your coordinates since you provided images with title-bar
    scene.push_back(cv::Point2f(313,47));
    scene.push_back(cv::Point2f(379,21));
    scene.push_back(cv::Point2f(385,131));
    scene.push_back(cv::Point2f(317,136));
    obj.push_back(cv::Point2f(9,41));
    obj.push_back(cv::Point2f(70,61));
    obj.push_back(cv::Point2f(69,149));
    obj.push_back(cv::Point2f(7,145));
    objCorners.push_back(cv::Point2f(0,0));
    objCorners.push_back(cv::Point2f(input2.cols,0));
    objCorners.push_back(cv::Point2f(input2.cols,input2.rows));
    objCorners.push_back(cv::Point2f(0,input2.rows));

    cv::Mat H = findHomography(obj, scene);

    for(unsigned int i=0; i<scene.size(); ++i)
    {
        cv::circle(input1, scene[i], 5, cv::Scalar(0,255,0));
    }

    for(unsigned int i=0; i<obj.size(); ++i)
    {
        cv::circle(input2, obj[i], 5, cv::Scalar(0,255,0));
    }



    cv::Mat result1;
    cv::warpPerspective(input2, result1, H, cv::Size(input1.cols*2, input1.rows));

    cv::Mat result2 = cv::Mat(result1.size(), CV_8UC3, cv::Scalar(0,0,0));
    input1.copyTo(result2(cv::Rect(0,0,input1.cols, input1.rows)));

    result = result1.clone();

    // primitive blending, non-optimized
    for(int j=0; j<result1.rows; ++j)
        for(int i=0; i<result1.cols; ++i)
        {
            cv::Vec3b c1(0,0,0);
            cv::Vec3b c2(0,0,0);

            if(j < result1.rows && i<result1.cols) c1  = result1.at<cv::Vec3b>(j,i);
            if(j < result2.rows && i<result2.cols) c2  = result2.at<cv::Vec3b>(j,i);

            bool c1_0 = false;
            bool c2_0 = false;

            if(c1 == cv::Vec3b(0,0,0)) c1_0 = true;
            if(c2 == cv::Vec3b(0,0,0)) c2_0 = true;

            cv::Vec3b color(0,0,0);

            if(!c1_0 && !c2_0)
            {
                // both nonzero: use mean value:
                color = 0.5*(c1+c2);
            }
            if(c1_0)
            {
                // c1 zero => use c2
                color = c2;
            }
            if(c2_0)
            {
                // c1 zero => use c2
                color = c1;
            }

            result.at<cv::Vec3b>(j,i) = color;

        }


    cv::imshow("input1", input1);
    cv::imshow("input2", input2);
    cv::imshow("result", result);
    cv::imwrite("../outputData/panoResult1.png", input1);
    cv::imwrite("../outputData/panoResult2.png", input2);
    cv::imwrite("../outputData/panoResult.png", result);
    cv::waitKey(0);
    return 0;
}

и вот результат с примитивным смешиванием:

введите описание изображения здесь

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

person Micka    schedule 07.07.2015
comment
Спасибо за код наложения! Что касается деформации, в вашем результате слева вы можете увидеть остатки входного изображения. почему такое поведение? Я проверил, чтобы камера вращалась вокруг центра. - person Badi8beach; 08.07.2015
comment
Я также отредактировал вопрос, можете ли вы дать некоторое представление об этом :) - person Badi8beach; 08.07.2015
comment
вращающийся вокруг центра должен быть центром камеры-обскуры. вы должны неискажать свои изображения. часть смешивания очень примитивна и, вероятно, ошибочна: D - person Micka; 08.07.2015
comment
спасибо за предложения. Я внес некоторые изменения в размещение камеры, не искажал изображения, использовал автоматическую внешнюю калибровку с шахматной доской и исправил сильный параллакс. Не могли бы вы посоветовать несколько алгоритмов смешивания в реальном времени? Я изучал смешение лапласиана и гаусса, но эффективны ли они для смешения швов? - person Badi8beach; 20.07.2015