RAPiD.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:  RAPiD.cpp
00037 // Author:    Pedram Azad
00038 // Date:      25.01.2008
00039 // ****************************************************************************
00040 
00041 
00042 // ****************************************************************************
00043 // Includes
00044 // ****************************************************************************
00045 
00046 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00047 
00048 #include "RAPiD.h"
00049 
00050 #include "Math/FloatMatrix.h"
00051 #include "Math/FloatVector.h"
00052 #include "Math/LinearAlgebra.h"
00053 #include "Calibration/Calibration.h"
00054 #include "DataStructures/DynamicArray.h"
00055 #include "Image/ImageProcessor.h"
00056 #include "Image/ByteImage.h"
00057 #include "Tracking/ICP.h"
00058 
00059 #include <stdio.h>
00060 
00061 
00062 // ****************************************************************************
00063 // This is an implementation of the algorithm described in:
00064 // C. Harris, "Tracking with rigid models", in "Active Vision",
00065 // edited by A. Blake, pages 59-73, MIT Press, 1992.
00066 // The Kalman filtering step is not implemented.
00067 // ****************************************************************************
00068 
00069 
00070 
00071 // ****************************************************************************
00072 // Constructor / Destructor
00073 // ****************************************************************************
00074 
00075 CRAPiD::CRAPiD()
00076 {
00077         m_nPixelsSearchDistance = 15;
00078         m_nPixelsDelta = 15;
00079 }
00080 
00081 CRAPiD::~CRAPiD()
00082 {
00083 }
00084 
00085 
00086 // ****************************************************************************
00087 // Methods
00088 // ****************************************************************************
00089 
00090 void CRAPiD::Init(const CCalibration *pCalibration)
00091 {
00092         m_pCalibration = pCalibration;
00093 }
00094 
00095 bool CRAPiD::Track(const CByteImage *pEdgeImage, Vec3d *pOutlinePoints, int nOutlinePoints,
00096                    Mat3d &rotation, Vec3d &translation)
00097 {
00098         if (pEdgeImage->type != CByteImage::eGrayScale)
00099         {
00100                 printf("error: input image must be grayscale image for CRAPiD::Track\n");
00101                 return false;
00102         }
00103 
00104         if (m_pCalibration->GetCameraParameters().width != pEdgeImage->width ||
00105                 m_pCalibration->GetCameraParameters().height != pEdgeImage->height)
00106         {
00107                 printf("error: calibration does not match image in CRAPiD::Track\n");
00108                 return false;
00109         }
00110 
00111         CDynamicArray rapidList(1000);
00112 
00113         const unsigned char *pixels = pEdgeImage->pixels;
00114         const int width = pEdgeImage->width;
00115         const int height = pEdgeImage->height;
00116 
00117         for (int i = 0; i < nOutlinePoints; i += 2)
00118         {
00119                 Vec3d p1, p2;
00120                 Math3d::SetVec(p1, pOutlinePoints[i]);
00121                 Math3d::SetVec(p2, pOutlinePoints[i + 1]);
00122 
00123                 Vec2d p1_, p2_;
00124                 {
00125                         Vec3d temp;
00126                         
00127                         Math3d::MulMatVec(rotation, p1, translation, temp);
00128                         m_pCalibration->WorldToImageCoordinates(temp, p1_, false);
00129 
00130                         Math3d::MulMatVec(rotation, p2, translation, temp);
00131                         m_pCalibration->WorldToImageCoordinates(temp, p2_, false);
00132                 }
00133 
00134                 const float length_ = Math2d::Distance(p1_, p2_);
00135 
00136                 const int nControlPoints = int(length_ / m_nPixelsDelta) - 1;
00137                 if (nControlPoints < 1)
00138                         continue;
00139 
00140                 Vec3d u;
00141                 Math3d::SubtractVecVec(p2, p1, u);
00142                 const float delta_length = Math3d::Length(u) / nControlPoints;
00143                 Math3d::NormalizeVec(u);
00144                 Math3d::MulVecScalar(u, delta_length, u);
00145 
00146                 Vec2d u_ = { p1_.x - p2_.x, p1_.y - p2_.y };
00147                 Math2d::NormalizeVec(u_);
00148 
00149                 // calculate normal vector
00150                 Vec2d n = { p1_.y - p2_.y, p2_.x - p1_.x };
00151                 Math2d::NormalizeVec(n);
00152                 
00153                 Vec3d p;
00154                 Math3d::SetVec(p, p1);
00155 
00156                 for (int j = 0; j < nControlPoints; j++)
00157                 {
00158                         Math3d::AddToVec(p, u);
00159 
00160                         Vec2d p_;
00161                         {
00162                                 Vec3d temp;
00163                                 Math3d::MulMatVec(rotation, p, translation, temp);
00164                                 m_pCalibration->WorldToImageCoordinates(temp, p_, false);
00165                         }
00166 
00167                         // search in perpendicular direction
00168                         Vec2d pn1, pn2;
00169                         int k, l = -1;
00170                         bool bPlus = true;
00171 
00172                         Math2d::SetVec(pn1, p_);
00173                         Math2d::SetVec(pn2, p_);
00174                         for (k = 0; k < m_nPixelsSearchDistance; k++)
00175                         {
00176                                 int x, y;
00177 
00178                                 // can be optimized: checking boundaries within loop is slow but convenient
00179                                 x = int(pn1.x + 0.5f);
00180                                 y = int(pn1.y + 0.5f);
00181                                 if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
00182                                 {
00183                                         l = k;
00184                                         bPlus = true;
00185                                         break;
00186                                 }
00187 
00188                                 x = int(pn2.x + 0.5f);
00189                                 y = int(pn2.y + 0.5f);
00190                                 if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
00191                                 {
00192                                         l = k;
00193                                         bPlus = false;
00194                                         break;
00195                                 }
00196 
00197                                 Math2d::AddToVec(pn1, n);
00198                                 Math2d::SubtractFromVec(pn2, n);
00199                         }
00200 
00201                         if (l != -1)
00202                         {
00203                                 CRAPiDElement *pRAPiDElement = new CRAPiDElement();
00204 
00205                                 pRAPiDElement->l = float(l);
00206                                 Math2d::SetVec(pRAPiDElement->n, n);
00207                                 Math2d::NormalizeVec(pRAPiDElement->n);
00208                                 Math3d::SetVec(pRAPiDElement->p, p);
00209 
00210                                 if (!bPlus)
00211                                         Math2d::MulVecScalar(pRAPiDElement->n, -1, pRAPiDElement->n);
00212 
00213                                 rapidList.AddElement(pRAPiDElement);
00214                         }
00215                 }
00216         }
00217 
00218         return RAPiD(rapidList, m_pCalibration, rotation, translation);
00219 }
00220 
00221 bool CRAPiD::RAPiD(CDynamicArray &elementList, const CCalibration *pCalibration, Mat3d &rotation, Vec3d &translation)
00222 {
00223         if (elementList.GetSize() < 6)
00224         {
00225                 printf("error: not enough input points for RAPiD::RAPiD\n");
00226                 return false;
00227         }
00228 
00229         const CCalibration::CCameraParameters &cameraParameters = pCalibration->GetCameraParameters();
00230         const float fx = cameraParameters.focalLength.x;
00231         const float fy = cameraParameters.focalLength.y;
00232 
00233         Vec3d t;
00234         Math3d::MulMatVec(cameraParameters.rotation, translation, cameraParameters.translation, t);
00235 
00236         Mat3d R;
00237         Math3d::MulMatMat(cameraParameters.rotation, rotation, R);
00238 
00239         const int nPoints = elementList.GetSize();
00240 
00241         int i;
00242 
00243         CFloatMatrix A(6, 6);
00244         ImageProcessor::Zero(&A);
00245 
00246         CFloatVector b(6);
00247         b.data[0] = b.data[1] = b.data[2] = b.data[3] = b.data[4] = b.data[5] = 0;
00248 
00249         CFloatMatrix C(1, 6), CT(6, 1);
00250         CFloatMatrix CTC(6, 6);
00251 
00252         for (i = 0; i < nPoints; i++)
00253         {
00254                 CRAPiDElement *pElement = (CRAPiDElement *) elementList.GetElement(i);
00255 
00256                 Vec3d p;
00257                 Math3d::MulMatVec(R, pElement->p, p);
00258 
00259                 const float x = p.x;
00260                 const float y = p.y;
00261                 const float z = p.z;
00262 
00263                 const float xc = x + t.x;
00264                 const float yc = y + t.y;
00265                 const float zc = z + t.z;
00266 
00267                 const float u0 = fx * xc / zc;
00268                 const float v0 = fy * yc / zc;
00269 
00270                 const float nx = pElement->n.x;
00271                 const float ny = pElement->n.y;
00272 
00273                 const float c1 = (-nx * u0 * y - ny * (fy * z + v0 * y)) / zc;
00274                 const float c2 = (nx * (fx * z + u0 * x) + ny * v0 * x) / zc;
00275                 const float c3 = (-nx * fx * y + ny * fy * x) / zc;
00276                 const float c4 = (nx * fx) / zc;
00277                 const float c5 = (ny * fy) / zc;
00278                 const float c6 = (-nx * u0 - ny * v0) / zc;
00279 
00280                 const float l = pElement->l;
00281 
00282                 b.data[0] += l * c1;
00283                 b.data[1] += l * c2;
00284                 b.data[2] += l * c3;
00285                 b.data[3] += l * c4;
00286                 b.data[4] += l * c5;
00287                 b.data[5] += l * c6;
00288 
00289                 C(0, 0) = c1;
00290                 C(0, 1) = c2;
00291                 C(0, 2) = c3;
00292                 C(0, 3) = c4;
00293                 C(0, 4) = c5;
00294                 C(0, 5) = c6;
00295 
00296                 LinearAlgebra::Transpose(&C, &CT);
00297                 LinearAlgebra::MulMatMat(&C, &CT, &CTC);
00298                 LinearAlgebra::AddToMat(&A, &CTC);
00299         }
00300 
00301         CFloatVector q(6);
00302         LinearAlgebra::SolveLinearLeastSquaresSVD(&A, &b, &q);
00303 
00304         Vec3d delta_theta = { q.data[0], q.data[1], q.data[2] };
00305         Vec3d delta_t = { q.data[3], q.data[4], q.data[5] };
00306 
00307         // calculate new transformation consisting of rotation matrix R and translation vector t
00308         Vec3d *pPoints = new Vec3d[nPoints];
00309         Vec3d *pNewPoints = new Vec3d[nPoints];
00310 
00311         for (i = 0; i < nPoints; i++)
00312         {
00313                 CRAPiDElement *pElement = (CRAPiDElement *) elementList.GetElement(i);
00314 
00315                 Math3d::SetVec(pPoints[i], pElement->p);
00316 
00317                 Vec3d p;
00318                 Math3d::MulMatVec(R, pElement->p, p);
00319 
00320                 Vec3d temp;
00321                 Math3d::CrossProduct(delta_theta, p, temp);
00322                 Math3d::AddVecVec(p, temp, pNewPoints[i]);
00323                 Math3d::AddToVec(pNewPoints[i], delta_t);
00324                 Math3d::AddToVec(pNewPoints[i], t);
00325 
00326                 // transform back from camera coordinate system into world coordinate system
00327                 Math3d::MulMatVec(pCalibration->m_rotation_inverse, pNewPoints[i], pCalibration->m_translation_inverse, pNewPoints[i]);
00328         }
00329 
00330         // apply algorithm by Horn for calculating the optimal transformation
00331         CICP::CalculateOptimalTransformation(pPoints, pNewPoints, nPoints, rotation, translation);
00332 
00333         delete [] pPoints;
00334         delete [] pNewPoints;
00335 
00336         return true;
00337 }


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:58