Tracker2d3d.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:  Tracker2d3d.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 "Tracker2d3d.h"
00049 
00050 #include "Math/FloatMatrix.h"
00051 #include "Math/FloatVector.h"
00052 #include "Math/LinearAlgebra.h"
00053 #include "Math/Math2d.h"
00054 #include "Math/Math3d.h"
00055 #include "Calibration/Calibration.h"
00056 #include "Image/ImageProcessor.h"
00057 #include "Image/ByteImage.h"
00058 #include "Tracking/ObjectPose.h"
00059 
00060 #include <stdio.h>
00061 
00062 
00063 // ****************************************************************************
00064 // This is a simple (and only partly) implementation of the algorithm
00065 // described in:
00066 // E. Marchand, P. Bouthemy, F. Chaumette, and V. Moreau,
00067 // "Robust Real-Time Visual Tracking using a 2D-3D Model-based Approach",
00068 // in Proc. of International Conference on Computer Vision (ICCV),
00069 // pages 262-268, 1999.
00070 // ****************************************************************************
00071 
00072 
00073 
00074 // ****************************************************************************
00075 // Constructor / Destructor
00076 // ****************************************************************************
00077 
00078 CTracker2d3d::CTracker2d3d()
00079 {
00080         m_nPixelsSearchDistance = 15;
00081         m_nPixelsDelta = 15;
00082 }
00083 
00084 CTracker2d3d::~CTracker2d3d()
00085 {
00086 }
00087 
00088 
00089 // ****************************************************************************
00090 // Methods
00091 // ****************************************************************************
00092 
00093 void CTracker2d3d::Init(const CCalibration *pCalibration)
00094 {
00095         m_pCalibration = pCalibration;
00096 }
00097 
00098 bool CTracker2d3d::Track(const CByteImage *pEdgeImage, Vec3d *pOutlinePoints, int nOutlinePoints,
00099                    Mat3d &rotation, Vec3d &translation)
00100 {
00101         if (pEdgeImage->type != CByteImage::eGrayScale)
00102         {
00103                 printf("error: input image must be grayscale image for CTracker2d3d::Track\n");
00104                 return false;
00105         }
00106 
00107         if (m_pCalibration->GetCameraParameters().width != pEdgeImage->width ||
00108                 m_pCalibration->GetCameraParameters().height != pEdgeImage->height)
00109         {
00110                 printf("error: calibration does not match image in CTracker2d3d::Track\n");
00111                 return false;
00112         }
00113 
00114         const int nMaxPoints = 10000;
00115 
00116         Vec3d *pPointList3d = new Vec3d[nMaxPoints];
00117         Vec2d *pPointList2dProjection = new Vec2d[nMaxPoints];
00118         Vec2d *pPointList2d = new Vec2d[nMaxPoints];
00119 
00120         const unsigned char *pixels = pEdgeImage->pixels;
00121         const int width = pEdgeImage->width;
00122         const int height = pEdgeImage->height;
00123 
00124         Mat3d A;
00125         Math3d::SetMat(A, Math3d::unit_mat);
00126 
00127         int nPoints;
00128 
00129         for (int nRun = 0;; nRun++)
00130         {
00131                 int i;
00132                 nPoints = 0;
00133 
00134                 for (i = 0; i < nOutlinePoints; i += 2)
00135                 {
00136                         Vec3d p1, p2;
00137                         Math3d::SetVec(p1, pOutlinePoints[i]);
00138                         Math3d::SetVec(p2, pOutlinePoints[i + 1]);
00139 
00140                         Vec2d p1_, p2_;
00141                         {
00142                                 Vec3d temp;
00143                                 
00144                                 Math3d::MulMatVec(rotation, p1, translation, temp);
00145                                 m_pCalibration->WorldToImageCoordinates(temp, p1_, false);
00146 
00147                                 Math3d::MulMatVec(rotation, p2, translation, temp);
00148                                 m_pCalibration->WorldToImageCoordinates(temp, p2_, false);
00149 
00150                                 Math3d::SetVec(temp, p1_.x, p1_.y, 1);
00151                                 Math3d::MulMatVec(A, temp, temp);
00152                                 p1_.x = temp.x / temp.z;
00153                                 p1_.y = temp.y / temp.z;
00154 
00155                                 Math3d::SetVec(temp, p2_.x, p2_.y, 1);
00156                                 Math3d::MulMatVec(A, temp, temp);
00157                                 p2_.x = temp.x / temp.z;
00158                                 p2_.y = temp.y / temp.z;
00159                         }
00160 
00161                         const float length_ = Math2d::Distance(p1_, p2_);
00162 
00163                         const int nControlPoints = int(length_ / m_nPixelsDelta) - 1;
00164                         if (nControlPoints < 1 || nControlPoints > 10000)
00165                                 continue;
00166 
00167                         Vec3d u;
00168                         Math3d::SubtractVecVec(p2, p1, u);
00169                         const float delta_length = Math3d::Length(u) / nControlPoints;
00170                         Math3d::NormalizeVec(u);
00171                         Math3d::MulVecScalar(u, delta_length, u);
00172 
00173                         Vec2d u_ = { p1_.x - p2_.x, p1_.y - p2_.y };
00174                         Math2d::NormalizeVec(u_);
00175 
00176                         // calculate normal vector
00177                         Vec2d n = { p1_.y - p2_.y, p2_.x - p1_.x };
00178                         Math2d::NormalizeVec(n);
00179                         
00180                         Vec3d p;
00181                         Math3d::SetVec(p, p1);
00182 
00183                         for (int j = 0; j < nControlPoints; j++)
00184                         {
00185                                 Math3d::AddToVec(p, u);
00186 
00187                                 Vec2d p_;
00188                                 {
00189                                         Vec3d temp;
00190                                         Vec2d temp2;
00191 
00192                                         Math3d::MulMatVec(rotation, p, translation, temp);
00193                                         m_pCalibration->WorldToImageCoordinates(temp, temp2, false);
00194 
00195                                         Vec3d temp3 = { temp2.x, temp2.y, 1 };
00196 
00197                                         Math3d::MulMatVec(A, temp3, temp3);             
00198 
00199                                         p_.x = temp3.x / temp3.z;
00200                                         p_.y = temp3.y / temp3.z;
00201                                 }
00202 
00203                                 // search in perpendicular direction
00204                                 Vec2d pn1, pn2;
00205                                 int k, l = -1;
00206                                 bool bPlus = true;
00207 
00208                                 Math2d::SetVec(pn1, p_);
00209                                 Math2d::SetVec(pn2, p_);
00210                                 for (k = 0; k < m_nPixelsSearchDistance; k++)
00211                                 {
00212                                         int x, y;
00213 
00214                                         // can be optimized: checking boundaries within loop is slow but convenient
00215                                         x = int(pn1.x + 0.5f);
00216                                         y = int(pn1.y + 0.5f);
00217                                         if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
00218                                         {
00219                                                 l = k;
00220                                                 bPlus = true;
00221                                                 break;
00222                                         }
00223 
00224                                         x = int(pn2.x + 0.5f);
00225                                         y = int(pn2.y + 0.5f);
00226                                         if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
00227                                         {
00228                                                 l = k;
00229                                                 bPlus = false;
00230                                                 break;
00231                                         }
00232 
00233                                         Math2d::AddToVec(pn1, n);
00234                                         Math2d::SubtractFromVec(pn2, n);
00235                                 }
00236 
00237                                 if (l != -1)
00238                                 {
00239                                         Math3d::SetVec(pPointList3d[nPoints], p);
00240                                         Math2d::SetVec(pPointList2dProjection[nPoints], p_);
00241 
00242                                         if (bPlus)
00243                                         {
00244                                                 Math2d::SetVec(pPointList2d[nPoints], pn1);
00245                                         }       
00246                                         else
00247                                         {
00248                                                 Math2d::SetVec(pPointList2d[nPoints], pn2);
00249                                         }
00250 
00251                                         if (++nPoints == nMaxPoints)
00252                                                 break;
00253                                 }
00254                         }
00255                 }
00256 
00257                 if (nPoints < 6)
00258                         return false;
00259 
00260                 if (nRun == 4)
00261                 {
00262                         // end after five runs
00263                         break;
00264                 }
00265 
00266                 Mat3d A_;
00267                 LinearAlgebra::DetermineAffineTransformation(pPointList2dProjection, pPointList2d, nPoints, A_);
00268                 Math3d::MulMatMat(A_, A, A);
00269         }
00270 
00271         CObjectPose objectPose(pPointList3d, nPoints);
00272         objectPose.EstimatePose(pPointList2d, rotation, translation, m_pCalibration);
00273         
00274         delete [] pPointList3d;
00275         delete [] pPointList2d;
00276         delete [] pPointList2dProjection;
00277         
00278         return true;
00279 }


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