RAPiD.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: RAPiD.cpp
37 // Author: Pedram Azad
38 // Date: 25.01.2008
39 // ****************************************************************************
40 
41 
42 // ****************************************************************************
43 // Includes
44 // ****************************************************************************
45 
46 #include <new> // for explicitly using correct new/delete operators on VC DSPs
47 
48 #include "RAPiD.h"
49 
50 #include "Math/FloatMatrix.h"
51 #include "Math/FloatVector.h"
52 #include "Math/LinearAlgebra.h"
55 #include "Image/ImageProcessor.h"
56 #include "Image/ByteImage.h"
57 #include "Tracking/ICP.h"
58 
59 #include <stdio.h>
60 
61 
62 // ****************************************************************************
63 // This is an implementation of the algorithm described in:
64 // C. Harris, "Tracking with rigid models", in "Active Vision",
65 // edited by A. Blake, pages 59-73, MIT Press, 1992.
66 // The Kalman filtering step is not implemented.
67 // ****************************************************************************
68 
69 
70 
71 // ****************************************************************************
72 // Constructor / Destructor
73 // ****************************************************************************
74 
76 {
78  m_nPixelsDelta = 15;
79 }
80 
82 {
83 }
84 
85 
86 // ****************************************************************************
87 // Methods
88 // ****************************************************************************
89 
90 void CRAPiD::Init(const CCalibration *pCalibration)
91 {
92  m_pCalibration = pCalibration;
93 }
94 
95 bool CRAPiD::Track(const CByteImage *pEdgeImage, Vec3d *pOutlinePoints, int nOutlinePoints,
96  Mat3d &rotation, Vec3d &translation)
97 {
98  if (pEdgeImage->type != CByteImage::eGrayScale)
99  {
100  printf("error: input image must be grayscale image for CRAPiD::Track\n");
101  return false;
102  }
103 
104  if (m_pCalibration->GetCameraParameters().width != pEdgeImage->width ||
106  {
107  printf("error: calibration does not match image in CRAPiD::Track\n");
108  return false;
109  }
110 
111  CDynamicArray rapidList(1000);
112 
113  const unsigned char *pixels = pEdgeImage->pixels;
114  const int width = pEdgeImage->width;
115  const int height = pEdgeImage->height;
116 
117  for (int i = 0; i < nOutlinePoints; i += 2)
118  {
119  Vec3d p1, p2;
120  Math3d::SetVec(p1, pOutlinePoints[i]);
121  Math3d::SetVec(p2, pOutlinePoints[i + 1]);
122 
123  Vec2d p1_, p2_;
124  {
125  Vec3d temp;
126 
127  Math3d::MulMatVec(rotation, p1, translation, temp);
128  m_pCalibration->WorldToImageCoordinates(temp, p1_, false);
129 
130  Math3d::MulMatVec(rotation, p2, translation, temp);
131  m_pCalibration->WorldToImageCoordinates(temp, p2_, false);
132  }
133 
134  const float length_ = Math2d::Distance(p1_, p2_);
135 
136  const int nControlPoints = int(length_ / m_nPixelsDelta) - 1;
137  if (nControlPoints < 1)
138  continue;
139 
140  Vec3d u;
141  Math3d::SubtractVecVec(p2, p1, u);
142  const float delta_length = Math3d::Length(u) / nControlPoints;
144  Math3d::MulVecScalar(u, delta_length, u);
145 
146  Vec2d u_ = { p1_.x - p2_.x, p1_.y - p2_.y };
148 
149  // calculate normal vector
150  Vec2d n = { p1_.y - p2_.y, p2_.x - p1_.x };
152 
153  Vec3d p;
154  Math3d::SetVec(p, p1);
155 
156  for (int j = 0; j < nControlPoints; j++)
157  {
158  Math3d::AddToVec(p, u);
159 
160  Vec2d p_;
161  {
162  Vec3d temp;
163  Math3d::MulMatVec(rotation, p, translation, temp);
164  m_pCalibration->WorldToImageCoordinates(temp, p_, false);
165  }
166 
167  // search in perpendicular direction
168  Vec2d pn1, pn2;
169  int k, l = -1;
170  bool bPlus = true;
171 
172  Math2d::SetVec(pn1, p_);
173  Math2d::SetVec(pn2, p_);
174  for (k = 0; k < m_nPixelsSearchDistance; k++)
175  {
176  int x, y;
177 
178  // can be optimized: checking boundaries within loop is slow but convenient
179  x = int(pn1.x + 0.5f);
180  y = int(pn1.y + 0.5f);
181  if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
182  {
183  l = k;
184  bPlus = true;
185  break;
186  }
187 
188  x = int(pn2.x + 0.5f);
189  y = int(pn2.y + 0.5f);
190  if (x > 0 && x < width && y > 0 && y < height && pixels[y * width + x])
191  {
192  l = k;
193  bPlus = false;
194  break;
195  }
196 
197  Math2d::AddToVec(pn1, n);
198  Math2d::SubtractFromVec(pn2, n);
199  }
200 
201  if (l != -1)
202  {
203  CRAPiDElement *pRAPiDElement = new CRAPiDElement();
204 
205  pRAPiDElement->l = float(l);
206  Math2d::SetVec(pRAPiDElement->n, n);
207  Math2d::NormalizeVec(pRAPiDElement->n);
208  Math3d::SetVec(pRAPiDElement->p, p);
209 
210  if (!bPlus)
211  Math2d::MulVecScalar(pRAPiDElement->n, -1, pRAPiDElement->n);
212 
213  rapidList.AddElement(pRAPiDElement);
214  }
215  }
216  }
217 
218  return RAPiD(rapidList, m_pCalibration, rotation, translation);
219 }
220 
221 bool CRAPiD::RAPiD(CDynamicArray &elementList, const CCalibration *pCalibration, Mat3d &rotation, Vec3d &translation)
222 {
223  if (elementList.GetSize() < 6)
224  {
225  printf("error: not enough input points for RAPiD::RAPiD\n");
226  return false;
227  }
228 
229  const CCalibration::CCameraParameters &cameraParameters = pCalibration->GetCameraParameters();
230  const float fx = cameraParameters.focalLength.x;
231  const float fy = cameraParameters.focalLength.y;
232 
233  Vec3d t;
234  Math3d::MulMatVec(cameraParameters.rotation, translation, cameraParameters.translation, t);
235 
236  Mat3d R;
237  Math3d::MulMatMat(cameraParameters.rotation, rotation, R);
238 
239  const int nPoints = elementList.GetSize();
240 
241  int i;
242 
243  CFloatMatrix A(6, 6);
245 
246  CFloatVector b(6);
247  b.data[0] = b.data[1] = b.data[2] = b.data[3] = b.data[4] = b.data[5] = 0;
248 
249  CFloatMatrix C(1, 6), CT(6, 1);
250  CFloatMatrix CTC(6, 6);
251 
252  for (i = 0; i < nPoints; i++)
253  {
254  CRAPiDElement *pElement = (CRAPiDElement *) elementList.GetElement(i);
255 
256  Vec3d p;
257  Math3d::MulMatVec(R, pElement->p, p);
258 
259  const float x = p.x;
260  const float y = p.y;
261  const float z = p.z;
262 
263  const float xc = x + t.x;
264  const float yc = y + t.y;
265  const float zc = z + t.z;
266 
267  const float u0 = fx * xc / zc;
268  const float v0 = fy * yc / zc;
269 
270  const float nx = pElement->n.x;
271  const float ny = pElement->n.y;
272 
273  const float c1 = (-nx * u0 * y - ny * (fy * z + v0 * y)) / zc;
274  const float c2 = (nx * (fx * z + u0 * x) + ny * v0 * x) / zc;
275  const float c3 = (-nx * fx * y + ny * fy * x) / zc;
276  const float c4 = (nx * fx) / zc;
277  const float c5 = (ny * fy) / zc;
278  const float c6 = (-nx * u0 - ny * v0) / zc;
279 
280  const float l = pElement->l;
281 
282  b.data[0] += l * c1;
283  b.data[1] += l * c2;
284  b.data[2] += l * c3;
285  b.data[3] += l * c4;
286  b.data[4] += l * c5;
287  b.data[5] += l * c6;
288 
289  C(0, 0) = c1;
290  C(0, 1) = c2;
291  C(0, 2) = c3;
292  C(0, 3) = c4;
293  C(0, 4) = c5;
294  C(0, 5) = c6;
295 
296  LinearAlgebra::Transpose(&C, &CT);
297  LinearAlgebra::MulMatMat(&C, &CT, &CTC);
298  LinearAlgebra::AddToMat(&A, &CTC);
299  }
300 
301  CFloatVector q(6);
303 
304  Vec3d delta_theta = { q.data[0], q.data[1], q.data[2] };
305  Vec3d delta_t = { q.data[3], q.data[4], q.data[5] };
306 
307  // calculate new transformation consisting of rotation matrix R and translation vector t
308  Vec3d *pPoints = new Vec3d[nPoints];
309  Vec3d *pNewPoints = new Vec3d[nPoints];
310 
311  for (i = 0; i < nPoints; i++)
312  {
313  CRAPiDElement *pElement = (CRAPiDElement *) elementList.GetElement(i);
314 
315  Math3d::SetVec(pPoints[i], pElement->p);
316 
317  Vec3d p;
318  Math3d::MulMatVec(R, pElement->p, p);
319 
320  Vec3d temp;
321  Math3d::CrossProduct(delta_theta, p, temp);
322  Math3d::AddVecVec(p, temp, pNewPoints[i]);
323  Math3d::AddToVec(pNewPoints[i], delta_t);
324  Math3d::AddToVec(pNewPoints[i], t);
325 
326  // transform back from camera coordinate system into world coordinate system
327  Math3d::MulMatVec(pCalibration->m_rotation_inverse, pNewPoints[i], pCalibration->m_translation_inverse, pNewPoints[i]);
328  }
329 
330  // apply algorithm by Horn for calculating the optimal transformation
331  CICP::CalculateOptimalTransformation(pPoints, pNewPoints, nPoints, rotation, translation);
332 
333  delete [] pPoints;
334  delete [] pNewPoints;
335 
336  return true;
337 }
~CRAPiD()
Definition: RAPiD.cpp:81
Struct containing all parameters of the camera model.
Definition: Calibration.h:133
Mat3d m_rotation_inverse
Rotation matrix of the inverted extrinsic transformation.
Definition: Calibration.h:443
GLdouble GLdouble t
Definition: glext.h:3219
GLdouble GLdouble z
Definition: glext.h:3343
void CrossProduct(const Vec3d &vector1, const Vec3d &vector2, Vec3d &result)
Definition: Math3d.cpp:564
float y
Definition: Math2d.h:84
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3235
int width
The width of the image in pixels.
Definition: ByteImage.h:257
GLenum GLsizei n
Definition: glext.h:4209
void AddToMat(CFloatMatrix *pMatrix, const CFloatMatrix *pMatrixToAdd)
CDynamicArrayElement * GetElement(int nElement)
Definition: DynamicArray.h:90
Data structure for the representation of a 3D vector.
Definition: Math3d.h:73
float x
Definition: Math3d.h:75
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80
float Length(const Vec3d &vec)
Definition: Math3d.cpp:585
GLfloat v0
Definition: glext.h:3530
void MulVecScalar(const Vec2d &vec, float scalar, Vec2d &result)
Definition: Math2d.cpp:142
void SolveLinearLeastSquaresSVD(const CFloatMatrix *A, const CFloatVector *b, CFloatVector *x)
float z
Definition: Math3d.h:75
unsigned char * pixels
The pointer to the the pixels.
Definition: ByteImage.h:283
void Init(const CCalibration *pCalibration)
Definition: RAPiD.cpp:90
bool AddElement(CDynamicArrayElement *pElement, bool bAddUniqueOnly=false, bool bManageMemory=true)
GLenum GLint x
Definition: glext.h:3125
const CCameraParameters & GetCameraParameters() const
Gives access to the camera parameters.
Definition: Calibration.h:268
float Distance(const Vec2d &vector1, const Vec2d &vector2)
Definition: Math2d.cpp:181
float x
Definition: Math2d.h:84
static bool RAPiD(CDynamicArray &elementList, const CCalibration *pCalibration, Mat3d &rotation, Vec3d &translation)
Definition: RAPiD.cpp:221
int m_nPixelsDelta
Definition: RAPiD.h:114
void SetVec(Vec3d &vec, float x, float y, float z)
Definition: Math3d.cpp:243
float y
Definition: Math3d.h:75
void MulVecScalar(const Vec3d &vec, float scalar, Vec3d &result)
Definition: Math3d.cpp:502
float * data
Definition: FloatVector.h:78
Data structure for the representation of a matrix of values of the data type float.
Definition: FloatMatrix.h:56
void AddVecVec(const Vec3d &vector1, const Vec3d &vector2, Vec3d &result)
Definition: Math3d.cpp:495
void MulMatMat(const Mat3d &matrix1, const Mat3d &matrix2, Mat3d &result)
Definition: Math3d.cpp:444
void AddToVec(Vec3d &vec, const Vec3d &vectorToAdd)
Definition: Math3d.cpp:481
static bool CalculateOptimalTransformation(const Vec3d *pSourcePoints, const Vec3d *pTargetPoints, int nPoints, Mat3d &rotation, Vec3d &translation)
Definition: ICP.cpp:300
void MulMatVec(const Mat3d &matrix, const Vec3d &vec, Vec3d &result)
Definition: Math3d.cpp:422
void NormalizeVec(Vec2d &vec)
Definition: Math2d.cpp:160
int m_nPixelsSearchDistance
Definition: RAPiD.h:115
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: glext.h:3154
int height
The height of the image in pixels.
Definition: ByteImage.h:264
void MulMatMat(const CFloatMatrix *A, const CFloatMatrix *B, CFloatMatrix *pResultMatrix, bool bTransposeB=false)
const CCalibration * m_pCalibration
Definition: RAPiD.h:112
int GetSize() const
Definition: DynamicArray.h:102
Vec3d m_translation_inverse
Translation vector of the inverted extrinsic transformation.
Definition: Calibration.h:454
GLubyte GLubyte b
Definition: glext.h:5166
CRAPiD()
Definition: RAPiD.cpp:75
GLfloat GLfloat GLfloat GLfloat nx
Definition: glext.h:5174
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
Data structure for the representation of a vector of values of the data type float.
Definition: FloatVector.h:53
ImageType type
The type of the image.
Definition: ByteImage.h:292
void NormalizeVec(Vec3d &vec)
Definition: Math3d.cpp:573
GLenum GLint GLint y
Definition: glext.h:3125
Data structure for the representation of a 2D vector.
Definition: Math2d.h:82
void SubtractVecVec(const Vec3d &vector1, const Vec3d &vector2, Vec3d &result)
Definition: Math3d.cpp:522
void Transpose(const CFloatMatrix *pMatrix, CFloatMatrix *pResultMatrix)
void SetVec(Vec2d &vec, float x, float y)
Definition: Math2d.cpp:68
GLfloat ny
Definition: glext.h:5172
void SubtractFromVec(Vec2d &vec, const Vec2d &vectorToSubtract)
Definition: Math2d.cpp:87
bool Track(const CByteImage *pEdgeImage, Vec3d *pOutlinePoints, int nOutlinePoints, Mat3d &rotation, Vec3d &translation)
Definition: RAPiD.cpp:95
void Zero(CByteImage *pImage, const MyRegion *pROI=0)
Sets all values in a CByteImage to zero.
GLfloat GLfloat p
Definition: glext.h:5178
Data structure for the representation of a 3x3 matrix.
Definition: Math3d.h:93
Camera model parameters and functions for a single camera.
Definition: Calibration.h:125
void WorldToImageCoordinates(const Vec3d &worldPoint, Vec2d &imagePoint, bool bUseDistortionParameters=true) const
Transforms 3D world coordinates to 2D image coordinates.


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