DLTCalibration.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00035 // ****************************************************************************
00036 // Filename:  DLTCalibration.cpp
00037 // Author:    Pedram Azad
00038 // Date:      04.12.2009
00039 // ****************************************************************************
00040 
00041 
00042 // ****************************************************************************
00043 // Includes
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 // Constructor / Destructor
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 // Methods
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 }


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:57