2
$\begingroup$

I am trying to figure out why a 3D cube doesn't project in the right place in the image.

I start with the camera at origin and the cube centered at (0,0,1) world coordinates:

front

Then I create a 3D rotation R of 45 degrees around the Y axis:

(0.707106781, 0, 0.707106781,
0, 1, 0,
-0.707106781, 0, 0.707106781)

And I set the camera to use rotation R^-1, with a translation of R * (0,0,1) (these are camera to world transformations). The camera should have rotated 45 degrees CCW around the cube (I can confirm I have 0.707106781 translation on x and z).

At this point, I would expect to see the cube with the same scale, still centered, and with one of the edges right in the middle of the image. But this is what I get:

side-45

The procedure I use to project a 3d point X is (pseudo code):

  • bring into camera coordinates: Xc = R^-1 * X - R^1 * translation
  • transform into image coordinates: x = Xc * focal length / Xc.z + principal point

I have read the theory from various sources and it seems I am following the rules.

This is just artificial data, so not sure if focal length and principal point can have any effect on it? What am I doing wrong? Why is the cube not centered?

EDIT:

I construct the cube like this (duplicate vertices are there because I need them to draw lines):

  cv::Matx31d center(0,0,1);
  double delta = 0.2;

  std::vector<cv::Matx31d> volumeCorners = {
    // back
    (center + cv::Matx31d(-delta, delta, delta)),
    (center + cv::Matx31d(delta, delta, delta)),

    (center + cv::Matx31d(delta, delta, delta)),
    (center + cv::Matx31d(delta, -delta, delta)),

    (center + cv::Matx31d(delta, -delta, delta)),
    (center + cv::Matx31d(-delta, -delta, delta)),

    (center + cv::Matx31d(-delta, -delta, delta)),
    (center + cv::Matx31d(-delta, delta, delta)),

    // right
    (center + cv::Matx31d(delta, delta, delta)),
    (center + cv::Matx31d(delta, delta, -delta)),

    (center + cv::Matx31d(delta, delta, -delta)),
    (center + cv::Matx31d(delta, -delta, -delta)),

    (center + cv::Matx31d(delta, -delta, -delta)),
    (center + cv::Matx31d(delta, -delta, delta)),

    // front
    (center + cv::Matx31d(delta, delta, -delta)),
    (center + cv::Matx31d(-delta, delta, -delta)),

    (center + cv::Matx31d(-delta, -delta, -delta)),
    (center + cv::Matx31d(delta, -delta, -delta)),

    (center + cv::Matx31d(-delta, -delta, -delta)),
    (center + cv::Matx31d(-delta, delta, -delta)),

    // left
    (center + cv::Matx31d(-delta, delta, -delta)),
    (center + cv::Matx31d(-delta, delta, delta)),

    (center + cv::Matx31d(-delta, -delta, delta)),
    (center + cv::Matx31d(-delta, -delta, -delta)),
  };

I use a right-handed coordinate system, with the y axis pointing down, for world and camera coordinates, while image has origin at top left.

$\endgroup$
1
$\begingroup$

My translation should have described a rotation around the center of the cube, but it was wrong. I changed it to:

rotate45 * (translation - center) + center

and I get the cube in the middle with the right angle.

$\endgroup$
  • $\begingroup$ Thanks for supplying the answer! Once the timeout is over, please select this as the correct answer. $\endgroup$ – Peter K. Oct 5 '15 at 23:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.