私は4台の固定カメラを使用しています。カメラは相互に移動しません。そして、それらからのビデオ画像をリアルタイムで1つのビデオ画像につなぎ合わせたい。
私はこのOpenCV2.4.10に使用し、 _cv:stitcher
_ クラスは次のようになります。
_// use 4 video-cameras
cv::VideoCapture cap0(0), cap1(1), cap2(2), cap3(3);
bool try_use_gpu = true; // use GPU
cv::Stitcher stitcher = cv::Stitcher::createDefault(try_use_gpu);
stitcher.setWarper(new cv::CylindricalWarperGpu());
stitcher.setWaveCorrection(false);
stitcher.setSeamEstimationResol(0.001);
stitcher.setPanoConfidenceThresh(0.1);
//stitcher.setSeamFinder(new cv::detail::GraphCutSeamFinder(cv::detail::GraphCutSeamFinderBase::COST_COLOR_GRAD));
stitcher.setSeamFinder(new cv::detail::NoSeamFinder());
stitcher.setBlender(cv::detail::Blender::createDefault(cv::detail::Blender::NO, true));
//stitcher.setExposureCompensator(cv::detail::ExposureCompensator::createDefault(cv::detail::ExposureCompensator::NO));
stitcher.setExposureCompensator(new cv::detail::NoExposureCompensator());
std::vector<cv::Mat> images(4);
cap0 >> images[0];
cap1 >> images[1];
cap2 >> images[2];
cap3 >> images[3];
// call once!
cv::Stitcher::Status status = stitcher.estimateTransform(images);
while(true) {
// **lack of speed, even if I use old frames**
// std::vector<cv::Mat> images(4);
//cap0 >> images[0];
//cap1 >> images[1];
//cap2 >> images[2];
//cap3 >> images[3];
cv::Stitcher::Status status = stitcher.composePanorama(images, pano_result);
}
_
10 FPS(フレーム/秒)しか得られませんが、25FPSが必要です。この例を加速するにはどうすればよいですか?
stitcher.setWarper(new cv::PlaneWarperGpu());
を使用すると、非常に拡大された画像が得られます。これは必要ありません。
のみ-翻訳が必要です。
たとえば、私は使用しない準備ができています:
どうすればいいですか?または、各画像の翻訳の_cv::Stitcher stitcher
_パラメータ_x,y
_からどのように取得できますか?
UPDATE-Windows 7x64上のMSVS2013でのプロファイリング:
_cv::Stitcher
_はかなり遅いです。カメラが確実に相互に移動せず、変換があなたが言うほど単純である場合は、 homographies をチェーンするだけで、画像を空白のキャンバスにオーバーレイできるはずです。
以下はやや数学的なものです-これが明確でない場合は、LaTeXを使用して適切に記述できますが、SOはかなりの数学をサポートしていません:)
左から右に_(C_1, C_2, C_3, C_4)
_の4つのカメラのセットがあり、4つの画像のセット_(I_1, I_2, I_3, I_4)
_を提供します。
_I_1
_から_I_2
_に変換するには、ホモグラフィと呼ばれる3x3の変換行列があります。これを_H_12
_と呼びます。同様に、_I_2
_から_I_3
_の場合は_H_23
_になり、_I_3
_から_I_4
_の場合は_H_34
_になります。
これらのホモグラフィは、標準的な方法を使用して事前に事前に調整できます( オーバーラップするカメラ間のポイントマッチング )。
キャンバスとして機能するには、空白のマトリックスを作成する必要があります。これのサイズを推測するか(4 * image_sizeで十分です)、右上隅を取り(これを_P1_tr
_と呼びます)、3つのホモグラフィで変換して、の右上に新しい点を与えることができます。パノラマ、_PP_tr
_(以下は_P1_tr
_が行列に変換されていることを前提としています):
_PP_tr = H_34 * H_23 * H_12 * P1_tr'
_
これは、_P1_tr
_を取得し、最初にカメラ2に変換し、次に_C_2
_から_C_3
_に、最後に_C_3
_から_C_4
_に変換します。
画像1と2、画像1、2と3、最後に画像1〜4を組み合わせるには、これらのいずれかを作成する必要があります。これらを_V_12
_、_V_123
_、_V_1234
_それぞれ。
以下を使用して、画像をキャンバスにワープします。
_cv::warpAffine(I_2, V_12, H_12, V_12.size( ));
_
次に、次の画像でも同じことを行います。
_cv::warpAffine(I_3, V_123, H_23*H_12, V_123.size( ));
cv::warpAffine(I_4, V_1234, H_34*H_23*H_12, V_1234.size( ));
_
これで、4つのキャンバスができました。これらはすべて、4つの結合された画像の幅であり、画像の1つがそれぞれの関連する場所に変換されています。
残っているのは、変換された画像を互いにマージすることだけです。これは、関心領域を使用して簡単に実現できます。
ROIマスクの作成は、フレームキャプチャを開始する前に、事前に行うことができます。
キャンバスと同じサイズの空白(ゼロ)の画像から始めます。左端の長方形を_I_1
_のサイズで白に設定します。これは最初の画像のマスクです。これを_M_1
_と呼びます。
次に、2番目の変換された画像のマスクを取得するために、
_cv::warpAffine(M_1, M_2, H_12, M_1.size( ));
cv::warpAffine(M_2, M_3, H_23*H_12, M_1.size( ));
cv::warpAffine(M_3, M_4, H_34*H_23*H_12, M_1.size( ));
_
すべての画像を1つのパノラマにまとめるには、次のようにします。
_cv::Mat pano = zeros(M_1.size( ), CV_8UC3);
I_1.copyTo(pano, M_1);
V_12.copyTo(pano, M_2):
V_123.copyTo(pano, M_3):
V_1234.copyTo(pano, M_4):
_
ここで行っているのは 各キャンバスの関連領域をコピーする 出力画像にパノラマ-高速操作です。
GPUでこれらすべてを実行できるはずです。_cv::gpu::Mat
_を_cv::Mats
_に、非GPUの対応物を_cv::gpu::warpAffine
_に置き換えます。
注:cv :: Matを使用しているときにGPUがすでに使用されているようですが、提案した方法が機能していないように見えるため、この回答は試行した内容のドキュメントとして残しておきます。
gpu::GpuMat
を使用してみてください:
std::vector<cv::Mat> images(4);
std::vector<gpu::GpuMat> gpuImages(4);
gpu::GpuMat pano_result_gpu;
cv::Mat pano_result;
bool firstTime = true;
[...]
cap0 >> images[0];
cap1 >> images[1];
cap2 >> images[2];
cap3 >> images[3];
for (int i = 0; i < 4; i++)
gpuImages[i].upload(images[i]);
if (firstTime) {
cv::Stitcher::Status status = stitcher.estimateTransform(gpuImages);
firstTime = false;
}
cv::Stitcher::Status status = stitcher.composePanorama(gpuImages, pano_result_gpu);
pano_result_gpu.download(pano_result);