10

高密度オプティカル フローを使用して、画像の複雑なワープを実行しようとしています。2 番目の画像を最初の画像とほぼ同じ形状にワープしようとしています。

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 );

2 つのグレースケール フレームからフローを計算します。関数を使用して、このフロー情報を使用して、元の (つまり、グレースケールではない) イメージを再マップしようとしていcv::remapます。しかし、私はそれから非常にひどく歪んだイメージを取得します。元の画像に少し似たオレンジと黒の画像になります。

cv::remap計算されたを使用するにはどうすればよいflowですか?

4

1 に答える 1

17

remap関数をflow直接操作することはできません。逆方向フロー ( からまで)を取得し、各フロー ベクトルをピクセル グリッド上の位置によってオフセットするmapことによって計算されるセパレートを使用する必要があります。以下の詳細を参照してください。frame2frame1(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))

上記の 2 つの式を比較すると、次の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);
于 2013-07-04T06:00:54.740 に答える