Transform pixel coordinates from camera 2 to camera 3 in Kitty dataset - coordinate-systems

Basically, I want to transform a point from the image of camera 2 (x_pixel_c2, y_pixel_c2) to a pixel point (x_pixel_c2, y_pixel_c3) in camera 3.
For a simple setup (no distortion parameters, no rectification), I would usually:
assign a certain distance to the point in C2
compute the coordinates in 3D space of C2 from the intrinsics
compute the World coordinates from the extrinsic matrix of C2
compute the 3D coordinates in C3 from its extrinsic matrix
project in pixel space of C2
For the Kitty dataset, I do not use this approach because of the distortion parameters (especially). In Kitty, we have the projection matrices for the 4 rectified cameras, which from what I understand, are the transformation matrices relating the 3D coordinates in Camera 0 to Camera X. However, from the tests I've made, this does not work:
pt_3d_cam0 = np.dot(inverse(P_rect_02), pt_cam_2)
pt_cam_3 = np.dot(P_rect_03, pt_3d_cam0)
I'm not sure the projection matrices move the referential back to camera 0 as it is mentioned. For instance, the points are closer to the expected coordinates if I add a translation in X equal to the amount of the baseline.
I'm not sure if I'm missing something. If anyone has encountered a similar problem with Kitty, it would be appreciated if you could help.
Thank you!

Related

Convert earth-centric coordinate frame to coordinate frame aligned to tangential plane?

