2Dポイントを3D位置に変換する


9

私は知られているとの固定カメラを持っているcameraMatrixdistCoeffs。私は、あまりにも固定されているチェス盤を持っている、とtransformし、rotationベクトルも使用して計算されていますsolvePnP

次の図のように、チェス盤が配置されているのと同じ平面上にある2Dポイントの3D位置を取得するにはどうすればよいのでしょうか。

ここに画像の説明を入力してください

確かなことは、その点のZは0ですが、その点のXYを取得する方法です。


変換ベクトルと回転ベクトルで、チェス盤のすべてのコーナーを3Dで説明できますか?
Micka

Zが0になると言う場合、その点の平面座標を取得するだけで問題ありませんか?「赤い方向に10 cm進み、緑色の方向にマイナス15 cm進むか?
Micka

この習慣仕事@Micka、近いカメラピクセルので、大きな面積表す
EBAG

将来のホモグラフィで平面座標を取得するのは簡単です。ただし、カメラの3次元空間の3次元点が必要な場合は、後で回転ベクトルと並進ベクトルに従って平面を変換する必要があります。
Micka

この点座標の期待される結果を提供できますか?
AbdelAziz AbdelLatef

回答:


6

これは、3つの簡単な手順で解決できます。

ステップ1:

カメラの投影モデルを反転して、指定された2D画像点に対応する光線の、カメラの座標フレームで表される3D方向ベクトルを計算します。

std::vector<cv::Point2f> imgPt = {{u,v}}; // Input image point
std::vector<cv::Point2f> normPt;
cv::undistortPoints     (imgPt, normPt, cameraMatrix, distCoeffs);
cv::Matx31f ray_dir_cam(normPt[0].x, normPt[0].y, 1);
// 'ray_dir_cam' is the 3d direction of the ray in camera coordinate frame
// In camera coordinate frame, this ray originates from the camera center at (0,0,0)

ステップ2:

カメラとチェス盤の相対ポーズを使用して、チェス盤に取り付けられた座標フレームでこの光線のベクトルの3D方向を計算します。

// solvePnP typically gives you 'rvec_cam_chessboard' and 'tvec_cam_chessboard'
// Inverse this pose to get the pose mapping camera coordinates to chessboard coordinates
cv::Matx33f R_cam_chessboard;
cv::Rodrigues(rvec_cam_chessboard, R_cam_chessboard);
cv::Matx33f R_chessboard_cam = R_cam_chessboard.t();
cv::Matx31f t_cam_chessboard = tvec_cam_chessboard;
cv::Matx31f pos_cam_wrt_chessboard = -R_chessboard_cam*t_cam_chessboard;
// Map the ray direction vector from camera coordinates to chessboard coordinates
cv::Matx31f ray_dir_chessboard = R_chessboard_cam * ray_dir_cam;

ステップ3:

3DレイとZ = 0のチェス盤平面の間の交差を計算して、目的の3Dポイントを見つけます。

// Expressed in the coordinate frame of the chessboard, the ray originates from the
// 3d position of the camera center, i.e. 'pos_cam_wrt_chessboard', and its 3d
// direction vector is 'ray_dir_chessboard'
// Any point on this ray can be expressed parametrically using its depth 'd':
// P(d) = pos_cam_wrt_chessboard + d * ray_dir_chessboard
// To find the intersection between the ray and the plane of the chessboard, we
// compute the depth 'd' for which the Z coordinate of P(d) is equal to zero
float d_intersection = -pos_cam_wrt_chessboard.val[2]/ray_dir_chessboard.val[2];
cv::Matx31f intersection_point = pos_cam_wrt_chessboard + d_intersection * ray_dir_chessboard;

あなたの方法は完璧に機能します、ありがとう:)
EBAG

1

あなたのケースは平野に限定されているので、簡単な方法はホモグラフィを使用することです。

まず、画像の歪みを取り除きます。次に、findHomographyを使用して、ピクセル座標(画像)を実際の座標(ユークリッド空間(cmなど))に変換するホモグラフィマトリックスを計算します。これに似たもの:

#include <opencv2/calib3d.hpp>
//...

//points on undistorted image (in pixel). more is better
vector<Point2f>  src_points = { Point2f(123,321), Point2f(456,654), Point2f(789,987), Point2f(123,321) };
//points on chessboard (e.g. in cm)
vector<Point2f>  dst_points = { Point2f(0, 0), Point2f(12.5, 0), Point2f(0, 16.5), Point2f(12.5, 16.5) }; 
Mat H = findHomography(src_points, dst_points, RANSAC);

//print euclidean coordinate of new point on undistorted image (in pixel)
cout << H * Mat(Point3d(125, 521, 0)) << endl;

私はあなたが言ったことをしました:vector <Point2f> corners、vector <Point2f> objectPoints2d; findChessboardCorners(img、patternSize、corners); calcChessboardCorners(patternSize、squareSize、objectPoints2d); chessboardHomography = findHomography(corners、objectPoints2d、RANSAC);
EBAG、

機能せず、返される座標が正しくない
EBAG

ホモグラフィ行列にチェスボード[0,0,0]にあるピクセルを掛けても、[
192

@EBAG最初にイメージのストアを解除しますか?objectPoints2dが正しいことを確認してください。イベントを印刷し、手動で確認します。
ma.mehralian
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.