Деформация изображения OpenCV на основе calcOpticalFlowFarneback

Я пытаюсь выполнить сложную деформацию изображения с помощью Dense Optical Flow. Я пытаюсь преобразовать второе изображение примерно в ту же форму, что и первое изображение.

cv::Mat flow;
cv::calcOpticalFlowFarneback( mGrayFrame1, mGrayFrame2, flow, 0.5, 3, 15, 3, 5, 1.2, 0 );

cv::Mat newFrame = cv::Mat::zeros( frame.rows, frame.cols, frame.type() );
cv:remap( frame, newFrame, flow, cv::Mat(), CV_INTER_LINEAR );

Я рассчитываю поток из двух кадров в градациях серого. Теперь я пытаюсь переназначить свое исходное (то есть не в оттенках серого) изображение, используя эту информацию о потоке, используя функцию cv::remap. Однако я получаю от него очень сильно искаженное изображение. Я просто получаю оранжево-черное изображение, которое имеет небольшое сходство с моим исходным изображением.

Как использовать cv::remap с рассчитанным flow?


person Goz    schedule 03.07.2013    source источник
comment
Здравствуйте, я видел этот пост, и у меня примерно такая же проблема (точно такая же проблема в окончательном варианте), и мне было интересно, нашли ли вы способ сделать это? (Я знаю, что этот пост старый, и я прошу прощения за это, но я не нахожу никакого ответа в реальном времени :о) Большое спасибо!   -  person Raph Schim    schedule 25.04.2016
comment
@RaphaelShimchowitsch: Наверное, лучше всего задать свой вопрос. Нет, даже если у меня все еще есть код, который я написал для этого... Однако у меня что-то заработало. Теперь уверен, если бы это было с оптическим потоком, хотя ...   -  person Goz    schedule 25.04.2016
comment
Ахах, хорошо, я уже задавал свой вопрос, но я нашел этот пост, поэтому мне просто интересно, не могли бы вы мне помочь :) Но ладно ^^ Большое спасибо за ваш ответ :)   -  person Raph Schim    schedule 26.04.2016


Ответы (1)


Функция remap не может напрямую работать с flow. Необходимо использовать отдельный map, который вычисляется путем взятия обратного потока (от frame2 до frame1) и последующего смещения каждого вектора потока по его (x, y) местоположению на пиксельной сетке. Подробнее см. ниже.

Вспомним формулу обратного оптического потока:

frame1(x, y) = frame2(x + flowx(x, y), y + flowy(x, y))

Функция remap преобразует исходное изображение, используя указанный map:

dst(x, y) = src(mapx(x, y), mapy(x, y))

Сравнив два приведенных выше уравнения, мы можем определить map, которое требуется для remap:

mapx(x, y) = x + flowx(x, y)
mapy(x, y) = y + flowy(x, y)

Пример:

Mat flow; // backward flow
calcOpticalFlowFarneback(nextFrame, prevFrame, flow);

Mat map(flow.size(), CV_32FC2);
for (int y = 0; y < map.rows; ++y)
{
    for (int x = 0; x < map.cols; ++x)
    {
        Point2f f = flow.at<Point2f>(y, x);
        map.at<Point2f>(y, x) = Point2f(x + f.x, y + f.y);
    }
}

Mat newFrame;
remap(prevFrame, newFrame, map);
person jet47    schedule 04.07.2013
comment
Гениально, это многое объясняет. К сожалению, поток не содержит данных, которые я думал, что это так, вернемся к чертежной доске и, возможно, скоро появится еще один вопрос! Спасибо! - person Goz; 04.07.2013
comment
Обратите внимание на использование обратного потока, то есть от nextFrame к prevFrame. Это нужно, потому что векторы потока даны для исходных пикселей (куда это делось), а нас интересуют конечные пиксели (откуда это взялось). - person lapis; 26.08.2015