Given that earth is perfectly spherical with radius R.
The earth-centric coordinate system E is defined as follows:
The center of this sphere is the origin,
Earth's north pole represents the z-axis.
Latitude 0 and longitude 0 represent x-axis.
Latitude 0 and longitude 90 represent y- axis.
Now at any given latitude, longitude, and altitude, we can make a local coordinate system S whose y-z plane is tangential to earth's surface and z points to the north pole and x points perpendicular to this plane.
I need a 4x4 transformation matrix to transform a 3d point from earth-centric coordinate system E to this local coordinate system S.
Transformation matrix from S to E might be composed as product of matrices:
Shift along X axis by R+Altitude
Rotation about Y-axis by Latitude
Rotation about Z-axis by Longitude
Make inverse of this matrix to get E-S transform
Assuming that earth is spherical, this is actually not that hard.
Spherical coordinates to the rescue (see here)! A sphere can be parametrized by 2 angles (as already mentions in the problem statement). Based on this, you can formulate equations to convert to cartesian coordinates. If you compute the derivative of those equations with respect to both angles, you get equations stating the tangent and bitangent of any point on the sphere. Based on this you can either use the vector pointing from the center to a point on the sphere as the normal or the cross product between tangent and bitangent. Formulations for tangent and bitangents are also given in the link above.
Now you got an orthogonal system for each point on the sphere based on your 3 vectors: tangent, bitangent and normal. The only part that is missing is the translation which is simply the vector pointing from the center to a point on the sphere. Given all the necessary ingredients, you can create a 4x4 matrix from those axes using standard libraries like glm or simply place those vectors as columns of your matrix (don't forget to normalize tangent, bitangent and normal!). Depending if you use row-major or column-major matrices you may need to transpose this matrix.

Rotate Image Orientation(Patient) in DICOM

I have extracted a 3D surface from an MRI acquisition and the coordinates of the points describing this surface are (I believe) with respect to the reference system of the first image of the series (I mean that the origin corresponds to the Image Position(Patient) and the axes orientation to the Image Orientation(Patient)).
I have another set of images with a different Image Position(Patient) and a different Image Orientation(Patient); I want to rotate and translate the surface extracted from the first set in order to have it match exactly the second set of images.
I'm having trouble with finding the correct 4x4 matrix that would do the job, once I get it, I know how to apply it to my surface.
Any kind of help would be greatly appreciated, thank you.
Simon
This page explains how to form a transformation matrix from the geometry information in the DICOM headers. These transformation matrices are used to transform from the volume coordinate system (pixel-x, pixel-y, slice number) to the patient/world coordinate system (in millimeters).
The basic idea to transform from volume 1 to volume 2 is to tranform from volume 1 to patient coordinates and from patient coordinates to volume 2 coordinate system. Multiplying both matrices yields the matrix to transform directly from volume 1 to volume 2.
Caution: Obviously, there can be no guarantee that every coordinate in v1 matches a coordinate in v2, i.e. the stacks may have different size and/or position.
So you have:
M1 - the matrix to transform from volume 1 to the world coordinate system and
M2 - the matrix to transform from volume 2 to the world coordinate system
Then
M1 * (M2^(-1)) is the matrix to transform a position vector from volume 1 to volume 2 (input and output is pixel-x, pixel-y, slice number)
and
M2 * (M1^(-1)) is the matrix to transform a position vector from volume 1 to volume 2 (input and output is pixel-x, pixel-y, slice number)

compute angle of rotation between two orthographic projections

I Have the orthographic projection of a unit cube with one of its vertex at origin as shown above. I have the x,y (no z) co ordinates of the projections. I would like to compute the angle of rotation of the plane to get the second orthographic projection from the first one (maybe euler angles??)
Is there any other easy way to compute this?
UPDATE:
Could I use this rotation matrix to get a system of equations in cos, sin angles and the x,y and x',y' and solve them easily? Or is there any easier way to get the angles back? (Am I on the right direction to solve this? )
First method
Use this idea to generate equations:
a1, a2 and a3 are coordinates in the original system, x y are the coordinates you get from the end-result and z is a coordinate you don’t know. This generates 2 equations for every point of the cube. E.g for point 0 with coordinates (-1, -1, 1) these are:
Do this for the 4 front points of the cube and you get 8 equations. Now add the fact that this is a rotation matrix -> the determinant is 1 and you have 9 equations. Solve these with any of the usual algorithms for solving equation systems and you have the transformation matrix. Getting the axis and angle from that is easy via google: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/
Second method
Naming your points 0, 1, 2, 3 a, b, c, d respectively, you can get the z coordinates of the vectors between them (e.g. b-a) with this idea:
you will still have to sort out if b3-a3 is positive, though. One way to do that is to use the centermost point as b (calculate distance from the center for all points, use the one with the minimal distance). Then you know for sure that b3-a3 is positive (if z is positive towards you).
Now assume that a is (0,0,0) in your transformed space and you can calculate all the point positions by adding the appropriate vectors to that.
To get the rotation you use the fact that you know where b-a did point in your origin space (e.g. (1,0,0)). You get the rotation angle via dot product of b-a and (1,0,0) and the rotation axis via cross product between those vectors.

Calculating 3d plane for two 3d vectors

If I have two vector coordinates representing positions on the surface of the earth where the center of the earth is (0,0,0) and the Up vector is (0,0,1);
What is the best way to calculate a 3d plane that is running along the two vectors (the direction v2 - v1) but back by a set number of meters (just imagine a virtual clip plane that is behind the two vectors and running parallel to them).
well, you do the cross product of v1 and v2 to get the normal of your plane (don't forget to normalize if you want to), then the 4th element of your plane would just be 0 (because it crosses 0,0,0).
and then you want to project the plane in a certain direction based on the UP vector, not the plane's normal?
in that case I think you would just get the dot product of the normal and the up vector, then multiply the inverse of the dot (1/dot) by the number of units you want to project along the up vector and set that as your 4th element?
to clarify, that creates a plane where the two vectors, and the center of the earth are points on the plane, the plane can then be projected up or down by a certain amount in the UP direction.
Planes are usually described by a normal vector N, and as all points x,y,z fitting the equation Ax + By + Cz + D = 0. (A,B,C) is the normal vector. It doesn't even need to be normalized (unit length) if you choose D. Sounds like you want a plane to which v1 and v2 are parallel (and v2-v1 too). For that, make N perpendicular to v1 and v2 by setting it to the cross product of v2 x v1. Then pick a point in (x,y,z) coordinates that you know the plane should pass through. Plug N and (x,y,z) into the equation and compute D.
1- Find the Normal vector N = V1 X V2
2-Select a point that you want your plane tuch P0 ==>R0
3- All the other points(P==>R) in the plane follow N(R-R0)=0
See the link

width of a frustum at a given distance from the near plane

I'm using CML to manage the 3D math in an OpenGL-based interface project I'm making for work. I need to know the width of the viewing frustum at a given distance from the eye point, which is kept as a part of a 4x4 matrix that represents the camera. My goal is to position gui objects along the apparent edge of the viewport, but at some distance into the screen from the near clipping plane.
CML has a function to extract the planes of the frustum, giving them back in Ax + By + Cz + D = 0 form. This frustum is perpendicular to the camera, which isn't necessarily aligned with the z axis of the perspective projection.
I'd like to extract x and z coordinates so as to pin graphical elements to the sides of the screen at different distances from the camera. What is the best way to go about doing it?
Thanks!
This seems to be a duplicate of Finding side length of a cross-section of a pyramid frustum/truncated pyramid, if you already have a cross-section of known width a known distance from the apex. If you don't have that and you want to derive the answer yourself you can follow these steps.
Take two adjacent planes and find
their line of intersection L1. You
can use the steps here. Really
what you need is the direction
vector of the line.
Take two more planes, one the same
as in the previous step, and find
their line of intersection L2.
Note that all planes of the form Ax + By + Cz + D = 0 go through the origin, so you know that L1 and L2
intersect.
Draw yourself a picture of the
direction vectors for L1 and L2,
tails at the origin. These form an
angle; call it theta. Find theta
using the formula for the angle
between two vectors, e.g. here.
Draw a bisector of that angle. Draw
a perpendicular to the bisector at
the distance d you want from the
origin (this creates an isosceles
triangle, bisected into two
congruent right triangles). The
length of the perpendicular is your
desired frustum width w. Note that w is
twice the length of one of the bases
of the right triangles.
Let r be the length of the
hypotenuses of the right triangles.
Then rcos(theta/2)=d and
rsin(theta/2)=w/2, so
tan(theta/2)=(w/2)/d which implies
w=2d*tan(theta/2). Since you know d
and theta, you are done.
Note that we have found the length of one side of a cross-section of a frustrum. This will work with any perpendicular cross-section of any frustum. This can be extended to adapt it to a non-perpendicular cross-section.

Resources