Line data Source code
1 : #pragma once 2 : 3 : #include "elsaDefines.h" 4 : #include "DataDescriptor.h" 5 : #include "StrongTypes.h" 6 : 7 : #include <utility> 8 : #include <cassert> 9 : 10 : namespace elsa 11 : { 12 : /** 13 : * @brief Class representing 2d/3d projective camera geometry for use in CT projectors. 14 : * 15 : * @author Matthias Wieczorek - initial code 16 : * @author Maximilian Hornung - modularization, redesign 17 : * @author David Frank - bugfixes, strong typing 18 : * @author Nikola Dinev - refactoring 19 : * @author Tobias Lasser - refactoring, modernization 20 : * 21 : * The location of X-ray source, volume (typically containing the center of rotation), and X-ray 22 : * detector are encoded using projection matrices (see A. Zissermann, "Multiple View Geometry in 23 : * Computer Vision"). Detectors are assumed to be flat. 24 : */ 25 : class Geometry 26 : { 27 : public: 28 : /** 29 : * @brief Constructor for 2D projective geometry 30 : * 31 : * @param[in] sourceToCenterOfRotation distance from source to the center of rotation (along 32 : * y axis) 33 : * @param[in] centerOfRotationToDetector distance from center of rotation to detector (along 34 : * y axis) 35 : * @param[in] angle rotation angle (in radians) 36 : * @param[in] volData descriptor for the 2d volume 37 : * @param[in] sinoData descriptor for the sinogram 38 : * @param[in] offset offset of the principal point [default 0] 39 : * @param[in] centerOfRotOffset offset of the center of rotation 40 : * 41 : * 42 : * VolumeData2D and SinogramData2D are taken as r-value references, as it's cheaper to move, 43 : * them in, and they are only intended as temporary objects. o construct a Geometry with 44 : * VolumeData2D{...}/SinogramData2D{...} as temporary or move the object in, but be aware of 45 : * reusing it 46 : */ 47 : Geometry(geometry::SourceToCenterOfRotation sourceToCenterOfRotation, 48 : geometry::CenterOfRotationToDetector centerOfRotationToDetector, 49 : geometry::Radian angle, geometry::VolumeData2D&& volData, 50 : geometry::SinogramData2D&& sinoData, 51 : geometry::PrincipalPointOffset offset = geometry::PrincipalPointOffset{0}, 52 0 : geometry::RotationOffset2D centerOfRotOffset = geometry::RotationOffset2D{0, 0}); 53 : 54 : /** 55 : * @brief Constructor for 3D projective geometry using Euler angles 56 : * 57 : * @param[in] sourceToCenterOfRotation distance from source to the center of rotation (along 58 : * z axis) 59 : * @param[in] centerOfRotationToDetector distance from center of rotation to detector (along 60 : * z axis) 61 : * @param[in] volData descriptor for the 3d volume 62 : * @param[in] sinoData descriptor for the sinogram 63 : * @param[in] angles (gamma -> around y''-axis, beta -> around z' axis, alpha -> around y 64 : * axis) in radians 65 : * @param[in] offset offset of the principal point 66 : * @param[in] centerOfRotOffset offset of the center of rotation 67 : * 68 : * Alpha, beta, gamma are Euler rotation angles using the YZY convention. They are specified 69 : * in radians. In standard circular trajectory CT settings, we would have alpha = beta = 0, 70 : * while gamma is the angle of rotation) 71 : * 72 : * VolumeData3D and SinogramData3D are taken as r-value references, as it's cheaper to move, 73 : * them in, and they are only intended as temporary objects. So construct a Geometry with 74 : * VolumeData3D{...}/SinogramData3D{...} as temporary or move the object in, but be aware of 75 : * reusing it 76 : */ 77 : Geometry(geometry::SourceToCenterOfRotation sourceToCenterOfRotation, 78 : geometry::CenterOfRotationToDetector centerOfRotationToDetector, 79 : geometry::VolumeData3D&& volData, geometry::SinogramData3D&& sinoData, 80 : geometry::RotationAngles3D angles, 81 0 : geometry::PrincipalPointOffset2D offset = geometry::PrincipalPointOffset2D{0, 0}, 82 0 : geometry::RotationOffset3D centerOfRotOffset = geometry::RotationOffset3D{0, 0, 83 0 : 0}); 84 : 85 : /** 86 : * @brief Constructor for 3D projective geometry using a 3x3 rotation matrix 87 : * 88 : * @param[in] sourceToCenterOfRotation distance from source to the center of rotation (along 89 : * z axis) 90 : * @param[in] centerOfRotationToDetector distance from center of rotation to 91 : * detector (along z axis) 92 : * @param[in] volumeDescriptor descriptor for the 3d volume 93 : * @param[in] sinoDescriptor descriptor for the sinogram 94 : * @param[in] R a 3x3 rotation matrix 95 : * @param[in] px offset of the principal point in x-direction [default 0] 96 : * @param[in] py offset of the principal point in y-direction [default 0] 97 : * @param[in] centerOfRotationOffsetX offset of the center of rotation in x direction 98 : * [default 0] 99 : * @param[in] centerOfRotationOffsetY offset of the center of rotation in y direction 100 : * [default 0] 101 : * @param[in] centerOfRotationOffsetZ offset of the center of rotation in z direction 102 : * [default 0] 103 : */ 104 : Geometry(real_t sourceToCenterOfRotation, real_t centerOfRotationToDetector, 105 : const DataDescriptor& volumeDescriptor, const DataDescriptor& sinoDescriptor, 106 : const RealMatrix_t& R, real_t px = static_cast<real_t>(0.0), 107 : real_t py = static_cast<real_t>(0.0), 108 : real_t centerOfRotationOffsetX = static_cast<real_t>(0.0), 109 : real_t centerOfRotationOffsetY = static_cast<real_t>(0.0), 110 : real_t centerOfRotationOffsetZ = static_cast<real_t>(0.0)); 111 : 112 : /** 113 : * @brief Return the projection matrix 114 : * 115 : * @returns projection matrix 116 : */ 117 : const RealMatrix_t& getProjectionMatrix() const; 118 : 119 : /** 120 : * @brief Return the inverse of the projection matrix 121 : * 122 : * @returns the inverse of the projection matrix 123 : */ 124 : const RealMatrix_t& getInverseProjectionMatrix() const; 125 : 126 : /** 127 : * @brief Return the camera center corresponding to the projection matrix 128 : * 129 : * @returns the camera center (as a coordinate vector) 130 : */ 131 : const RealVector_t& getCameraCenter() const; 132 : 133 : /** 134 : * @brief Return the rotation matrix corresponding to the projection matrix 135 : * 136 : * @returns the rotation matrix 137 : */ 138 : const RealMatrix_t& getRotationMatrix() const; 139 : 140 : /// comparison operator 141 : bool operator==(const Geometry& other) const; 142 : 143 : private: 144 : /// the dimension of the object space / volume (either 2 or 3) 145 : index_t _objectDimension; 146 : 147 : /// the projection matrix (= [_K|0] * [_R|_t] * _S) 148 : RealMatrix_t _P; 149 : /// the inverse of the projection matrix 150 : RealMatrix_t _Pinv; 151 : 152 : /// the intrinsic parameters _K 153 : RealMatrix_t _K; 154 : /// the rotation matrix 155 : RealMatrix_t _R; 156 : /// the translation in object space 157 : RealVector_t _t; 158 : /// the scaling in object space 159 : RealMatrix_t _S; 160 : 161 : /// the camera center _C 162 : RealVector_t _C; 163 : 164 : /// build the projection matrix, its inverse and the camera center 165 : void buildMatrices(); 166 : }; 167 : } // namespace elsa