00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "Math/Math3d.h"
00047 #include "Math/Math2d.h"
00048 #include "Math/FloatMatrix.h"
00049 #include "Math/FloatVector.h"
00050 #include "Math/LinearAlgebra.h"
00051 #include "Calibration/Calibration.h"
00052
00053 #include "DLTCalibration.h"
00054
00055 #include <stdio.h>
00056 #include <math.h>
00057
00058
00059
00060
00061
00062
00063
00064 CDLTCalibration::CDLTCalibration()
00065 {
00066 m_pPairElements = 0;
00067 m_nPairElements = 0;
00068
00069 L1 = L6 = 1;
00070 L2 = L3 = L4 = L5 = L7 = L8 = L9 = L10 = L11 = 0;
00071 }
00072
00073 CDLTCalibration::~CDLTCalibration()
00074 {
00075 }
00076
00077
00078
00079
00080
00081
00082 float CDLTCalibration::Calibrate(const CDLTCalibration::PairElement *pPairElements, int nPairElements, CCalibration &resultCalibration, DistortionType eCalculateDistortionParameters, int nIterations)
00083 {
00084 m_pPairElements = pPairElements;
00085 m_nPairElements = nPairElements;
00086
00087 resultCalibration.SetDistortion(0, 0, 0, 0);
00088
00089 if (eCalculateDistortionParameters == eNoDistortion)
00090 {
00091 CalculateDLT(resultCalibration, true);
00092 ExtractFromDLT(resultCalibration);
00093 }
00094 else
00095 {
00096 for (int i = 0; i < nIterations; i++)
00097 {
00098 CalculateDLT(resultCalibration, i == 0);
00099 ExtractFromDLT(resultCalibration);
00100
00101 if (eCalculateDistortionParameters == eRadialDistortion)
00102 CalculateRadialLensDistortion(resultCalibration);
00103 else if (eCalculateDistortionParameters == eRadialAndTangentialDistortion)
00104 CalculateRadialAndTangentialLensDistortion(resultCalibration);
00105 }
00106 }
00107
00108 return CheckCalibration(resultCalibration);
00109 }
00110
00111
00112 void CDLTCalibration::GetImageCoordinatesDLT(const Vec3d &worldPoint, Vec2d &imagePoint)
00113 {
00114 const float x = worldPoint.x;
00115 const float y = worldPoint.y;
00116 const float z = worldPoint.z;
00117
00118 imagePoint.x = (L1 * x + L2 * y + L3 * z + L4) / (L9 * x + L10 * y + L11 * z + 1);
00119 imagePoint.y = (L5 * x + L6 * y + L7 * z + L8) / (L9 * x + L10 * y + L11 * z + 1);
00120 }
00121
00122
00123 float CDLTCalibration::CheckCalibration(const CCalibration &calibration)
00124 {
00125 float error = 0.0f;
00126 float max = 0.0f;
00127
00128 for (int i = 0; i < m_nPairElements; i++)
00129 {
00130 Vec2d imagePoint;
00131 calibration.WorldToImageCoordinates(m_pPairElements[i].worldPoint, imagePoint);
00132
00133 const float distance = Math2d::Distance(m_pPairElements[i].imagePoint, imagePoint);
00134
00135 if (distance > max)
00136 max = distance;
00137
00138 error += distance;
00139 }
00140
00141 return error / m_nPairElements;
00142 }
00143
00144
00145 float CDLTCalibration::CheckDLT()
00146 {
00147 float error = 0.0f;
00148
00149 for (int i = 0; i < m_nPairElements; i++)
00150 {
00151 Vec2d imagePoint;
00152 GetImageCoordinatesDLT(m_pPairElements[i].worldPoint, imagePoint);
00153
00154 error += Math2d::Distance(m_pPairElements[i].imagePoint, imagePoint);
00155 }
00156
00157 return error / m_nPairElements;
00158 }
00159
00160
00161 void CDLTCalibration::CalculateRadialLensDistortion(CCalibration &calibration)
00162 {
00163 CFloatMatrix A(2, 2 * m_nPairElements);
00164 CFloatVector b(2 * m_nPairElements);
00165
00166 const float cx = calibration.GetCameraParameters().principalPoint.x;
00167 const float cy = calibration.GetCameraParameters().principalPoint.y;
00168 const float fx = calibration.GetCameraParameters().focalLength.x;
00169 const float fy = calibration.GetCameraParameters().focalLength.y;
00170
00171 for (int i = 0; i < m_nPairElements; i++)
00172 {
00173 const int ii = 2 * i;
00174
00175 Vec2d undistorted_point;
00176 calibration.WorldToImageCoordinates(m_pPairElements[i].worldPoint, undistorted_point, false);
00177
00178 const float u = undistorted_point.x;
00179 const float v = undistorted_point.y;
00180 const float ud = m_pPairElements[i].imagePoint.x;
00181 const float vd = m_pPairElements[i].imagePoint.y;
00182
00183 const float x = (u - cx) / fx;
00184 const float y = (v - cy) / fy;
00185
00186 const float rr = x * x + y * y;
00187
00188 A(0, ii) = (u - cx) * rr;
00189 A(1, ii) = (u - cx) * rr * rr;
00190 A(0, ii + 1) = (v - cy) * rr;
00191 A(1, ii + 1) = (v - cy) * rr * rr;
00192
00193 b[ii] = ud - u;
00194 b[ii + 1] = vd - v;
00195 }
00196
00197 CFloatVector result(2);
00198 LinearAlgebra::SolveLinearLeastSquaresSimple(&A, &b, &result);
00199
00200 calibration.SetDistortion((float) result[0], (float) result[1], 0, 0);
00201 }
00202
00203
00204 void CDLTCalibration::CalculateRadialAndTangentialLensDistortion(CCalibration &calibration)
00205 {
00206 CFloatMatrix A(4, 2 * m_nPairElements);
00207 CFloatVector b(2 * m_nPairElements);
00208
00209 const float cx = calibration.GetCameraParameters().principalPoint.x;
00210 const float cy = calibration.GetCameraParameters().principalPoint.y;
00211 const float fx = calibration.GetCameraParameters().focalLength.x;
00212 const float fy = calibration.GetCameraParameters().focalLength.y;
00213
00214 for (int i = 0; i < m_nPairElements; i++)
00215 {
00216 const int ii = 2 * i;
00217
00218 Vec2d undistorted_point;
00219 calibration.WorldToImageCoordinates(m_pPairElements[i].worldPoint, undistorted_point, false);
00220
00221 const float u = undistorted_point.x;
00222 const float v = undistorted_point.y;
00223 const float ud = m_pPairElements[i].imagePoint.x;
00224 const float vd = m_pPairElements[i].imagePoint.y;
00225
00226 const float x = (u - cx) / fx;
00227 const float y = (v - cy) / fy;
00228
00229 const float rr = x * x + y * y;
00230
00231 A(0, ii) = (u - cx) * rr;
00232 A(1, ii) = (u - cx) * rr * rr;
00233 A(2, ii) = 2 * x * y * fx;
00234 A(3, ii) = (rr + 2 * x * x) * fx;
00235 A(0, ii + 1) = (v - cy) * rr;
00236 A(1, ii + 1) = (v - cy) * rr * rr;
00237 A(2, ii + 1) = (rr + 2 * y * y) * fy;
00238 A(3, ii + 1) = 2 * x * y * fy;
00239
00240 b[ii] = ud - u;
00241 b[ii + 1] = vd - v;
00242 }
00243
00244 CFloatVector result(4);
00245 LinearAlgebra::SolveLinearLeastSquaresSimple(&A, &b, &result);
00246
00247 calibration.SetDistortion((float) result[0], (float) result[1], (float) result[2], (float) result[3]);
00248 }
00249
00250
00251 void CDLTCalibration::ExtractFromDLT(CCalibration &calibration)
00252 {
00253 const float LL = L9 * L9 + L10 * L10 + L11 * L11;
00254 const float L = sqrt(LL);
00255 const float atc = L1 * L9 + L2 * L10 + L3 * L11;
00256 const float btc = L5 * L9 + L6 * L10 + L7 * L11;
00257 const float atb = L1 * L5 * L2 * L6 + L3 * L7;
00258 const float ata = L1 * L1 + L2 * L2 + L3 * L3;
00259 const float btb = L5 * L5 + L6 * L6 + L7 * L7;
00260
00261 const float cx = atc / LL;
00262 const float cy = btc / LL;
00263 const float fx = sqrt(ata / LL - cx * cx);
00264 const float fy = sqrt(btb / LL - cy * cy);
00265
00266 const float r31 = L9 / L;
00267 const float r32 = L10 / L;
00268 const float r33 = L11 / L;
00269 const float r11 = (L1 / L - cx * r31) / fx;
00270 const float r12 = (L2 / L - cx * r32) / fx;
00271 const float r13 = (L3 / L - cx * r33) / fx;
00272 const float r21 = (L5 / L - cy * r31) / fy;
00273 const float r22 = (L6 / L - cy * r32) / fy;
00274 const float r23 = (L7 / L - cy * r33) / fy;
00275
00276 const Mat3d rotation = { r11, r12, r13, r21, r22, r23, r31, r32, r33 };
00277 Vec3d translation;
00278
00279 Mat3d abc = { L1, L2, L3, L5, L6, L7, L9, L10, L11 };
00280 Math3d::Invert(abc, abc);
00281
00282 const Vec3d x = { L4, L8, 1 };
00283 Math3d::MulMatVec(abc, x, translation);
00284 Math3d::MulMatVec(rotation, translation, translation);
00285
00286 calibration.SetIntrinsicBase(cx, cy, fx, fy);
00287 calibration.SetRotation(rotation);
00288 calibration.SetTranslation(translation);
00289 }
00290
00291
00292 void CDLTCalibration::CalculateDLT(const CCalibration &calibration, bool bFirstCall)
00293 {
00294 CFloatMatrix A(11, 2 * m_nPairElements);
00295 CFloatVector b(2 * m_nPairElements);
00296
00297 for (int i = 0; i < m_nPairElements; i++)
00298 {
00299 const float x = m_pPairElements[i].worldPoint.x;
00300 const float y = m_pPairElements[i].worldPoint.y;
00301 const float z = m_pPairElements[i].worldPoint.z;
00302
00303 float u = m_pPairElements[i].imagePoint.x;
00304 float v = m_pPairElements[i].imagePoint.y;
00305
00306 if (!bFirstCall)
00307 {
00308 const Vec2d distortedPoint = { u, v };
00309 Vec2d undistortedPoint;
00310
00311 calibration.UndistortImageCoordinates(distortedPoint, undistortedPoint);
00312
00313 u = undistortedPoint.x;
00314 v = undistortedPoint.y;
00315 }
00316
00317 const int ii = 2 * i;
00318
00319 A(0, ii) = x;
00320 A(1, ii) = y;
00321 A(2, ii) = z;
00322 A(3, ii) = 1;
00323 A(4, ii) = 0;
00324 A(5, ii) = 0;
00325 A(6, ii) = 0;
00326 A(7, ii) = 0;
00327 A(8, ii) = -u * x;
00328 A(9, ii) = -u * y;
00329 A(10, ii) = -u * z;
00330
00331 A(0, ii + 1) = 0;
00332 A(1, ii + 1) = 0;
00333 A(2, ii + 1) = 0;
00334 A(3, ii + 1) = 0;
00335 A(4, ii + 1) = x;
00336 A(5, ii + 1) = y;
00337 A(6, ii + 1) = z;
00338 A(7, ii + 1) = 1;
00339 A(8, ii + 1) = -v * x;
00340 A(9, ii + 1) = -v * y;
00341 A(10, ii + 1) = -v * z;
00342
00343 b[ii] = u;
00344 b[ii + 1] = v;
00345 }
00346
00347 CFloatVector result(11);
00348 LinearAlgebra::SolveLinearLeastSquaresSimple(&A, &b, &result);
00349
00350 L1 = (float) result[0];
00351 L2 = (float) result[1];
00352 L3 = (float) result[2];
00353 L4 = (float) result[3];
00354 L5 = (float) result[4];
00355 L6 = (float) result[5];
00356 L7 = (float) result[6];
00357 L8 = (float) result[7];
00358 L9 = (float) result[8];
00359 L10 = (float) result[9];
00360 L11 = (float) result[10];
00361 }