Reputation: 185
I saw that lots of people ask similar questions, but I can't exactly match any answer to my problem
I have marker and I get (x,y) of it in image coordinates. I can get transformation matrix and rotation matrix. Now how can I get (x,y,z) coordinates?
(if anyone could advise me how to solve my problem or redirect I would be grateful).
EDIT: I use Alvar library, where I get marker coordinates, and I can get also pose of it (so I have also rotation matrix 3x3, and translation matrix 3x4 or 4x4)
EDIT 2: I searched more and I study the method that allow me to acquire the rotation and translation matrices. Well I suposed that I can get two matrices depends on input arguments. But If I set as a argument 3x3 matrix I will have rotation matrix only, but if I put there 3x4 or 4x4 matrix I will get:
for 4x4
| r0 r1 r2 t1 |
| r3 r4 r5 t2 |
| r6 r7 r8 t3 |
| 0 0 0 1 |
for 3x4
| r0 r1 r2 t1 |
| r3 r4 r5 t2 |
| r6 r7 r8 t3 |
Upvotes: 2
Views: 10251
Reputation: 5364
Say you have a image point in pixel unit on the image plane: cv::Vec2d imagePoint(u, v);
First of all, you should transform this point in the camera coordinate system. Assuming that the intrinsics parameters (camera matrix and lens distortion coefficients) of your camera is known, you can compute the ideal (u', v')
coordinates of your observed imagePoint
:
u'' = (u - cx)/fx
v'' = (v - cy)/fy
(u', v') = undistort(u'', v'', distCoeffs)
Where cx
and cy
are the coordinates of principal points that is usually around the image center, furthermore fx
and fy
are the focal lengths in pixel units (you can get them from the camera matrix).
And distCoeffs
contains the radial/tangential distortion coefficients, which are also the results of cv::calibrateCamera(...)
.
Anyway, you shouldn't compute (u', v')
manually, because cv::undistortPoints(...)
does this by calling the function with no or the default R
and P
parameters.
The point of imagePoint
in the camera coordinate system is the following:
std::vector<cv::Vec2d> imagePts;
std::vector<cv::Vec2d> idealPts;
imagePts.push_back(imagePoint);
cv::undistortPoints(imagePts, idealPts, cameraMatrix, distCoeffs);
const double lambda = 1.0;
cv::Mat cameraPt(3, 1, CV_64F);
cameraPt.at<double>(0) = idealPts[0][0] * lambda;
cameraPt.at<double>(1) = idealPts[1][1] * lambda;
cameraPt.at<double>(2) = lambda;
At this point, you need the camera to world transformation matrix to express cameraPt
in the world coordinate system:
cv::Mat camToWorld = cv::Mat::eye(4, 4, CV_64FC1);
// Fill camToWorld with [R^T|-R^T*t]
// ...
cameraPt.push_back(1.0);
cv::Mat worldPt = camToWorld * cameraPt;
So far, worldPt
defines a ray in the world coordinate system corresponding to imagePoint
. That is each points of the ray/line can be projected to the same imagePoint
, so you have infinite number of points in the world which belong to the same imagePoint
. But, for example with Möller–Trumbore ray-triangle intersection algorithm you can determine one 3-D point on a plane of the world.
Upvotes: 10