edu.stanford.rsl.konrad.geometry
Class Projection

java.lang.Object
  extended by edu.stanford.rsl.konrad.geometry.Projection
All Implemented Interfaces:
java.io.Serializable

public class Projection
extends java.lang.Object
implements java.io.Serializable

This class represents a finite perspective projection (or a camera associated with it) and provides all sorts of routines for converting between different representations and obtaining geometric information. A finite projective camera can be minimally represented either by a 3x4 projection matrix P or its decomposed version of intrinsic (K) and extrinsic (R and t) parameters. OpenGL uses a 4x4 matrix which contains an additional third row with depth information. All these three representations are supported by this class.

The following text defines all variable names used in the member documentation and explains the projection representations.

It is recommended to refer to chapter 6 ("Camera Models") of [Hartley and Zisserman: Multiple View %Geometry. Cambridge Univ. Press] for further information.

Projection Matrix

A 3x4 projection matrix P transforms a world coordinate point v (given in homogeneous coordinates) into a image pixel coordinate p (also in homogeneous coordinates):
\[
Since the resulting pixel vector is normalized before usage, a scaling of P does not affect the resulting pixel. Therefore, we have 11 degrees of freedom (3x4 entries up to scale). The world coordinates v as well as the image coordinates p are assumed to represent infinitesimally small points in 3D or 2D, respectively. Therefore, if you work with voxels or pixels of finite size, always use their center coordinates. $\mathbf{P}$ is mainly composed of two parts, the left 3x3 sub matrix $\mathbf{M}$ and the right column $\mathbf{p_4}$. It can also be further decomposed into the intrinsic and extrinsic parameters as shown in the next section.
%preamble{\usepackage{amsmath}} \begin{align*}
\[

Viewing Direction

However, such a projection matrix only defines the relation of voxels to pixels and therefore the rays of the projection. We have no definition of "viewing direction" yet. A real camera has a defined direction which it "looks at" and thus only images points in front of the camera, clipping those behind it.

This is usually defined by explicitly modeling a camera coordinate system and then defining that the camera looks into positive or negative z direction (implying that the other side is invisible). Then, the 3rd coordinate w of the projected point (w*u, w*v, w) can be used to clip either points with a negative or positive depth value w.

In order to define the visible half space, we use the sign of the homogeneous coordinate of p and choose the convention that visible points result in a positive value $p_3$ for a volume point given with a positive homogeneous component. This choice is arbitrary. But since a choice has to be made anyways and to avoid complicating the internal formulas, we have chosen this convention.

If your P matrix returns a negative third coordinate for a voxel which which should be visible, then just multiply the whole matrix by -1 before using it with this class. It should then fulfill the condition $\mathbf{P}_3 \cdot \mathbf{v} > 0$ for all voxels in front of the camera. Note that this negative scaling does not affect the resulting pixel coordinate (due to the homogeneous division) but only flips the visibility coordinate.

Note that the 3x4 matrix does does not rely on a definition of a camera coordinate system but merely is a direct mapping from world coordinates to pixels. Therefore, there is also no notion of "viewing in +z or -z direction". For understanding the structure and effect of 3x4 projection matrix (using an intermediate camera coordinate system), you might want to look at the decomposition into intrinsic and extrinsic parameters described in the following section.

Intrinsic and Extrinsic Parameters K/R/t

A finite perspective projection P can also be represented using intrinsic (related to the camera's internal geometry) and extrinsic (position of the camera in the world) parameters:
\[
We will now give detailed explanations for the parameters mentioned above:

The conversion to/from a 3x4 P matrix as described above is "lossless" since any scaling factor is stored in s and the same assumptions are made concerning the viewing direction (positive third coordinate for points in front of the camera). Again, the world coordinates as well as the image coordinates are assumed to represent infinitesimally small points in 3D or 2D, respectively. Therefore, if you work with voxels or pixels of finite size, always use their center coordinates.

The representation using intrinsic and extrinsic parameters is the best-suited for further computations. Therefore, this representation is used internally for storing a projection in this class.

Note that the K/R/t representation always represents scaling effects with the K matrix of intrinsic parameters. Only rotations and translations are stored in R and t.

OpenGL Projections

This class interfaces with OpenGL's matrices via the methods fromGL() and computeGLMatrices(), respectively.

OpenGL has two so-called "matrix modes": GL_MODELVIEW and GL_PROJECTION. The modelview matrix basically covers all transformations from object coordinates to eye coordinates (the OpenGL term for camera coordinates). This includes translation, rotation, and also scaling (e.g. of standard unit cubes to another size). The projection matrix then covers the projective part. (However, OpenGL in the end just multiplies both matrices so that the user may also "abuse" the two matrices.)

The first difference to the intrinsic / extrinsic representation using K, R, and t is therefore that scaling effects are modeled twice in OpenGL (in the modelview as well as in the projection matrix) and only once using the K/R/t representation (namely in K's focal lengths). This is due to OpenGL's concept of not using a world coordinate system but standard objects of normalized size.

Moreover, OpenGL uses homogeneous 4x4 matrices throughout the full transformation pipeline. It separates depth from the z coordinate by adding an additional row to the coordinates:

%preamble{\usepackage{amsmath}} \[
In the above term, d is a depth coordinate in and is separated from the scaling coordinate -z (which is the negated z coordinate and therefore positive for visible points in OpenGL). u, v, and d are the normalized device coordinates, each in the range [-1,1]. Therefore, conversion from OpenGL to a minimal representation (P or K/R/t) is easily achieved by deleting the third row (containing the additional depth information) and only keeping the 4th row (containing the flipped scaling/z coordinate). Conversion in the other direction (K/R/t -> OpenGL) is achieved by adding the missing depth row. This row can be reconstructed from the existing z coordinate.

As a last adjustment, it has to be noted that OpenGL uses a so-called "normalized device coordinate system" which represents all pixels to be drawn in a $[-1, 1]^3$ cube (where the 3rd coordinate represents the normalized depth). The transformation from these normalized coordinates to the screen pixel coordinates is done using the viewport transform in OpenGL. This final transformation has to be appended to a given OpenGL projection matrix in order to obtain the full transformation pipeline from world coordinates to screen pixel coordinates. In contrast to the other projection representations, OpenGL also defines 6 clipping planes (top, bottom, left, right, near, and far). That's the reason why computeGLMatrices() has to know these 6 parameters for a proper conversion. (fromGL() only needs the viewport for the correct mapping from normalized device coordinates to window coordinates.)

Summarizing, the following adjustments have to be made between the K/R/t and the OpenGL representation:

Warning: Mind that OpenGL uses column-major order while the NuDeLib uses row-major matrices. This class' OpenGL connections, however, interface with OpenGL using C-style arrays in column-major order so that you can directly load/get them in OpenGL.

See also [Wright et al.: OpenGL SuperBible. Sams] and [Shreiner et al.: OpenGL Programming Guide] for more information on OpenGL.

Additional Variables

In addition to the variables defined in the preceding sections, we will also use throughout the documentation of this class.

Author:
Andreas Keil
See Also:
Serialized Form

Nested Class Summary
static class Projection.CameraAxisDirection
           
 
Constructor Summary
Projection()
          Default constructor.
Projection(double[] glProjectionGlVec, double[] glModelviewGlVec, int[] glViewport)
          Construct this projection from GL matrices.
Projection(SimpleMatrix P)
          Construct this projection from a 3x4 Matrix.
 
Method Summary
 SimpleVector computeCameraCenter()
          Compute the camera center in world coordinates.
 double computeDepth(SimpleVector v)
          Computes a given point's Eucledian distance to the camera.
 void computeGLMatrices(int imgMinU, int imgMinV, int imgSizeU, int imgSizeV, double distanceNear, double distanceFar, double[] glProjectionGlVec, double[] glModelviewGlVec)
          Compute the 4x4 OpenGL projection and modelview matrices from this Projection.
 boolean computeGLMatrices(int imgMinU, int imgMinV, int imgSizeU, int imgSizeV, SimpleVector cubmin, SimpleVector cubmax, double[] glProjectionGlVec, double[] glModelviewGlVec)
          Compute the 4x4 OpenGL projection and modelview matrices from this Projection.
 SimpleVector computeOffset(SimpleVector sizeUV)
          This convenience method computes the offset from the image center to the principal point.
 SimpleMatrix computeP()
          Computes the 3x4 projection matrix $\mathbf{P} = s \cdot \mathbf{K} \cdot \left(\begin{array}{c|c} \mathbf{R} & \mathbf{t} \end{array}\right)$ and returns it.
 SimpleVector computePrincipalAxis()
          Compute the principal axis direction in world coordinates.
 SimpleVector computeRayDirection(SimpleVector p)
          Computes the direction of the ray corresponding to a given pixel.
 double[] computeSourceToDetectorDistance(SimpleVector spacingUV)
          This convenience method computes the source-to-detector distance in world corrdinate dimensions.
 SimpleMatrix getK()
          Returns a const reference to the K matrix of intrinsic parameters.
 java.lang.String getPMatrixSerialization()
          This method is only used for XML serialization.
 SimpleVector getPrincipalPoint()
          Returns the principal point in pixels.
 SimpleMatrix getR()
          Returns a const reference to the rotation matrix R.
 SimpleMatrix getRt()
          Returns all extrinsic parameters (R and t) in a homogeneous rigid motion matrix.
 double getS()
          Returns a const reference to the scaling.
 SimpleVector getT()
          Returns a const reference to the translation vector t.
 double getViewingDirection()
          Returns the viewing direction of the camera with respect to the z axis of the camera coordinate system The viewing direction can be either in positive or negative %preamble{\usepackage{amsmath}} $z_\text{C}$ direction.
 void initFromGL(double[] glProjectionGlVec, double[] glModelviewGlVec, int[] glViewport)
          Gets all projection parameters from a given OpenGL projection matrix.
 void initFromP(SimpleMatrix P)
          Define the projection using a 3x4 projection matrix.
 void initFromSKRT(double s, SimpleMatrix K, SimpleMatrix R, SimpleVector t)
          Set the projection's intrinsic and extrinsic parameters all at once.
 void initToExampleCamera()
          Creates a exemplary perspective projection.
 boolean intersectRayWithCuboid(SimpleVector p, SimpleVector cubmin, SimpleVector cubmax, double[] distanceNearFar, SimpleVector C, SimpleVector d)
          Computes the two intersections of a ray with a cuboid, called entry and exit point where the ray is defined by this projection and the given pixel.
 double project(SimpleVector volumePoint, SimpleVector pixel)
          Projects a given voxel to a pixel and determines its visibility.
 void setKFromDistancesSpacingsSizeOffset(double sourceToDetector, SimpleVector spacingUV, SimpleVector sizeUV, SimpleVector offset, double dir, double skew)
          Constructs the K matrix from distance and offset parameters.
 void setKValue(SimpleMatrix K)
          Set the intrinsic parameters K of the projection.
 void setPMatrixSerialization(java.lang.String projectionMatrix)
          This method is only used for XML serialization.
 void setPrincipalPointValue(SimpleVector p)
          Sets the principal point in pixels.
 double setRtFromCircularTrajectory(SimpleVector rotationCenter, SimpleVector rotationAxis, double rotationRadius, SimpleVector centerToCameraAtZeroAngle, Projection.CameraAxisDirection uDirection, Projection.CameraAxisDirection vDirection, double rotationAngle)
          Constructs the extrinsic parameters (R and t) of this projection from the extrensic parameters source-to-isocenter distance, rotation axis, rotation angle, and viewing axis.
 void setRtValue(SimpleMatrix Rt)
          Set the extrinsic parameters of the projection.
 void setRValue(SimpleMatrix R)
          Set the rotation part of the extrinsic parameters of the projection.
 void setSValue(double s)
          Set the (positive) scaling of the projection.
 void setTVector(SimpleVector t)
          Set the translation part of the extrinsic parameters of the projection.
 void setViewingDirectionValue(double dir)
          Set the viewing direction of the camera with respect to the z axis of the camera coordinate system.
 java.lang.String toString()
          Returns a String representation of this projection's 3x4 matrix.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

Projection

public Projection()
Default constructor. The default constructor assumes a camera placed at the world origin viewing in +z direction with focal lengths both equal 1, principal point (0, 0) and no skew. It is the best setting to start from when setting up the camera step by step by, e.g. by concatenating transformations for computing the external setup.


Projection

public Projection(SimpleMatrix P)
Construct this projection from a 3x4 Matrix.

See Also:
initFromP(SimpleMatrix P)

Projection

public Projection(double[] glProjectionGlVec,
                  double[] glModelviewGlVec,
                  int[] glViewport)
Construct this projection from GL matrices.

See Also:
initFromGL(double[] glProjectionGlVec, double[] glModelviewGlVec, int[] glViewport)
Method Detail

initToExampleCamera

public void initToExampleCamera()
Creates a exemplary perspective projection. The exemplary projection assumes a camera placed at (0mm, 0mm, -500mm) so that it views the world origin in +z direction, projecting the world's x and y axes to the images' u and v axes, resp. The focal lengths are 1000px (which corresponds to a 1m source-to-image distance for 1mm square pixels), the principal point is (500px, 500px) and no there is no skew. This setting should enable a visibility of cuboid volumes centered at the origin. E.g., assuming 1mm pixel resolution and projection images of 1000 by 1000 pixels (1m x 1m), cubes of up to 16 2/3 cm side length are fully visible in the projection.

Warning: This exemplary camera may be subject to change in future versions. Only use it when first experimenting with this class. Set up your own camera for any application.


initFromP

public void initFromP(SimpleMatrix P)
Define the projection using a 3x4 projection matrix. Internally, the given matrix is decomposed into intrinsic and extrinsic parameters as well as a positive scalar. See the class documentation for further details on the internal representation.

Parameters:
P - A 3x4 projection matrix. See the class documentation for further details.
See Also:
"This function uses decomposition.RQ internally in order to decompose the matrix into intrinsic and extrinsic parameters and storing those internally."

initFromGL

public void initFromGL(double[] glProjectionGlVec,
                       double[] glModelviewGlVec,
                       int[] glViewport)
Gets all projection parameters from a given OpenGL projection matrix. This method defines the projection using a given OpenGL projection matrix. The given matrix may be either OpenGL's projection matrix only or the product of OpenGL's projection and modelview matrix:

Remark: Usually, the following OpenGL commands have to be used for getting OpenGL's projection: double glProjectionGlVec[16]; double glModelviewGlVec[16]; int glViewport[4]; glGetDoublev(GL_PROJECTION_MATRIX, glProjectionGlVec); glGetDoublev(GL_MODELVIEW_MATRIX, glModelviewGlVec); glGetIntegerv(GL_VIEWPORT, glViewport); Projection proj; proj.fromGL(glProjectionGlVec, glModelviewGlVec, glViewport);

Remark: Internally, the following 3x4 matrix is computed using the conversion matrix %preamble{\usepackage{amsmath}} ${}^\text{P}T_\text{GL}$ and the product $\mathbf{MVP}$ of the given 4x4 matrices:

%preamble{\usepackage{amsmath}} \[
where
%preamble{\usepackage{amsmath}} \begin{align*}
This chain of transformations first deletes the third row of the given MVP matrix, then converts the normalized device coordinates to screen coordinates, and finally feeds the result into fromP().

Warning: Mind that OpenGL uses C-style arrays in column-major order whereas the NuDeLib uses row-major matrices. However, you shouldn't bother with that since this methods takes glProjectionGlVec and glModelviewGlVec in a column-major C-style array as you get it using OpenGL's glGetDoublev() function.

Parameters:
glProjectionGlVec - A given OpenGL projection matrix. This is a C-style array of 16 values, representing a 4x4 matrix in column-major / OpenGL order.
glModelviewGlVec - A given OpenGL modelview matrix. This is a C-style array of 16 values, representing a 4x4 matrix in column-major / OpenGL order.
glViewport - A given OpenGL viewport specification in the form [imgMinU, imgMinV, imgSizeU, imgSizeV], where
  • imgMinU is the minimum image index (in px) in the u direction (usually 0),
  • imgMinV is the minimum image index (in px) in the v direction (usually 0),
  • imgSizeU is the image width (in px) in u direction (imgSizeU = imgMaxU-imgMinU+1),
  • imgSizeV is the image width (in px) in v direction (imgSizeV = imgMaxV-imgMinV+1).

initFromSKRT

public void initFromSKRT(double s,
                         SimpleMatrix K,
                         SimpleMatrix R,
                         SimpleVector t)
Set the projection's intrinsic and extrinsic parameters all at once.

Parameters:
s - A positive scaling factor. See the class documentation for further details.
K - A 3x3 intrinsic camera matrix. See the class documentation for further details.
R - A 3x3 rotation matrix, representing the extrinsic rotation of the camera. See the class documentation for further details.
t - A 3x1 translation vector, representing the translation of the camera. See the class documentation for further details.
See Also:
setSValue(double), setKValue(SimpleMatrix), setRValue(SimpleMatrix R), setTVector(SimpleVector)

setSValue

public void setSValue(double s)
Set the (positive) scaling of the projection.

Parameters:
s - A positive scaling factor. See the class documentation for further details.
See Also:
initFromSKRT(double s, SimpleMatrix K, SimpleMatrix R, SimpleVector t)

setKValue

public void setKValue(SimpleMatrix K)
Set the intrinsic parameters K of the projection.

Parameters:
K - A 3x3 intrinsic camera matrix. See the class documentation for further details.
See Also:
initFromSKRT(double s, SimpleMatrix K, SimpleMatrix R, SimpleVector t)

setRValue

public void setRValue(SimpleMatrix R)
Set the rotation part of the extrinsic parameters of the projection.

Parameters:
R - A 3x3 rotation matrix, representing the extrinsic rotation of the camera. See the class documentation for further details.
See Also:
initFromSKRT(double s, SimpleMatrix K, SimpleMatrix R, SimpleVector t)

setTVector

public void setTVector(SimpleVector t)
Set the translation part of the extrinsic parameters of the projection.

Parameters:
t - A 3x1 translation vector, representing the translation of the camera. See the class documentation for further details.
See Also:
initFromSKRT(double s, SimpleMatrix K, SimpleMatrix R, SimpleVector t)

setRtValue

public void setRtValue(SimpleMatrix Rt)
Set the extrinsic parameters of the projection.

Parameters:
Rt - A homogeneous 4x4 rigid motion matrix, representing the extrinsic rotation and translation of the camera. See the class documentation for further details.
See Also:
getRt()

setPrincipalPointValue

public void setPrincipalPointValue(SimpleVector p)
Sets the principal point in pixels. The principal point is the pixel onto which every voxel on the principal axis gets mapped by the projection. It is stored in the last column of K. This last column is a homogeneous vector with a scaling of +1 for a +z viewing direction and a scaling of -1 for -z viewing direction.

Parameters:
p - The principal point %preamble{\usepackage{amsmath}} $\begin{pmatrix} p_u \\ p_v \end{pmatrix}$ in image/pixel coordinates.

setViewingDirectionValue

public void setViewingDirectionValue(double dir)
Set the viewing direction of the camera with respect to the z axis of the camera coordinate system. The viewing direction can be either in positive or negative %preamble{\usepackage{amsmath}} $z_\text{C}$ direction.

Parameters:
dir - +1.0 for a camera looking in %preamble{\usepackage{amsmath}} $+z_\text{C}$ direction or -1.0 for a camera looking in %preamble{\usepackage{amsmath}} $-z_\text{C}$ direction.

getS

public double getS()
Returns a const reference to the scaling. Note that a projection matrix is defined up to (positive) scale. Therefore, this scaling factor is only of interest in case you want to exactly restore a given 3x4 projection matrix.

Returns:
The positive scaling factor s. See the class documentation for further details.
See Also:
setSValue(double s)

getK

public SimpleMatrix getK()
Returns a const reference to the K matrix of intrinsic parameters.

Returns:
The upper-triangular 3x3 matrix K of intrinsic parameters. See the class documentation for further details.
See Also:
setKValue(SimpleMatrix K)

getR

public SimpleMatrix getR()
Returns a const reference to the rotation matrix R.

Remark: If you want to obtain the rigid motion matrix $\left(\begin{array}{cc} \mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{array}\right) $ use createHomRigidMotionMatrix(const Matrix& R, const Vector& t). Matrix<T> Rt = createHomRigidMotionMatrix(R, t);

Returns:
The 3x3 rotation matrix R, representing the extrinsic rotation of the camera. See the class documentation for further details.
See Also:
setRValue(SimpleMatrix R), getRt()

getT

public SimpleVector getT()
Returns a const reference to the translation vector t.

Returns:
The 3x1 translation vector t, representing the extrinsic translation of the camera. See the class documentation for further details.
See Also:
setTVector(SimpleVector t), getRt()

getRt

public SimpleMatrix getRt()
Returns all extrinsic parameters (R and t) in a homogeneous rigid motion matrix.

Returns:
The homogeneous 4x4 motion matrix %preamble{\usepackage{amsmath}} $\begin{pmatrix} \mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{pmatrix} $. See the class documentation for further details.
See Also:
getR(), getT(), setRValue(SimpleMatrix R), setTVector(SimpleVector t)

getPrincipalPoint

public SimpleVector getPrincipalPoint()
Returns the principal point in pixels. The principal point is the pixel onto which every voxel on the principal axis gets mapped by the projection. It can be read out from the last column of K (after normalization).

Returns:
The principal point %preamble{\usepackage{amsmath}} $\begin{pmatrix} p_u \\ p_v \end{pmatrix}$ in image/pixel coordinates.

getViewingDirection

public double getViewingDirection()
Returns the viewing direction of the camera with respect to the z axis of the camera coordinate system The viewing direction can be either in positive or negative %preamble{\usepackage{amsmath}} $z_\text{C}$ direction.

Returns:
+1.0 for a camera looking in %preamble{\usepackage{amsmath}} $+z_\text{C}$ direction or -1.0 for a camera looking in %preamble{\usepackage{amsmath}} $-z_\text{C}$ direction.

computeP

public SimpleMatrix computeP()
Computes the 3x4 projection matrix $\mathbf{P} = s \cdot \mathbf{K} \cdot \left(\begin{array}{c|c} \mathbf{R} & \mathbf{t} \end{array}\right)$ and returns it.

Returns:
The 3x4 projection matrix P defined by this object. See the class documentation for further details.
See Also:
initFromP(SimpleMatrix P)

computeCameraCenter

public SimpleVector computeCameraCenter()
Compute the camera center in world coordinates. Formulas for the camera center C are derived from the condition %preamble{\usepackage{amsmath}} $\mathbf{P} \cdot \begin{pmatrix} \mathbf{C} \\ 1 \end{pmatrix} = 0$ (since the camera center is the only point mapped to a "pixel at infinity"):
%preamble{\usepackage{amsmath}} \begin{align*}
An alternative formula is derived as follows:
%preamble{\usepackage{amsmath}} \begin{align*}

Returns:
The camera center in world coordinates.

computePrincipalAxis

public SimpleVector computePrincipalAxis()
Compute the principal axis direction in world coordinates. Formulas for the normalized direction vector of principal axis are derived from the condition
%preamble{\usepackage{amsmath}} \[
that any point $\mathbf{C} + \lambda_1 \cdot \mathbf{a}$ on the principal axis gets mapped to the principal point $\mathbf{k_3} / k_{33}$ (with $\lambda_1,\lambda_2 > 0$ being scalar factors, $\mathbf{k_3}$ being the 3rd column of $\mathbf{K}$, and $k_{33} = \pm 1$ the lower-right entry of $\mathbf{K}$).
%preamble{\usepackage{amsmath}} \begin{align*}
\[
\[
%preamble{\usepackage{amsmath}} \[
And since the third row of $\mathbf{M}$ is $\mathbf{m_3} = s \cdot k_{33} \cdot \mathbf{r_3}$, an equivalent formula is
%preamble{\usepackage{amsmath}} \[

Returns:
The (normalized) principal axis vector in world coordinates. The direction of the principal axis is aligned with the viewing direction of the camera.

computeRayDirection

public SimpleVector computeRayDirection(SimpleVector p)
Computes the direction of the ray corresponding to a given pixel. The formula for computing a ray corresponding to a given pixel is derived as follows: Assume that %preamble{\usepackage{amsmath}} $\mathbf{X} = \begin{pmatrix} x \\ y \\ z \end{pmatrix}$ is a point on the ray belonging to pixel %preamble{\usepackage{amsmath}} $\mathbf{p} = \begin{pmatrix} u \\ v \end{pmatrix}$. Further assume that this point is in front of the camera and different from the camera center C. Then
%preamble{\usepackage{amsmath}} \begin{align*}
Therefore, solve %preamble{\usepackage{amsmath}} $\mathbf{K} \mathbf{R} \cdot (\mathbf{X}-\mathbf{C}) = \begin{pmatrix} u \\ v \\ 1 \end{pmatrix}$ for the ray direction $\mathbf{X} - \mathbf{C}$. The normalized vector is returned by this method.

Parameters:
p - A 2x1 pixel vector %preamble{\usepackage{amsmath}} $\begin{pmatrix} u \\ v \end{pmatrix}$.
Returns:
The (normalized) ray direction $\mathbf{d} = \frac{\mathbf{X} - \mathbf{C}}{\|\mathbf{X} - \mathbf{C}\|}$ in world coordinates. Its orientation is chosen so that it points from the camera center to the viewing volume.

computeGLMatrices

public void computeGLMatrices(int imgMinU,
                              int imgMinV,
                              int imgSizeU,
                              int imgSizeV,
                              double distanceNear,
                              double distanceFar,
                              double[] glProjectionGlVec,
                              double[] glModelviewGlVec)
Compute the 4x4 OpenGL projection and modelview matrices from this Projection. This method computes a 4x4 OpenGL projection matrix which can be set in OpenGL's GL_PROJECTION mode by the user as well as a 4x4 modelview matrix which can be set in OpenGL's GL_MODELVIEW mode. Once the returned matrices are set in OpenGL, their application to world coordinate vectors returns coordinates in OpenGl's clip coordinate system (CCS) and gluProject() should yield the same result as Projection::project() (up to scaling).

Remark: The parameters imgMinU, imgMinV, imgSizeU, and imgSizeV are needed in order to define a region of pixels which constitute an image. The image coordinates resulting from this Projection are then mapped to normalized device coordinates ([-1, 1] x [-1, 1]). These coordinates are later mapped back to window coordinates by the viewport transformation in OpenGL. Therefore, remember to set the OpenGL viewport using these four parameters!

Remark: Usually, the following OpenGL commands have to be used for setting up OpenGL's rendering pipeline: // instantiate projection Nude::Geometry::Projection proj; // ... // set up some projection in proj by using one or more of the from...() or set...() methods // define image viewport imgMinU, imgMinV, imgSizeU, imgSizeV and depth clipping planes n and f // ... // instantiate OpenGL matrices double glProjectionGlVec[16]; double glModelviewGlVec[16]; // convert the projection into OpenGL representation proj.computeGLMatrices(imgMinU, imgMinV, imgSizeU, imgSizeV, n, f, glProjectionGlVec, glModelviewGlVec); // set OpenGL matrices glMatrixMode(GL_PROJECTION); glLoadMatrixd(glProjectionGlVec); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(glModelviewGlVec); // map normalized device coordinates to window coordinates glViewPort(imgMinU, imgMinV, imgSizeU, imgSizeV); // additionally, the following command can be executed for reversing front/back face // definition for cameras with +z viewing direction and, therefore, enable the correct culling glFrontFace((proj.getViewingDirection() > 0) ? GL_CW : GL_CCW);

Remark: Internally, this method returns the matrix

%preamble{\usepackage{amsmath}} \[
where
%preamble{\usepackage{amsmath}} \[
is the transformation from image pixel coordinates [imgMinU, imgMinU+imgSizeU] x [imgMinV, imgMinV+imgSizeV] to normalized device coordinates [-1, 1] x [-1, 1], the middle matrix flips the z axis (as OpenGL also would do internally, resulting in a left-handed coordinate system at this point), and the left matrix inserts the third row with depth information created from the z value. The depth row created here yields a depth coordinate which, after perspective division, maps the distance range from the camera [-n, -f] (in world coordinates) to [-1, 1], so that the clipping volume includes only objects at a distance of n to f from the camera.

Warning: Mind that OpenGL uses C-style arrays in column-major order whereas the NuDeLib uses row-major matrices. However, you shouldn't bother with that since this methods returns glProjectionGlVec and glModelviewGlVec in a column-major C-style array as you set it using OpenGL's glLoadMatrixd() function.

Parameters:
imgMinU - The minimum image index (in px) in the u direction (usually 0).
imgMinV - The minimum image index (in px) in the v direction (usually 0).
imgSizeU - The image width (in px) in u direction (imgSizeU = imgMaxU-imgMinU+1).
imgSizeV - The image width (in px) in v direction (imgSizeV = imgMaxV-imgMinV+1).
distanceNear - The near plane clipping coordinate (in mm). The clipping distances are measured from the camera center to the clipping plane in mm.
distanceFar - The far plane clipping coordinate (in mm). The clipping distances are measured from the camera center to the clipping plane in mm.
glProjectionGlVec - Return value. This has to be an already allocated(!) C-style array of 16 values, representing a 4x4 OpengGL projection matrix in column-major / OpenGL order. It can be directly set in OpenGL in the GL_PROJECTION mode.
glModelviewGlVec - Return value. This has to be an already allocated(!) C-style array of 16 values, representing a 4x4 OpengGL modelview matrix in column-major / OpenGL order. It can be directly set in OpenGL in the GL_MODELVIEW mode.
See Also:
computeGLMatrices(int imgMinU, int imgMinV, int imgSizeU, int imgSizeV, SimpleVector cubmin, SimpleVector cubmax, double[] glProjectionGlVec, double[] glModelviewGlVec)

computeGLMatrices

public boolean computeGLMatrices(int imgMinU,
                                 int imgMinV,
                                 int imgSizeU,
                                 int imgSizeV,
                                 SimpleVector cubmin,
                                 SimpleVector cubmax,
                                 double[] glProjectionGlVec,
                                 double[] glModelviewGlVec)
Compute the 4x4 OpenGL projection and modelview matrices from this Projection. This method is very similar to computeGLMatrices(const int imgMinU, const int imgMinV, const unsigned int imgSizeU, const unsigned int imgSizeV, const double n, const double f, double glProjectionGlVec[16], double glModelviewGlVec[16]). The only difference is that it takes bounding box dimensions and computes appropriate near and far clipping planes internally. Additionally, the return value tells you whether or not the bounding box is visible using the specified projection. In case it is not visible, the given GL matrix storage variables are left unchanged.

Remark: The parameters imgMinU, imgMinV, imgSizeU, and imgSizeV are needed in order to define a region of pixels which constitute an image. The image coordinates resulting from this Projection are then mapped to normalized device coordinates ([-1, 1] x [-1, 1]). These coordinates are later mapped back to window coordinates by the viewport transformation in OpenGL. Therefore, remember to set the OpenGL viewport using these four parameters!

Remark: Usually, the following OpenGL commands have to be used for setting up OpenGL's rendering pipeline: // instantiate projection Nude::Geometry::Projection proj; // ... // set up some projection in proj by using one or more of the from...() or set...() methods // define image viewport imgMinU, imgMinV, imgSizeU, imgSizeV and bounding box extents cubmin and cubmax. // ... // instantiate OpenGL matrices double glProjectionGlVec[16]; double glModelviewGlVec[16]; // convert the projection into OpenGL representation proj.computeGLMatrices(imgMinU, imgMinV, imgSizeU, imgSizeV, cubmin, cubmax, glProjectionGlVec, glModelviewGlVec); // set OpenGL matrices glMatrixMode(GL_PROJECTION); glLoadMatrixd(glProjectionGlVec); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(glModelviewGlVec); // map normalized device coordinates to window coordinates glViewPort(imgMinU, imgMinV, imgSizeU, imgSizeV); // additionally, the following command can be executed for reversing front/back face // definition for cameras with +z viewing direction and, therefore, enable the correct culling glFrontFace((proj.getViewingDirection() > 0) ? GL_CW : GL_CCW);

Warning: Mind that OpenGL uses C-style arrays in column-major order whereas the NuDeLib uses row-major matrices. However, you shouldn't bother with that since this methods returns glProjectionGlVec and glModelviewGlVec in a column-major C-style array as you set it using OpenGL's glLoadMatrixd() function.

Warning: Using this convenience method which automatically computes suitable near and far clipping planes implies that you do not further change the returned matrices, esp. the modelview matrix. Applying additional transformations in OpenGL would result in a displaced cube and therefore wrong depth clipping planes. Therefore, either apply all motions/transformations to this projection and call this method after each change or manually specify your own depth clipping planes using computeGLMatrices(final int imgMinU, final int imgMinV, final int imgSizeU, final int imgSizeV, final double n, final double f, final double[] glProjectionGlVec, final double[] glModelviewGlVec).

Parameters:
imgMinU - The minimum image index (in px) in the u direction (usually 0).
imgMinV - The minimum image index (in px) in the v direction (usually 0).
imgSizeU - The image width (in px) in u direction (imgSizeU = imgMaxU-imgMinU+1).
imgSizeV - The image width (in px) in v direction (imgSizeV = imgMaxV-imgMinV+1).
cubmin - The bounding box' minimum extents (in mm).
cubmax - The bounding box' maximum extents (in mm).
glProjectionGlVec - Return value. This is an already allocated(!) C-style array of 16 values, representing a 4x4 OpengGL projection matrix in column-major / OpenGL order. It can be directly set in OpenGL in the GL_PROJECTION mode.
glModelviewGlVec - Return value. This is an already allocated(!) C-style array of 16 values, representing a 4x4 OpengGL modelview matrix in column-major / OpenGL order. It can be directly set in OpenGL in the GL_MODELVIEW mode.
Returns:
Returns true if the bounding box is (at least partly) visible and false otherwise.
See Also:
computeGLMatrices(int imgMinU, int imgMinV, int imgSizeU, int imgSizeV, double n, double f, double[] glProjectionGlVec, double[] glModelviewGlVec), computeOptimalClippingDepthsForCuboid(edu.stanford.rsl.konrad.numerics.SimpleVector, edu.stanford.rsl.konrad.numerics.SimpleVector, double[])

computeDepth

public double computeDepth(SimpleVector v)
Computes a given point's Eucledian distance to the camera. A signed distance between camera center and 3D point is returned. If this distance is positive, then the point is in front of the camera and therefore visible.

Parameters:
v - A 3x1 vector of the given 3D point.
Returns:
The point's depth w.r.t. the camera which is computed by transforming it into camera coordinates, computing the norm $\pm \left\| \mathbf{R} \cdot \mathbf{v} + \mathbf{t} \right\|_2 $, and chosing the sign according to the transformed point's z coordinate (taking into account the camera's viewing direction).
See Also:
project(edu.stanford.rsl.konrad.numerics.SimpleVector, edu.stanford.rsl.konrad.numerics.SimpleVector)

project

public double project(SimpleVector volumePoint,
                      SimpleVector pixel)
Projects a given voxel to a pixel and determines its visibility.

Parameters:
volumePoint - The 3x1 volume point in world coordinates.
pixel - The returned 2x1 image coordiante in pixels.
Returns:
The method also returns the depth of the projected point. This depth is positive if the volume point is visible and false otherwise.
See Also:
computeDepth(edu.stanford.rsl.konrad.numerics.SimpleVector)

intersectRayWithCuboid

public boolean intersectRayWithCuboid(SimpleVector p,
                                      SimpleVector cubmin,
                                      SimpleVector cubmax,
                                      double[] distanceNearFar,
                                      SimpleVector C,
                                      SimpleVector d)
Computes the two intersections of a ray with a cuboid, called entry and exit point where the ray is defined by this projection and the given pixel. Internally, this method first computes the camera center and ray direction and then calls intersectRayWithCuboid(final SimpleVector origin, final SimpleVector dir, final SimpleVector cubmin, final SimpleVector cubmax, final double[] tntf). The entry and exit points are returned as distances from the camera center along the projection ray. The world coordinates of the entry and exit voxels may be computed as follows:
%preamble{\usepackage{amsmath}} \begin{align*}

Parameters:
p - A 2x1 pixel vector.
cubmin - The cuboid's minimal planes given as [min_x, min_y, min_z] in world coordinates.
cubmax - The cuboid's box' maximal planes given as [max_x, max_y, max_z] in world coordinates.
distanceNearFar - Return values. In case of a hit: Positive distance (in world coordinate units) of nearest [0] and farthest [1] plane intersections.
C - Return value. The ray origin / camera center (corresponding to the internal projection matrix) in world coordinates [ro_x, ro_y, ro_z].
d - Return value. The normalized(!) ray direction (corresponding to the given pixel) in world coordinates [rd_x, rd_y, rd_z].
Returns:
Boolean value which is true if the ray intersects with the bounding box and false otherwise.

setKFromDistancesSpacingsSizeOffset

public void setKFromDistancesSpacingsSizeOffset(double sourceToDetector,
                                                SimpleVector spacingUV,
                                                SimpleVector sizeUV,
                                                SimpleVector offset,
                                                double dir,
                                                double skew)
Constructs the K matrix from distance and offset parameters. This method sets this Projection's K matrix according to the given distance, pixel size, offset, and other parameters. Note that the distance and pixel size parameters include redundant information not needed for establishing a world-pixel projection relationship. They cannot be recovered from this Projection again. The only (non-redundant) information that can be recovered is the source-to-detector distances in pixels. Also note that the camera coordinate system is supposed to be set up using the R and t transform parameters in a way that the x and y axes are colinear with the projection's u and v axes, resp. Furthermore, the z axis must point into the direction of the principal axis (for dir == +1.0) or into the oppose direction (for dir == -1.0).

Warning: The parameters given to this method are mostly discarded since they are not essential or minimal for representing a single projection. This is why they also cannot be recovered from this object. This method is rather a convenience method for setting up this projection.

Parameters:
sourceToDetector - The distance from projection / camera / X-ray source center to the image plane / detector in world coordinates.
spacingUV - The pixel size in u- and v-direction.
sizeUV - The projection image size in u- and v-direction.
offset - The offset (in pixels) from the image center to the principal point (where the principal ray hits the image plane orthogonally), i.e., the principal point is computed as (image center + offset).
dir - +1.0 for a camera looking in %preamble{\usepackage{amsmath}} $+z_\text{C}$ direction direction or -1.0 for a camera looking in %preamble{\usepackage{amsmath}} $-z_\text{C}$ direction.
skew - The skew parameter (usually zero).
See Also:
setRtFromCircularTrajectory(edu.stanford.rsl.konrad.numerics.SimpleVector, edu.stanford.rsl.konrad.numerics.SimpleVector, double, edu.stanford.rsl.konrad.numerics.SimpleVector, edu.stanford.rsl.konrad.geometry.Projection.CameraAxisDirection, edu.stanford.rsl.konrad.geometry.Projection.CameraAxisDirection, double)

setRtFromCircularTrajectory

public double setRtFromCircularTrajectory(SimpleVector rotationCenter,
                                          SimpleVector rotationAxis,
                                          double rotationRadius,
                                          SimpleVector centerToCameraAtZeroAngle,
                                          Projection.CameraAxisDirection uDirection,
                                          Projection.CameraAxisDirection vDirection,
                                          double rotationAngle)
Constructs the extrinsic parameters (R and t) of this projection from the extrensic parameters source-to-isocenter distance, rotation axis, rotation angle, and viewing axis. It is assumed that this projection is part of a series of projections acquired along a circular trajectory with a known rotation center, axis, radius (i.e. the source-to-isocenter distance), and rotation angle. These parameters together with the direction to the zero angle position fully describe the camera's current position. The principal axis of the camera is assumed to always cross the rotation center so that the image plane is not tilted, swiveled, or rotated with respect to the trajectory plane. For more general cases where the camera's rotational position is not defined that simple, the user has to modify the resulting [R|t] transform himself by multiplying it from the left with additional rotations in the camera coordinate system. The principal axis (in world coordinates) of the projection with a zero angular argument. If the principal axis hits the center of rotation (i.e., thr detector is neither tilted nor swiveled), the principal axis is just the negated center-to-camera vector.

Warning: The parameters given to this method are mostly discarded since they are not essential or minimal for representing a single projection. This is why they also cannot be recovered from this object. This method is rather a convenience method for setting up this projection.

Parameters:
rotationCenter - The center of rotation, given as 3D point in world coordinates. (This is usually chosen to be (0,0,0).)
rotationAxis - The rotation axis (in world coordinates) for a circular acquisition trajectory (where the last projection's angular value is bigger than the first one's.) (This is usually chosen to be (0,0,1).)
rotationRadius - The radius of the camera rotation, i.e. the distance from the camera / X-ray source to the iso center.
centerToCameraAtZeroAngle - The direction from the center of rotation to the camera position at zero angle. This direction vector can have any length but zero. Its normalized version is used together with the rotationRadius for translating the camera to its zero angle position. Since the zero angle position has to be on the circular trajectory defined by the rotationAxis (and the rotationRadius), centerToCameraAtZeroAngle has to be perpendicular to rotationAxis. (This is usually chosen to be (1,0,0).)
uDirection - Sets the camera's u axis in terms of the direction of motion of the detector (for increasing angles) and the rotation axis.
vDirection - Sets the camera's v axis in terms of the direction of motion of the detector (for increasing angles) and the rotation axis.
rotationAngle - The angle of rotation (away from the zero position) for this projection.
Returns:
After setting up the extrinsic parameters R and t using this method, the x and y axes of the camera coordinate system are aligned with the u and v axis of the projections, resp. The camera coordinate system's z axis may then either point into the camera's viewing direction (return value 1.0) or into the opposite direction (return value -1.0). This method already sets the viewing direction in this Projection accordingly, but it has to be taken into account when re-setting up the internal parameters using another method.
See Also:
TODO: Move this method to ProjectionSeries, taking an array of angles and generating the series of Projections.

computeSourceToDetectorDistance

public double[] computeSourceToDetectorDistance(SimpleVector spacingUV)
This convenience method computes the source-to-detector distance in world corrdinate dimensions. The Projection class only stores the minimal information needed for establishing world to pixel correspondences. It therefore only know the focal length in pixels (stored as the first two diagonal entries of the K matrix). Computing the source-to-detector distance requires knowledge about the pixel size. Since there are focal length entries in K that could be used for computing the source-to-detector distance, this method returns two result values. They should, theoretically, be equal. This check is left to the caller of this method.

Parameters:
spacingUV - Given pixel sizes in u- and v-direction.
Returns:
An array of two computed source-to-detector distances that should be equal.

computeOffset

public SimpleVector computeOffset(SimpleVector sizeUV)
This convenience method computes the offset from the image center to the principal point.

Parameters:
sizeUV - Projection image size in u- and v-direction in pixels.
Returns:
A 2-vector with the computed offset from the image center to the principal point in pixels (so that principal point = center + offset).

toString

public java.lang.String toString()
Returns a String representation of this projection's 3x4 matrix.

Overrides:
toString in class java.lang.Object
Returns:
The 3x4 matrix in the numeric package's standard String format.

setPMatrixSerialization

public void setPMatrixSerialization(java.lang.String projectionMatrix)
This method is only used for XML serialization.

Parameters:
projectionMatrix - String representation of the projection matrix to de-serialize.

getPMatrixSerialization

public java.lang.String getPMatrixSerialization()
This method is only used for XML serialization.

Returns:
A String representation of the projection matrix to serialize.