2013-10-30 11 views
6

私はiPadでキャプチャした画像のマーカーを検出しています。そのため、それらの間の平行移動と回転を計算したいので、これらのイメージのイメージの変更を変更したいので、マーカーの上に直接キャプチャしているように見えます。OpenCV:画像全体にwrapPerspective

photo 1 photo 2 photo 3

として:今私は、これらの結果は、(warpPerspectiveの結果のための右下の隅を見て)与え

points2D.push_back(cv::Point2f(0, 0)); 
points2D.push_back(cv::Point2f(50, 0)); 
points2D.push_back(cv::Point2f(50, 50)); 
points2D.push_back(cv::Point2f(0, 50)); 

Mat perspectiveMat = cv::getPerspectiveTransform(points2D, imagePoints); 
cv::warpPerspective(*_image, *_undistortedImage, M, cv::Size(_image->cols, _image->rows)); 

を使用してい

結果画像の左上隅に認識マーカーが含まれていることがわかります。私の問題は、(切り抜かずに)画像全体をキャプチャしたいので、後でその画像上の他のマーカーを検出できるということです。

どうすればいいですか?たぶん私はsolvePnP機能から回転/翻訳ベクトルを使用する必要がありますか?

EDIT:

生憎のワープ画像のサイズを変更すると、画像がまだ翻訳されているため、そのマーカーの左上隅には画像の左上隅にある、あまり役に立ちません。例えば

私が使用してサイズを倍増しました:私はこれらのイメージ受け取ってきました

cv::warpPerspective(*_image, *_undistortedImage, M, cv::Size(2*_image->cols, 2*_image->rows)); 

photo 4 photo 5

答えて

3

をあなたのコードはそう、完全ではないようです問題が何であるかを言うことは難しい。

いずれの場合も、ワープ画像は入力画像と比べて大きさが異なる可能性があります。そのため、warpPerspectiveに使用しているサイズパラメータを調整する必要があります。

たとえばサイズを2倍してみてください:

cv::warpPerspective(*_image, *_undistortedImage, M, 2*cv::Size(_image->cols, _image->rows)); 

編集:

画像全体が、この画像の中にあることを確認するには、元の画像のすべてのコーナーは、結果内であることをワープする必要があります画像。したがって、各コーナーポイントのワープされた目的地を計算し、それに応じて目的地点を調整するだけです。

それがより明確にいくつかのサンプルコードにするには:私は、出力画像が異なるdimenstionsを持つことができることを知っている

// calculate transformation 
cv::Matx33f M = cv::getPerspectiveTransform(points2D, imagePoints); 

// calculate warped position of all corners 

cv::Point3f a = M.inv() * cv::Point3f(0, 0, 1); 
a = a * (1.0/a.z); 

cv::Point3f b = M.inv() * cv::Point3f(0, _image->rows, 1); 
b = b * (1.0/b.z); 

cv::Point3f c = M.inv() * cv::Point3f(_image->cols, _image->rows, 1); 
c = c * (1.0/c.z); 

cv::Point3f d = M.inv() * cv::Point3f(_image->cols, 0, 1); 
d = d * (1.0/d.z); 

// to make sure all corners are in the image, every position must be > (0, 0) 
float x = ceil(abs(min(min(a.x, b.x), min(c.x, d.x)))); 
float y = ceil(abs(min(min(a.y, b.y), min(c.y, d.y)))); 

// and also < (width, height) 
float width = ceil(abs(max(max(a.x, b.x), max(c.x, d.x)))) + x; 
float height = ceil(abs(max(max(a.y, b.y), max(c.y, d.y)))) + y; 

// adjust target points accordingly 
for (int i=0; i<4; i++) { 
    points2D[i] += cv::Point2f(x,y); 
} 

// recalculate transformation 
M = cv::getPerspectiveTransform(points2D, imagePoints); 

// get result 
cv::Mat result; 
cv::warpPerspective(*_image, result, M, cv::Size(width, height), cv::WARP_INVERSE_MAP); 
+0

は、私は(結果のために編集された質問を見て)、それらを倍増して試してみたが、それはしませんでした私に有用な結果をもたらしました。 あなたは私のコードが不完全であると言います - 私は何よりも追加する必要がありますか?私は変換行列を得るために 'getPerspectiveTransform'を使用しています、そして、' dst'行列として検出されたマーカーの角の座標を使用しています(OpenCVドキュメンテーションによると - http://docs.opencv.org/modules/imgproc /doc/geometric_transformations.html#getperspectivetransform)。 – Axadiw

+0

あなたの目標座標(-6、-6)などはちょっと変だと思います。これは、ターゲットの矩形が、結果のイメージ内のこれらの座標にあることを意味するためです。それらを移動するには、ターゲットの矩形をターゲット画像の中央に移動するだけです。 – littleimp

+0

ありがとうございます - 間違ったpoints2D配列を投稿したことがわかりました(私は今質問で編集しました)。 これらの点を少しシフトすると出力画像全体が移動しましたが、まだ一部を切り取っています。 – Axadiw

関連する問題