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)),
  };
$\endgroup$
1
$\begingroup$

It looks to me like your axis of rotation is the vertical red line on the left in the first diagram rather than the vertical line through the center of mass of the cube (not depicted).

I think you need to check everything again to confirm that the corners of the cube are really where you think they are.

I can add a little more help if you help me with your coordinate system a bit. (Can you label the axes and/or tell me the coordinate of the corners? Different people use different conventions...)


If the center of the cube is $(0,0,1)$, it looks to me like the $x-y$ origin is in the center of the picture.

Conceptually, this would be the order things would happen in:

  1. translate the cube forward so that its center is along the $y$-axis. You can do this by subtracting $(0,0,1)$ from all of the coordinates.

  2. Now apply the rotation matrix to turn the cube (I haven't actually checked the direction it goes, but I trust your computation on that. It looks correct.)

  3. Translate the cube back from whence it came by adding $(0,0,1)$ to all the coordinates.

If I can answer questions of translating this into your implementation, ask away.


If you believe that the $x-y$ origin is in the upper left hand corner (as standard graphics conventions do) then your cube obviously can't be centered at $(0,0,1)$. The point $(0,0,1)$ would have to be underneath the left hand border of the image. I think if you tried to rotate around the line through $(0,0,1)$ parallel to the $y$-axis, you would be swinging your cube around the left hand border of the picture. That would be consistent with the picture you're producing. So perhaps you are applying the correct transformation, but you have been misinformed about the location of the cube's center.

$\endgroup$
  • $\begingroup$ I use a right-handed coordinate system, with the y axis pointing down. $\endgroup$ – aledalgrande Oct 5 '15 at 18:37
  • $\begingroup$ @aledalgrande Er, that's not quite detailed enough, but let me guess the rest: x is across the top, and positive z is into the picture? $\endgroup$ – rschwieb Oct 5 '15 at 18:38
  • 1
    $\begingroup$ Yeah, sorry: x to the right, y down and z into the picture. $\endgroup$ – aledalgrande Oct 5 '15 at 18:39
  • $\begingroup$ Also image coordinates: origin at top left corner, x to the right, y down. $\endgroup$ – aledalgrande Oct 5 '15 at 18:43
  • $\begingroup$ @aledalgrande Actually, I'm a little confused. To me, it looks like your x-y origin is in the center of the picture, with the z-axis receding from view. If your x-y origin is in the upper left, I don't know how the center could be at $(0,0,1)$. $\endgroup$ – rschwieb Oct 5 '15 at 18:45
0
$\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$

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.