# Why is this projection wrong?

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: 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: 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.

rotate45 * (translation - center) + center