KLTTracker.cpp
Go to the documentation of this file.
1 // ****************************************************************************
2 // This file is part of the Integrating Vision Toolkit (IVT).
3 //
4 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
5 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
6 //
7 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // 3. Neither the name of the KIT nor the names of its contributors may be
21 // used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
28 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // ****************************************************************************
35 // ****************************************************************************
36 // Filename: KLTTracker.cpp
37 // Author: Pedram Azad
38 // Date: 18.11.2009
39 // ****************************************************************************
40 
41 
42 // ****************************************************************************
43 // Includes
44 // ****************************************************************************
45 
46 #include <new> // for explicitly using correct new/delete operators on VC DSPs
47 
48 #include "KLTTracker.h"
49 
50 #include "Image/ByteImage.h"
51 #include "Image/ImageProcessor.h"
52 #include "Math/Math2d.h"
53 
54 #include <stdio.h>
55 #include <float.h>
56 #include <math.h>
57 
58 
59 // ****************************************************************************
60 // Defines
61 // ****************************************************************************
62 
63 #define KLT_ITERATIONS 20
64 
65 
66 
67 // ****************************************************************************
68 // Constructor / Destructor
69 // ****************************************************************************
70 
71 CKLTTracker::CKLTTracker(int width_, int height_, int nLevels, int nHalfWindowSize) : width(width_), height(height_), m_nLevels(nLevels), m_nHalfWindowSize(nHalfWindowSize)
72 {
73  m_ppPyramidI = new CByteImage*[nLevels + 1];
74  m_ppPyramidJ = new CByteImage*[nLevels + 1];
75 
76  int w = width;
77  int h = height;
78 
79  int i;
80 
81  // allocate pyramid images
82  for (i = 0; i <= nLevels; i++)
83  {
86 
87  w /= 2;
88  h /= 2;
89  }
90 
91  // precalculate scale factors
92  m_pScaleFactors = new float[m_nLevels + 1];
93  for (i = m_nLevels; i >= 0; i--)
94  m_pScaleFactors[i] = 1.0f / powf(2.0f, (float) i);
95 
96  m_bInitialized = false;
97 }
98 
100 {
101  for (int i = 0; i <= m_nLevels; i++)
102  {
103  delete m_ppPyramidI[i];
104  delete m_ppPyramidJ[i];
105  }
106 
107  delete [] m_ppPyramidI;
108  delete [] m_ppPyramidJ;
109 
110  delete [] m_pScaleFactors;
111 }
112 
113 
114 // ****************************************************************************
115 // Methods
116 // ****************************************************************************
117 
118 bool CKLTTracker::Track(const CByteImage *pImage, const Vec2d *pPoints, int nPoints, Vec2d *pResultPoints)
119 {
120  if (pImage->type != CByteImage::eGrayScale)
121  {
122  printf("error: image must be of type eGrayScale for CKLTTracker::Track\n");
123  return false;
124  }
125 
126  if (!m_bInitialized)
127  {
128  // copy image to become level 0 of pyramid
130 
131  // compute levels 1 to m_nLevels - 1 of pyramid
132  for (int i = 1; i <= m_nLevels; i++)
134 
135  m_bInitialized = true;
136  }
137 
138  int i;
139 
140  // copy image to become level 0 of pyramid
142 
143  // compute levels 1 to m_nLevels - 1 of pyramid
144  for (i = 1; i <= m_nLevels; i++)
146 
147  const int nWindowSize = 2 * m_nHalfWindowSize + 1;
148  const int nWindowSizePlus2 = nWindowSize + 2;
149 
150  Vec2d d;
151 
152  float *IX = new float[nWindowSizePlus2 * nWindowSizePlus2];
153  float *IY = new float[nWindowSizePlus2 * nWindowSizePlus2];
154  float *pGrayValues = new float[nWindowSizePlus2 * nWindowSizePlus2];
155 
156  // track each point
157  for (i = 0; i < nPoints; i++)
158  {
159  const float ux = pPoints[i].x;
160  const float uy = pPoints[i].y;
161 
162  if (ux < 0.0f && uy < 0.0f)
163  {
164  Math2d::SetVec(pResultPoints[i], -1.0f, -1.0f);
165  continue;
166  }
167 
168  Vec2d g = { 0.0f, 0.0f };
169 
170  for (int l = m_nLevels; l >= 0; l--)
171  {
172  const int w = m_ppPyramidI[l]->width;
173  const int h = m_ppPyramidI[l]->height;
174 
175  const float px_ = m_pScaleFactors[l] * ux;
176  const float py_ = m_pScaleFactors[l] * uy;
177 
178  const int px = int(floorf(px_));
179  const int py = int(floorf(py_));
180 
181  if (px - m_nHalfWindowSize < 1 || px + m_nHalfWindowSize + 3 > w || py - m_nHalfWindowSize < 1 || py + m_nHalfWindowSize + 3 > h)
182  {
183  Math2d::MulVecScalar(g, 2.0f, g);
184  continue;
185  }
186 
187  const unsigned char *pixelsI = m_ppPyramidI[l]->pixels;
188 
189  {
190  const int diff = w - nWindowSizePlus2;
191 
192  const float dx = px_ - floorf(px_);
193  const float dy = py_ - floorf(py_);
194 
195  const float f00 = (1.0f - dx) * (1.0f - dy);
196  const float f10 = dx * (1.0f - dy);
197  const float f01 = (1.0f - dx) * dy;
198  const float f11 = dx * dy;
199 
200  for (int j = nWindowSizePlus2, offset = (py - m_nHalfWindowSize - 1) * w + px - m_nHalfWindowSize - 1, offset2 = 0; j; j--, offset += diff)
201  for (int jj = nWindowSizePlus2; jj; jj--, offset++, offset2++)
202  pGrayValues[offset2] = f00 * pixelsI[offset] + f10 * pixelsI[offset + 1] + f01 * pixelsI[offset + w] + f11 * pixelsI[offset + w + 1];
203  }
204 
205  float gxx = 0.0f, gxy = 0.0f, gyy = 0.0f;
206 
207  for (int j = nWindowSize, offset = nWindowSizePlus2 + 1; j; j--, offset += 2)
208  for (int jj = nWindowSize; jj; jj--, offset++)
209  {
210  const float ix = pGrayValues[offset + 1] - pGrayValues[offset - 1];
211  const float iy = pGrayValues[offset + nWindowSizePlus2] - pGrayValues[offset - nWindowSizePlus2];
212 
213  IX[offset] = ix;
214  IY[offset] = iy;
215 
216  gxx += ix * ix;
217  gyy += iy * iy;
218  gxy += ix * iy;
219  }
220 
221  Vec2d v = { 0.0f, 0.0f };
222 
223  if (fabsf(gxx * gyy - gxy * gxy) > FLT_EPSILON) // determinant check
224  {
225  const Mat2d G = { gxx, gxy, gxy, gyy };
226  Mat2d G_;
227  Math2d::Invert(G, G_);
228 
229  const unsigned char *pixelsJ = m_ppPyramidJ[l]->pixels;
230 
231  for (int k = 0; k < KLT_ITERATIONS; k++)
232  {
233  const float dxJ = g.x + v.x;
234  const float dyJ = g.y + v.y;
235 
236  const int xb = int(floorf(px_ + dxJ));
237  const int yb = int(floorf(py_ + dyJ));
238 
239  if (xb - m_nHalfWindowSize < 1 || xb + m_nHalfWindowSize + 3 >= w || yb - m_nHalfWindowSize < 1 || yb + m_nHalfWindowSize + 3 >= h)
240  break;
241 
242  float bx = 0.0f, by = 0.0f;
243 
244  {
245  const int diff = w - nWindowSize;
246 
247  const float dx = px_ + dxJ - floorf(px_ + dxJ);
248  const float dy = py_ + dyJ - floorf(py_ + dyJ);
249 
250  const float f00 = (1.0f - dx) * (1.0f - dy);
251  const float f10 = dx * (1.0f - dy);
252  const float f01 = (1.0f - dx) * dy;
253  const float f11 = dx * dy;
254 
255  for (int j = nWindowSize, offset = (yb - m_nHalfWindowSize) * w + xb - m_nHalfWindowSize, offset2 = nWindowSizePlus2 + 1; j; j--, offset += diff, offset2 += 2)
256  for (int jj = nWindowSize; jj; jj--, offset++, offset2++)
257  {
258  const float dI = pGrayValues[offset2] - (f00 * pixelsJ[offset] + f10 * pixelsJ[offset + 1] + f01 * pixelsJ[offset + w] + f11 * pixelsJ[offset + w + 1]);
259 
260  bx += IX[offset2] * dI;
261  by += IY[offset2] * dI;
262  }
263  }
264 
265  const Vec2d b = { bx, by };
266 
267  Vec2d n;
268  Math2d::MulMatVec(G_, b, n);
269 
270  Math2d::MulVecScalar(n, 2.0f, n); // take into account leaving out factor 0.5 for gradient computation
271 
272  Math2d::AddToVec(v, n);
273 
274  if (Math2d::SquaredLength(n) < 0.03f)
275  break;
276  }
277  }
278 
279  Math2d::SetVec(d, v);
280 
281  if (l != 0)
282  {
283  g.x = 2.0f * (g.x + d.x);
284  g.y = 2.0f * (g.y + d.y);
285  }
286  }
287 
288  Math2d::AddToVec(d, g);
289 
290  const float x = ux + d.x;
291  const float y = uy + d.y;
292 
293  const int x_ = int(floorf(x));
294  const int y_ = int(floorf(y));
295 
296  if (x_ > m_nHalfWindowSize && x_ < width - m_nHalfWindowSize - 3 && y_ > m_nHalfWindowSize && y_ < height - m_nHalfWindowSize - 3)
297  Math2d::SetVec(pResultPoints[i], x, y);
298  else
299  Math2d::SetVec(pResultPoints[i], -1.0f, -1.0f);
300  }
301 
302  // swap pyramids
303  CByteImage **ppTemp = m_ppPyramidI;
305  m_ppPyramidJ = ppTemp;
306 
307  // free memory
308  delete [] IX;
309  delete [] IY;
310  delete [] pGrayValues;
311 
312  return true;
313 }
314 
GLubyte g
Definition: glext.h:5166
const int width
Definition: KLTTracker.h:83
float y
Definition: Math2d.h:84
int width
The width of the image in pixels.
Definition: ByteImage.h:257
GLenum GLsizei n
Definition: glext.h:4209
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80
float * m_pScaleFactors
Definition: KLTTracker.h:80
void MulVecScalar(const Vec2d &vec, float scalar, Vec2d &result)
Definition: Math2d.cpp:142
GLintptr offset
Definition: glext.h:3389
CKLTTracker(int width, int height, int nLevels, int nHalfWindowSize)
Definition: KLTTracker.cpp:71
unsigned char * pixels
The pointer to the the pixels.
Definition: ByteImage.h:283
const int height
Definition: KLTTracker.h:83
CByteImage ** m_ppPyramidI
Definition: KLTTracker.h:79
const int m_nHalfWindowSize
Definition: KLTTracker.h:82
GLenum GLint x
Definition: glext.h:3125
float x
Definition: Math2d.h:84
#define KLT_ITERATIONS
Definition: KLTTracker.cpp:63
Data structure for the representation of a 2x2 matrix.
Definition: Math2d.h:101
bool Track(const CByteImage *pImage, const Vec2d *pPoints, int nPoints, Vec2d *pResultPoints)
Definition: KLTTracker.cpp:118
bool CopyImage(const CByteImage *pInputImage, CByteImage *pOutputImage, const MyRegion *pROI=0, bool bUseSameSize=false)
Copies one CByteImage to another.
bool m_bInitialized
Definition: KLTTracker.h:84
int height
The height of the image in pixels.
Definition: ByteImage.h:264
void Invert(const Mat2d &matrix, Mat2d &result)
Definition: Math2d.cpp:238
GLubyte GLubyte b
Definition: glext.h:5166
GLenum GLsizei width
Definition: glext.h:3122
GLenum GLsizei GLsizei height
Definition: glext.h:3132
void AddToVec(Vec2d &vec, const Vec2d &vectorToAdd)
Definition: Math2d.cpp:81
ImageType type
The type of the image.
Definition: ByteImage.h:292
GLenum GLint GLint y
Definition: glext.h:3125
const GLdouble * v
Definition: glext.h:3212
GLbyte by
Definition: glext.h:5042
Data structure for the representation of a 2D vector.
Definition: Math2d.h:82
CByteImage ** m_ppPyramidJ
Definition: KLTTracker.h:79
void SetVec(Vec2d &vec, float x, float y)
Definition: Math2d.cpp:68
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3571
float SquaredLength(const Vec2d &vec)
Definition: Math2d.cpp:176
void MulMatVec(const Mat2d &matrix, const Vec2d &vec, Vec2d &result)
Definition: Math2d.cpp:128
bool Resize(const CByteImage *pInputImage, CByteImage *pOutputImage, const MyRegion *pROI=0, bool bInterpolation=true)
Resizes a CByteImage and writes the result to a CByteImage.
const int m_nLevels
Definition: KLTTracker.h:81


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Mon Dec 2 2019 03:47:28