KLTTracker.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:  KLTTracker.cpp
00037 // Author:    Pedram Azad
00038 // Date:      18.11.2009
00039 // ****************************************************************************
00040 
00041 
00042 // ****************************************************************************
00043 // Includes
00044 // ****************************************************************************
00045 
00046 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00047 
00048 #include "KLTTracker.h"
00049 
00050 #include "Image/ByteImage.h"
00051 #include "Image/ImageProcessor.h"
00052 #include "Math/Math2d.h"
00053 
00054 #include <stdio.h>
00055 #include <float.h>
00056 #include <math.h>
00057 
00058 
00059 // ****************************************************************************
00060 // Defines
00061 // ****************************************************************************
00062 
00063 #define KLT_ITERATIONS  20
00064 
00065 
00066 
00067 // ****************************************************************************
00068 // Constructor / Destructor
00069 // ****************************************************************************
00070 
00071 CKLTTracker::CKLTTracker(int width_, int height_, int nLevels, int nHalfWindowSize) : width(width_), height(height_), m_nLevels(nLevels), m_nHalfWindowSize(nHalfWindowSize)
00072 {
00073         m_ppPyramidI = new CByteImage*[nLevels + 1];
00074         m_ppPyramidJ = new CByteImage*[nLevels + 1];
00075         
00076         int w = width;
00077         int h = height;
00078         
00079         int i;
00080         
00081         // allocate pyramid images
00082         for (i = 0; i <= nLevels; i++)
00083         {
00084                 m_ppPyramidI[i] = new CByteImage(w, h, CByteImage::eGrayScale);
00085                 m_ppPyramidJ[i] = new CByteImage(w, h, CByteImage::eGrayScale);
00086                 
00087                 w /= 2;
00088                 h /= 2;
00089         }
00090         
00091         // precalculate scale factors
00092         m_pScaleFactors = new float[m_nLevels + 1];
00093         for (i = m_nLevels; i >= 0; i--)
00094                 m_pScaleFactors[i] = 1.0f / powf(2.0f, (float) i);
00095         
00096         m_bInitialized = false;
00097 }
00098 
00099 CKLTTracker::~CKLTTracker()
00100 {
00101         for (int i = 0; i <= m_nLevels; i++)
00102         {
00103                 delete m_ppPyramidI[i];
00104                 delete m_ppPyramidJ[i];
00105         }
00106         
00107         delete [] m_ppPyramidI;
00108         delete [] m_ppPyramidJ;
00109         
00110         delete [] m_pScaleFactors;
00111 }
00112 
00113 
00114 // ****************************************************************************
00115 // Methods
00116 // ****************************************************************************
00117 
00118 bool CKLTTracker::Track(const CByteImage *pImage, const Vec2d *pPoints, int nPoints, Vec2d *pResultPoints)
00119 {
00120         if (pImage->type != CByteImage::eGrayScale)
00121         {
00122                 printf("error: image must be of type eGrayScale for CKLTTracker::Track\n");
00123                 return false;
00124         }
00125         
00126         if (!m_bInitialized)
00127         {
00128                 // copy image to become level 0 of pyramid
00129                 ImageProcessor::CopyImage(pImage, m_ppPyramidI[0]);
00130                 
00131                 // compute levels 1 to m_nLevels - 1 of pyramid
00132                 for (int i = 1; i <= m_nLevels; i++)
00133                         ImageProcessor::Resize(m_ppPyramidI[i - 1], m_ppPyramidI[i]);
00134                 
00135                 m_bInitialized = true;
00136         }
00137         
00138         int i;
00139         
00140         // copy image to become level 0 of pyramid
00141         ImageProcessor::CopyImage(pImage, m_ppPyramidJ[0]);
00142         
00143         // compute levels 1 to m_nLevels - 1 of pyramid
00144         for (i = 1; i <= m_nLevels; i++)
00145                 ImageProcessor::Resize(m_ppPyramidJ[i - 1], m_ppPyramidJ[i]);
00146         
00147         const int nWindowSize = 2 * m_nHalfWindowSize + 1;
00148         const int nWindowSizePlus2 = nWindowSize + 2;
00149         
00150         Vec2d d;
00151         
00152         float *IX = new float[nWindowSizePlus2 * nWindowSizePlus2];
00153         float *IY = new float[nWindowSizePlus2 * nWindowSizePlus2];
00154         float *pGrayValues = new float[nWindowSizePlus2 * nWindowSizePlus2];
00155         
00156         // track each point
00157         for (i = 0; i < nPoints; i++)
00158         {
00159                 const float ux = pPoints[i].x;
00160                 const float uy = pPoints[i].y;
00161                 
00162                 if (ux < 0.0f && uy < 0.0f)
00163                 {
00164                         Math2d::SetVec(pResultPoints[i], -1.0f, -1.0f);
00165                         continue;
00166                 }
00167                 
00168                 Vec2d g = { 0.0f, 0.0f };
00169                 
00170                 for (int l = m_nLevels; l >= 0; l--)
00171                 {
00172                         const int w = m_ppPyramidI[l]->width;
00173                         const int h = m_ppPyramidI[l]->height;
00174                         
00175                         const float px_ = m_pScaleFactors[l] * ux;
00176                         const float py_ = m_pScaleFactors[l] * uy;
00177                         
00178                         const int px = int(floorf(px_));
00179                         const int py = int(floorf(py_));
00180                         
00181                         if (px - m_nHalfWindowSize < 1 || px + m_nHalfWindowSize + 3 > w || py - m_nHalfWindowSize < 1 || py + m_nHalfWindowSize + 3 > h)
00182                         {
00183                                 Math2d::MulVecScalar(g, 2.0f, g);
00184                                 continue;
00185                         }
00186                         
00187                         const unsigned char *pixelsI = m_ppPyramidI[l]->pixels;
00188                         
00189                         {
00190                                 const int diff = w - nWindowSizePlus2;
00191                                 
00192                                 const float dx = px_ - floorf(px_);
00193                                 const float dy = py_ - floorf(py_);
00194                                 
00195                                 const float f00 = (1.0f - dx) * (1.0f - dy);
00196                                 const float f10 = dx * (1.0f - dy);
00197                                 const float f01 = (1.0f - dx) * dy;
00198                                 const float f11 = dx * dy;
00199                                 
00200                                 for (int j = nWindowSizePlus2, offset = (py - m_nHalfWindowSize - 1) * w + px - m_nHalfWindowSize - 1, offset2 = 0; j; j--, offset += diff)
00201                                         for (int jj = nWindowSizePlus2; jj; jj--, offset++, offset2++)
00202                                                 pGrayValues[offset2] = f00 * pixelsI[offset] + f10 * pixelsI[offset + 1] + f01 * pixelsI[offset + w] + f11 * pixelsI[offset + w + 1];
00203                         }
00204                         
00205                         float gxx = 0.0f, gxy = 0.0f, gyy = 0.0f;
00206                         
00207                         for (int j = nWindowSize, offset = nWindowSizePlus2 + 1; j; j--, offset += 2)
00208                                 for (int jj = nWindowSize; jj; jj--, offset++)
00209                                 {
00210                                         const float ix = pGrayValues[offset + 1] - pGrayValues[offset - 1];
00211                                         const float iy = pGrayValues[offset + nWindowSizePlus2] - pGrayValues[offset - nWindowSizePlus2];
00212                                         
00213                                         IX[offset] = ix;
00214                                         IY[offset] = iy;
00215                                         
00216                                         gxx += ix * ix;
00217                                         gyy += iy * iy;
00218                                         gxy += ix * iy;
00219                                 }
00220                         
00221                         Vec2d v = { 0.0f, 0.0f };
00222                         
00223                         if (fabsf(gxx * gyy - gxy * gxy) > FLT_EPSILON) // determinant check
00224                         {
00225                                 const Mat2d G = { gxx, gxy, gxy, gyy };
00226                                 Mat2d G_;
00227                                 Math2d::Invert(G, G_);
00228                                 
00229                                 const unsigned char *pixelsJ = m_ppPyramidJ[l]->pixels;
00230                                 
00231                                 for (int k = 0; k < KLT_ITERATIONS; k++)
00232                                 {
00233                                         const float dxJ = g.x + v.x;
00234                                         const float dyJ = g.y + v.y;
00235                                         
00236                                         const int xb = int(floorf(px_ + dxJ));
00237                                         const int yb = int(floorf(py_ + dyJ));
00238                                         
00239                                         if (xb - m_nHalfWindowSize < 1 || xb + m_nHalfWindowSize + 3 >= w || yb - m_nHalfWindowSize < 1 || yb + m_nHalfWindowSize + 3 >= h)
00240                                                 break;
00241                                         
00242                                         float bx = 0.0f, by = 0.0f;
00243                                         
00244                                         {
00245                                                 const int diff = w - nWindowSize;
00246                                                 
00247                                                 const float dx = px_ + dxJ - floorf(px_ + dxJ);
00248                                                 const float dy = py_ + dyJ - floorf(py_ + dyJ);
00249                                                 
00250                                                 const float f00 = (1.0f - dx) * (1.0f - dy);
00251                                                 const float f10 = dx * (1.0f - dy);
00252                                                 const float f01 = (1.0f - dx) * dy;
00253                                                 const float f11 = dx * dy;
00254                                                 
00255                                                 for (int j = nWindowSize, offset = (yb - m_nHalfWindowSize) * w + xb - m_nHalfWindowSize, offset2 = nWindowSizePlus2 + 1; j; j--, offset += diff, offset2 += 2)
00256                                                         for (int jj = nWindowSize; jj; jj--, offset++, offset2++)
00257                                                         {
00258                                                                 const float dI = pGrayValues[offset2] - (f00 * pixelsJ[offset] + f10 * pixelsJ[offset + 1] + f01 * pixelsJ[offset + w] + f11 * pixelsJ[offset + w + 1]);
00259                                                                 
00260                                                                 bx += IX[offset2] * dI;
00261                                                                 by += IY[offset2] * dI;
00262                                                         }
00263                                         }
00264                                         
00265                                         const Vec2d b = { bx, by };
00266                                         
00267                                         Vec2d n;
00268                                         Math2d::MulMatVec(G_, b, n);
00269                                         
00270                                         Math2d::MulVecScalar(n, 2.0f, n); // take into account leaving out factor 0.5 for gradient computation
00271                                         
00272                                         Math2d::AddToVec(v, n);
00273                                         
00274                                         if (Math2d::SquaredLength(n) < 0.03f)
00275                                                 break;
00276                                 }
00277                         }
00278                         
00279                         Math2d::SetVec(d, v);
00280                         
00281                         if (l != 0)
00282                         {
00283                                 g.x = 2.0f * (g.x + d.x);
00284                                 g.y = 2.0f * (g.y + d.y);
00285                         }
00286                 }
00287                 
00288                 Math2d::AddToVec(d, g);
00289                 
00290                 const float x = ux + d.x;
00291                 const float y = uy + d.y;
00292                 
00293                 const int x_ = int(floorf(x));
00294                 const int y_ = int(floorf(y));
00295                 
00296                 if (x_ > m_nHalfWindowSize && x_ < width - m_nHalfWindowSize - 3 && y_ > m_nHalfWindowSize && y_ < height - m_nHalfWindowSize - 3)
00297                         Math2d::SetVec(pResultPoints[i], x, y);
00298                 else
00299                         Math2d::SetVec(pResultPoints[i], -1.0f, -1.0f);
00300         }
00301         
00302         // swap pyramids
00303         CByteImage **ppTemp = m_ppPyramidI;
00304         m_ppPyramidI = m_ppPyramidJ;
00305         m_ppPyramidJ = ppTemp;
00306         
00307         // free memory
00308         delete [] IX;
00309         delete [] IY;
00310         delete [] pGrayValues;
00311         
00312         return true;
00313 }
00314 


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