|
IVT
|
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) 2013 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: Calibration.cpp 00037 // Author: Pedram Azad 00038 // Date: 2004 00039 // **************************************************************************** 00040 // Changes: 17.11.2006, Stefanie Speidel 00041 // * improved calculations for radial lens distortion 00042 // * added calculations for tangential lens distortion 00043 // **************************************************************************** 00044 00045 00046 // **************************************************************************** 00047 // Includes 00048 // **************************************************************************** 00049 00050 #include <new> // for explicitly using correct new/delete operators on VC DSPs 00051 00052 #include "Calibration.h" 00053 #include "Math/Matd.h" 00054 #include "Math/Vecd.h" 00055 #include "Image/ByteImage.h" 00056 00057 #include <stdio.h> 00058 #include <stdlib.h> 00059 #include <math.h> 00060 00061 00062 00063 00064 // **************************************************************************** 00065 // Constructor / Destructor 00066 // **************************************************************************** 00067 00068 CCalibration::CCalibration() 00069 { 00070 m_cameraParameters.width = 640; 00071 m_cameraParameters.height = 480; 00072 00073 Math2d::SetVec(m_cameraParameters.principalPoint, 320, 240); 00074 Math2d::SetVec(m_cameraParameters.focalLength, 580, 580); 00075 SetRotation(Math3d::unit_mat); 00076 SetTranslation(Math3d::zero_vec); 00077 00078 for (int i = 0; i < 4; i++) 00079 m_cameraParameters.distortion[i] = 0; 00080 } 00081 00082 CCalibration::~CCalibration() 00083 { 00084 } 00085 00086 00087 // **************************************************************************** 00088 // Methods 00089 // **************************************************************************** 00090 00091 void CCalibration::GetCalibrationMatrix(Mat3d &K) const 00092 { 00093 Math3d::SetMat(K, 00094 m_cameraParameters.focalLength.x, 0, m_cameraParameters.principalPoint.x, 00095 0, m_cameraParameters.focalLength.y, m_cameraParameters.principalPoint.y, 00096 0, 0, 1); 00097 } 00098 00099 void CCalibration::GetProjectionMatrix(Mat3d &P, Vec3d &p) const 00100 { 00101 Mat3d K; 00102 GetCalibrationMatrix(K); 00103 00104 Math3d::MulMatMat(K, m_cameraParameters.rotation, P); 00105 Math3d::MulMatVec(K, m_cameraParameters.translation, p); 00106 } 00107 00108 00109 void CCalibration::CalculateInverseTransformation() 00110 { 00111 Math3d::Transpose(m_cameraParameters.rotation, m_rotation_inverse); 00112 Math3d::MulMatVec(m_rotation_inverse, m_cameraParameters.translation, m_translation_inverse); 00113 Math3d::MulVecScalar(m_translation_inverse, -1, m_translation_inverse); 00114 } 00115 00116 00117 void CCalibration::SetCameraParameters(float fx, float fy, float cx, float cy, 00118 float d1, float d2, float d3, float d4, 00119 const Mat3d &R, const Vec3d &t, int width, int height) 00120 { 00121 m_cameraParameters.width = width; 00122 m_cameraParameters.height = height; 00123 00124 Math3d::SetMat(m_cameraParameters.rotation, R); 00125 Math3d::SetVec(m_cameraParameters.translation, t); 00126 00127 Math2d::SetVec(m_cameraParameters.focalLength, fx, fy); 00128 Math2d::SetVec(m_cameraParameters.principalPoint, cx, cy); 00129 00130 m_cameraParameters.distortion[0] = d1; 00131 m_cameraParameters.distortion[1] = d2; 00132 m_cameraParameters.distortion[2] = d3; 00133 m_cameraParameters.distortion[3] = d4; 00134 00135 CalculateInverseTransformation(); 00136 } 00137 00138 void CCalibration::Set(const CCalibration &calibration) 00139 { 00140 const CCameraParameters &cameraParameters = calibration.GetCameraParameters(); 00141 00142 m_cameraParameters.width = cameraParameters.width; 00143 m_cameraParameters.height = cameraParameters.height; 00144 00145 Math3d::SetMat(m_cameraParameters.rotation, cameraParameters.rotation); 00146 Math3d::SetVec(m_cameraParameters.translation, cameraParameters.translation); 00147 00148 Math2d::SetVec(m_cameraParameters.focalLength, cameraParameters.focalLength); 00149 Math2d::SetVec(m_cameraParameters.principalPoint, cameraParameters.principalPoint); 00150 00151 m_cameraParameters.distortion[0] = cameraParameters.distortion[0]; 00152 m_cameraParameters.distortion[1] = cameraParameters.distortion[1]; 00153 m_cameraParameters.distortion[2] = cameraParameters.distortion[2]; 00154 m_cameraParameters.distortion[3] = cameraParameters.distortion[3]; 00155 00156 CalculateInverseTransformation(); 00157 } 00158 00159 void CCalibration::SetRotation(const Mat3d &rotation) 00160 { 00161 Math3d::SetMat(m_cameraParameters.rotation, rotation); 00162 CalculateInverseTransformation(); 00163 } 00164 00165 void CCalibration::SetTranslation(const Vec3d &translation) 00166 { 00167 Math3d::SetVec(m_cameraParameters.translation, translation); 00168 CalculateInverseTransformation(); 00169 } 00170 00171 void CCalibration::SetIntrinsicBase(float cx, float cy, float fx, float fy) 00172 { 00173 Math2d::SetVec(m_cameraParameters.principalPoint, cx, cy); 00174 Math2d::SetVec(m_cameraParameters.focalLength, fx, fy); 00175 } 00176 00177 void CCalibration::SetDistortion(float d1, float d2, float d3, float d4) 00178 { 00179 m_cameraParameters.distortion[0] = d1; 00180 m_cameraParameters.distortion[1] = d2; 00181 m_cameraParameters.distortion[2] = d3; 00182 m_cameraParameters.distortion[3] = d4; 00183 } 00184 00185 00186 void CCalibration::WorldToImageCoordinates(const Vec3d &worldPoint, Vec2d &imagePoint, bool bUseDistortionParameters) const 00187 { 00188 Vec3d cameraPoint; 00189 WorldToCameraCoordinates(worldPoint, cameraPoint); 00190 CameraToImageCoordinates(cameraPoint, imagePoint, bUseDistortionParameters); 00191 } 00192 00193 void CCalibration::ImageToWorldCoordinates(const Vec2d &imagePoint, Vec3d &worldPoint, float zc, bool bUseDistortionParameters) const 00194 { 00195 Vec3d cameraPoint; 00196 ImageToCameraCoordinates(imagePoint, cameraPoint, zc, bUseDistortionParameters); 00197 CameraToWorldCoordinates(cameraPoint, worldPoint); 00198 } 00199 00200 void CCalibration::WorldToCameraCoordinates(const Vec3d &worldPoint, Vec3d &cameraPoint) const 00201 { 00202 Math3d::MulMatVec(m_cameraParameters.rotation, worldPoint, m_cameraParameters.translation, cameraPoint); 00203 } 00204 00205 void CCalibration::CameraToWorldCoordinates(const Vec3d &cameraPoint, Vec3d &worldPoint) const 00206 { 00207 Math3d::MulMatVec(m_rotation_inverse, cameraPoint, m_translation_inverse, worldPoint); 00208 } 00209 00210 void CCalibration::CameraToImageCoordinates(const Vec3d &cameraPoint, Vec2d &imagePoint, bool bUseDistortionParameters) const 00211 { 00212 imagePoint.x = m_cameraParameters.principalPoint.x + (cameraPoint.x * m_cameraParameters.focalLength.x) / cameraPoint.z; 00213 imagePoint.y = m_cameraParameters.principalPoint.y + (cameraPoint.y * m_cameraParameters.focalLength.y) / cameraPoint.z; 00214 00215 if (bUseDistortionParameters) 00216 DistortImageCoordinates(imagePoint, imagePoint); 00217 } 00218 00219 void CCalibration::ImageToCameraCoordinates(const Vec2d &imagePoint_, Vec3d &cameraPoint, float zc, bool bUseDistortionParameters) const 00220 { 00221 Vec2d imagePoint; 00222 00223 if (bUseDistortionParameters) 00224 UndistortImageCoordinates(imagePoint_, imagePoint); 00225 else 00226 Math2d::SetVec(imagePoint, imagePoint_); 00227 00228 cameraPoint.x = (imagePoint.x - m_cameraParameters.principalPoint.x) / m_cameraParameters.focalLength.x * zc; 00229 cameraPoint.y = (imagePoint.y - m_cameraParameters.principalPoint.y) / m_cameraParameters.focalLength.y * zc; 00230 cameraPoint.z = zc; 00231 } 00232 00233 void CCalibration::UndistortImageCoordinates(const Vec2d &distortedImagePoint, Vec2d &undistortedImagePoint) const 00234 { 00235 // distortion parameters 00236 const float d1 = m_cameraParameters.distortion[0]; 00237 const float d2 = m_cameraParameters.distortion[1]; 00238 const float d3 = m_cameraParameters.distortion[2]; 00239 const float d4 = m_cameraParameters.distortion[3]; 00240 00241 // undistort 00242 const float x_const = (distortedImagePoint.x - m_cameraParameters.principalPoint.x) / m_cameraParameters.focalLength.x; 00243 const float y_const = (distortedImagePoint.y - m_cameraParameters.principalPoint.y) / m_cameraParameters.focalLength.y; 00244 00245 float x = x_const; 00246 float y = y_const; 00247 00248 for (int i = 0; i < 10; i++) 00249 { 00250 // radial distortion 00251 const float rr = x * x + y * y; 00252 const float factor = 1 + d1 * rr + d2 * rr * rr; 00253 00254 // tangential distortion 00255 const float dx = d3 * (2 * x * y) + d4 * (rr + 2 * x * x); 00256 const float dy = d3 * (rr + 2 * y * y) + d4 * (2 * x * y); 00257 00258 x = (x_const - dx) / factor; 00259 y = (y_const - dy) / factor; 00260 } 00261 00262 undistortedImagePoint.x = x * m_cameraParameters.focalLength.x + m_cameraParameters.principalPoint.x; 00263 undistortedImagePoint.y = y * m_cameraParameters.focalLength.y + m_cameraParameters.principalPoint.y; 00264 } 00265 00266 void CCalibration::DistortImageCoordinates(const Vec2d &undistortedImagePoint, Vec2d &distortedImagePoint) const 00267 { 00268 const float x = (undistortedImagePoint.x - m_cameraParameters.principalPoint.x) / m_cameraParameters.focalLength.x; 00269 const float y = (undistortedImagePoint.y - m_cameraParameters.principalPoint.y) / m_cameraParameters.focalLength.y; 00270 00271 // distortion parameters 00272 const float d1 = m_cameraParameters.distortion[0]; 00273 const float d2 = m_cameraParameters.distortion[1]; 00274 const float d3 = m_cameraParameters.distortion[2]; 00275 const float d4 = m_cameraParameters.distortion[3]; 00276 00277 // radial distortion 00278 const float rr = x * x + y * y; 00279 const float factor = 1 + d1 * rr + d2 * rr * rr; 00280 00281 // tangential distortion 00282 const float dx = d3 * (2 * x * y) + d4 * (rr + 2 * x * x); 00283 const float dy = d3 * (rr + 2 * y * y) + d4 * (2 * x * y); 00284 00285 distortedImagePoint.x = m_cameraParameters.focalLength.x * (factor * x + dx) + m_cameraParameters.principalPoint.x; 00286 distortedImagePoint.y = m_cameraParameters.focalLength.y * (factor * y + dy) + m_cameraParameters.principalPoint.y; 00287 } 00288 00289 // <obsolete names> 00290 void CCalibration::GetCameraCoordinates(const Vec3d &worldPoint, Vec2d &imagePoint, bool bUseDistortionParameters) const 00291 { 00292 WorldToImageCoordinates(worldPoint, imagePoint, bUseDistortionParameters); 00293 } 00294 00295 void CCalibration::GetWorldCoordinates(const Vec2d &imagePoint, Vec3d &worldPoint, float zc, bool bUseDistortionParameters) const 00296 { 00297 ImageToWorldCoordinates(imagePoint, worldPoint, zc, bUseDistortionParameters); 00298 } 00299 00300 void CCalibration::UndistortCameraCoordinates(const Vec2d &distortedImagePoint, Vec2d &undistortedImagePoint) const 00301 { 00302 UndistortImageCoordinates(distortedImagePoint, undistortedImagePoint); 00303 } 00304 00305 void CCalibration::DistortCameraCoordinates(const Vec2d &undistortedImagePoint, Vec2d &distortedImagePoint) const 00306 { 00307 DistortImageCoordinates(undistortedImagePoint, distortedImagePoint); 00308 } 00309 // </obsolete names> 00310 00311 00312 bool CCalibration::LoadCameraParameters(const char *pCameraParameterFileName, int nCamera, bool bSetExtrinsicToIdentity) 00313 { 00314 int i, nCameraCount = 0; 00315 00316 FILE* f = fopen(pCameraParameterFileName, "r"); 00317 if(!f) 00318 return false; 00319 00320 if (fscanf(f, "%d", &nCameraCount) != 1 || nCameraCount < nCamera + 1) 00321 { 00322 fclose(f); 00323 return false; 00324 } 00325 00326 float skip_value, w, h; 00327 00328 for (i = 0; i < nCamera; i++) 00329 for (int j = 0; j < 27; j++) 00330 if (fscanf(f, "%f", &skip_value) != 1) 00331 { 00332 fclose(f); 00333 return false; 00334 } 00335 00336 if (fscanf(f, "%f", &w) != 1) { fclose(f); return false; } 00337 if (fscanf(f, "%f", &h) != 1) { fclose(f); return false; } 00338 if (fscanf(f, "%f", &m_cameraParameters.focalLength.x) != 1) { fclose(f); return false; } 00339 if (fscanf(f, "%f", &skip_value) != 1) { fclose(f); return false; } 00340 if (fscanf(f, "%f", &m_cameraParameters.principalPoint.x) != 1) { fclose(f); return false; } 00341 if (fscanf(f, "%f", &skip_value) != 1) { fclose(f); return false; } 00342 if (fscanf(f, "%f", &m_cameraParameters.focalLength.y) != 1) { fclose(f); return false; } 00343 if (fscanf(f, "%f", &m_cameraParameters.principalPoint.y) != 1) { fclose(f); return false; } 00344 if (fscanf(f, "%f", &skip_value) != 1) { fclose(f); return false; } 00345 if (fscanf(f, "%f", &skip_value) != 1) { fclose(f); return false; } 00346 if (fscanf(f, "%f", &skip_value) != 1) { fclose(f); return false; } 00347 for (i = 0; i < 4; i++) 00348 if (fscanf(f, "%f", &m_cameraParameters.distortion[i]) != 1) { fclose(f); return false; } 00349 if (fscanf(f, "%f", &m_cameraParameters.rotation.r1) != 1) { fclose(f); return false; } 00350 if (fscanf(f, "%f", &m_cameraParameters.rotation.r2) != 1) { fclose(f); return false; } 00351 if (fscanf(f, "%f", &m_cameraParameters.rotation.r3) != 1) { fclose(f); return false; } 00352 if (fscanf(f, "%f", &m_cameraParameters.rotation.r4) != 1) { fclose(f); return false; } 00353 if (fscanf(f, "%f", &m_cameraParameters.rotation.r5) != 1) { fclose(f); return false; } 00354 if (fscanf(f, "%f", &m_cameraParameters.rotation.r6) != 1) { fclose(f); return false; } 00355 if (fscanf(f, "%f", &m_cameraParameters.rotation.r7) != 1) { fclose(f); return false; } 00356 if (fscanf(f, "%f", &m_cameraParameters.rotation.r8) != 1) { fclose(f); return false; } 00357 if (fscanf(f, "%f", &m_cameraParameters.rotation.r9) != 1) { fclose(f); return false; } 00358 if (fscanf(f, "%f", &m_cameraParameters.translation.x) != 1) { fclose(f); return false; } 00359 if (fscanf(f, "%f", &m_cameraParameters.translation.y) != 1) { fclose(f); return false; } 00360 if (fscanf(f, "%f", &m_cameraParameters.translation.z) != 1) { fclose(f); return false; } 00361 00362 m_cameraParameters.width = int(w + 0.5f); 00363 m_cameraParameters.height = int(h + 0.5f); 00364 00365 fclose(f); 00366 00367 if (bSetExtrinsicToIdentity) 00368 { 00369 SetRotation(Math3d::unit_mat); 00370 SetTranslation(Math3d::zero_vec); 00371 } 00372 else 00373 { 00374 CalculateInverseTransformation(); 00375 } 00376 00377 return true; 00378 } 00379 00380 bool CCalibration::SaveCameraParameters(const char *pFileName) const 00381 { 00382 const Mat3d &rotation = m_cameraParameters.rotation; 00383 const Vec3d &translation = m_cameraParameters.translation; 00384 00385 const float cx = m_cameraParameters.principalPoint.x; 00386 const float cy = m_cameraParameters.principalPoint.y; 00387 const float fx = m_cameraParameters.focalLength.x; 00388 const float fy = m_cameraParameters.focalLength.y; 00389 00390 const float d1 = m_cameraParameters.distortion[0]; 00391 const float d2 = m_cameraParameters.distortion[1]; 00392 const float d3 = m_cameraParameters.distortion[2]; 00393 const float d4 = m_cameraParameters.distortion[3]; 00394 00395 FILE *f = fopen(pFileName, "w"); 00396 if (!f) 00397 return false; 00398 00399 fprintf(f, "1\n\n"); 00400 fprintf(f, "%i %i %.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f ", m_cameraParameters.width, m_cameraParameters.height, fx, 0.0, cx, 0.0, fy, cy, 0.0, 0.0, 1.0); 00401 fprintf(f, "%.10f %.10f %.10f %.10f ", d1, d2, d3, d4); 00402 fprintf(f, "%.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f ", rotation.r1, rotation.r2, rotation.r3, rotation.r4, rotation.r5, rotation.r6, rotation.r7, rotation.r8, rotation.r9); 00403 fprintf(f, "%.10f %.10f %.10f\n", translation.x, translation.y, translation.z); 00404 00405 fclose(f); 00406 00407 return true; 00408 } 00409 00410 void CCalibration::PrintCameraParameters() const 00411 { 00412 printf("cx/cy = %.10f / %.10f\nfx/fy = %.10f / %.10f\nt = %.10f %.10f %.10f\nR = %.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f %.10f\nd1/d2/d3/d4 = %.10f %.10f %.10f %.10f\n\n", 00413 m_cameraParameters.principalPoint.x, 00414 m_cameraParameters.principalPoint.y, 00415 m_cameraParameters.focalLength.x, 00416 m_cameraParameters.focalLength.y, 00417 m_cameraParameters.translation.x, 00418 m_cameraParameters.translation.y, 00419 m_cameraParameters.translation.z, 00420 m_cameraParameters.rotation.r1, 00421 m_cameraParameters.rotation.r2, 00422 m_cameraParameters.rotation.r3, 00423 m_cameraParameters.rotation.r4, 00424 m_cameraParameters.rotation.r5, 00425 m_cameraParameters.rotation.r6, 00426 m_cameraParameters.rotation.r7, 00427 m_cameraParameters.rotation.r8, 00428 m_cameraParameters.rotation.r9, 00429 m_cameraParameters.distortion[0], 00430 m_cameraParameters.distortion[1], 00431 m_cameraParameters.distortion[2], 00432 m_cameraParameters.distortion[3] 00433 ); 00434 }