00001
00016 #include <dlrComputerVision/stereoRectify.h>
00017 #include <dlrLinearAlgebra/linearAlgebra.h>
00018 #include <dlrNumeric/utilities.h>
00019
00020 namespace linalg = dlr::linearAlgebra;
00021 namespace num = dlr::numeric;
00022
00023
00024 namespace {
00025
00026 namespace cv = dlr::computerVision;
00027
00028 num::Array2D<double>
00029 extractUpperLeftBlock(cv::CameraIntrinsicsPinhole const& intrinsics,
00030 num::Transform3D const& cameraTworld)
00031 {
00032 num::Array2D<double> result(3, 3);
00033 #if 0
00034 result(0, 0) = (intrinsics.getKx() * cameraTworld(0, 0)
00035 + intrinsics.getCenterU() * cameraTworld(2, 0));
00036 result(0, 1) = (intrinsics.getKx() * cameraTworld(0, 1)
00037 + intrinsics.getCenterU() * cameraTworld(2, 1));
00038 result(0, 2) = (intrinsics.getKx() * cameraTworld(0, 2)
00039 + intrinsics.getCenterU() * cameraTworld(2, 2));
00040 result(1, 0) = (intrinsics.getKy() * cameraTworld(1, 0)
00041 + intrinsics.getCenterV() * cameraTworld(2, 0));
00042 result(1, 1) = (intrinsics.getKy() * cameraTworld(1, 1)
00043 + intrinsics.getCenterV() * cameraTworld(2, 1));
00044 result(1, 2) = (intrinsics.getKy() * cameraTworld(1, 2)
00045 + intrinsics.getCenterV() * cameraTworld(2, 2));
00046 result(2, 0) = cameraTworld(2, 0);
00047 result(2, 1) = cameraTworld(2, 1);
00048 result(2, 2) = cameraTworld(2, 2);
00049 #else
00050 result(0, 0) = (intrinsics.getKx() * cameraTworld(0, 0)
00051 + intrinsics.getCenterU() * cameraTworld(2, 0));
00052 result(0, 1) = (intrinsics.getKx() * cameraTworld(0, 1)
00053 + intrinsics.getCenterU() * cameraTworld(2, 1));
00054 result(0, 2) = (intrinsics.getKx() * cameraTworld(0, 2)
00055 + intrinsics.getCenterU() * cameraTworld(2, 2));
00056
00057 double ky = intrinsics.getKy();
00058 double c10 = cameraTworld(1, 0);
00059 double dummy = ky * c10;
00060 dummy += intrinsics.getCenterV() * cameraTworld(2, 0);
00061 result(1, 0) = dummy;
00062 result(1, 1) = (intrinsics.getKy() * cameraTworld(1, 1)
00063 + intrinsics.getCenterV() * cameraTworld(2, 1));
00064 result(1, 2) = (intrinsics.getKy() * cameraTworld(1, 2)
00065 + intrinsics.getCenterV() * cameraTworld(2, 2));
00066 result(2, 0) = cameraTworld(2, 0);
00067 result(2, 1) = cameraTworld(2, 1);
00068 result(2, 2) = cameraTworld(2, 2);
00069 #endif
00070 return result;
00071 }
00072
00073
00074 };
00075
00076
00077 namespace dlr {
00078
00079 namespace computerVision {
00080
00081 void
00082 stereoRectify(CameraIntrinsicsPinhole const& intrinsics0,
00083 CameraIntrinsicsPinhole const& intrinsics1,
00084 numeric::Transform3D const& camera0Tworld,
00085 numeric::Transform3D const& camera1Tworld,
00086 CameraIntrinsicsPinhole& rectifiedIntrinsics0,
00087 CameraIntrinsicsPinhole& rectifiedIntrinsics1,
00088 numeric::Transform3D& rcamera0Tworld,
00089 numeric::Transform3D& rcamera1Tworld,
00090 numeric::Transform2D& image0Trimage0,
00091 numeric::Transform2D& image1Trimage1)
00092 {
00093
00094 double localEpsilon = 1.0E-12;
00095
00096
00097
00098 num::Transform3D worldTcamera0 = camera0Tworld.invert();
00099 num::Transform3D worldTcamera1 = camera1Tworld.invert();
00100 num::Vector3D focalPoint0(
00101 worldTcamera0(0, 3), worldTcamera0(1, 3), worldTcamera0(2, 3));
00102 num::Vector3D focalPoint1(
00103 worldTcamera1(0, 3), worldTcamera1(1, 3), worldTcamera1(2, 3));
00104
00105
00106
00107 num::Vector3D xAxis = focalPoint1 - focalPoint0;
00108 double xMagnitude = num::magnitude(xAxis);
00109 if(xMagnitude < localEpsilon) {
00110 DLR_THROW(ValueException, "rectify()",
00111 "Optical centers of camera1 and camera0 are too close "
00112 "together.");
00113 }
00114 xAxis /= xMagnitude;
00115
00116
00117
00118
00119
00120 num::Vector3D oldZ(
00121 camera0Tworld(2, 0), camera0Tworld(2, 1), camera0Tworld(2, 2));
00122 num::Vector3D yAxis = num::cross(oldZ, xAxis);
00123 double yMagnitude = num::magnitude(yAxis);
00124 if(yMagnitude < localEpsilon) {
00125 DLR_THROW(ValueException, "rectify()",
00126 "Camera1 lies too close to the optical axis of camera0.");
00127 }
00128 yAxis /= yMagnitude;
00129
00130
00131
00132 num::Vector3D zAxis = num::cross(xAxis, yAxis);
00133 double zMagnitude = num::magnitude(zAxis);
00134 if(zMagnitude < localEpsilon) {
00135 DLR_THROW(LogicException, "rectify()",
00136 "Error in computation of z axis.");
00137 }
00138 zAxis /= zMagnitude;
00139
00140
00141
00142
00143 num::Transform3D worldTrcamera0(
00144 xAxis.x(), yAxis.x(), zAxis.x(), worldTcamera0(0, 3),
00145 xAxis.y(), yAxis.y(), zAxis.y(), worldTcamera0(1, 3),
00146 xAxis.z(), yAxis.z(), zAxis.z(), worldTcamera0(2, 3),
00147 0.0, 0.0, 0.0, 1.0);
00148 num::Transform3D worldTrcamera1(
00149 xAxis.x(), yAxis.x(), zAxis.x(), worldTcamera1(0, 3),
00150 xAxis.y(), yAxis.y(), zAxis.y(), worldTcamera1(1, 3),
00151 xAxis.z(), yAxis.z(), zAxis.z(), worldTcamera1(2, 3),
00152 0.0, 0.0, 0.0, 1.0);
00153
00154 rcamera0Tworld = worldTrcamera0.invert();
00155 rcamera1Tworld = worldTrcamera1.invert();
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 size_t numPixelsX = intrinsics0.getNumPixelsX();
00167 size_t numPixelsY = intrinsics0.getNumPixelsY();
00168 double focalLength =
00169 (intrinsics0.getFocalLength() + intrinsics1.getFocalLength()) / 2.0;
00170 double pixelSizeX =
00171 (intrinsics0.getPixelSizeX() + intrinsics1.getPixelSizeX()) / 2.0;
00172 double pixelSizeY =
00173 (intrinsics0.getPixelSizeY() + intrinsics1.getPixelSizeY()) / 2.0;
00174 double centerU =
00175 (intrinsics0.getCenterU() + intrinsics1.getCenterU()) / 2.0;
00176 double centerV =
00177 (intrinsics0.getCenterV() + intrinsics1.getCenterV()) / 2.0;
00178 rectifiedIntrinsics0 = CameraIntrinsicsPinhole(
00179 numPixelsX, numPixelsY, focalLength, pixelSizeX, pixelSizeY,
00180 centerU, centerV);
00181 rectifiedIntrinsics1 = rectifiedIntrinsics0;
00182
00183
00184
00185
00186 num::Array2D<double> oldQ0 = extractUpperLeftBlock(
00187 intrinsics0, camera0Tworld);
00188 num::Array2D<double> oldQ1 = extractUpperLeftBlock(
00189 intrinsics1, camera1Tworld);
00190 num::Array2D<double> newQ0 = extractUpperLeftBlock(
00191 rectifiedIntrinsics0, rcamera0Tworld);
00192 num::Array2D<double> newQ1 = extractUpperLeftBlock(
00193 rectifiedIntrinsics1, rcamera1Tworld);
00194
00195 num::Array2D<double> rectArray0 =
00196 num::matrixMultiply(oldQ0, linalg::inverse(newQ0));
00197 num::Array2D<double> rectArray1 =
00198 num::matrixMultiply(oldQ1, linalg::inverse(newQ1));
00199 image0Trimage0.setTransform(
00200 rectArray0(0, 0), rectArray0(0, 1), rectArray0(0, 2),
00201 rectArray0(1, 0), rectArray0(1, 1), rectArray0(1, 2),
00202 rectArray0(2, 0), rectArray0(2, 1), rectArray0(2, 2));
00203 image1Trimage1.setTransform(
00204 rectArray1(0, 0), rectArray1(0, 1), rectArray1(0, 2),
00205 rectArray1(1, 0), rectArray1(1, 1), rectArray1(1, 2),
00206 rectArray1(2, 0), rectArray1(2, 1), rectArray1(2, 2));
00207 }
00208
00209
00210 }
00211
00212 }
00213