ColorICP.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "ColorICP.h"
25 
27 
28 // IVT
29 #include <cmath>
30 
32 
33 #include <DataStructures/KdTree/KdTree.h>
34 #include <Tracking/ICP.h>
35 
37 {
38  SetParameters();
39  m_pKdTree = new CKdTree();
40 
41  m_nNumScenePoints = 0;
42  m_pValues = new float*[1];
43 }
44 
46 {
47  delete m_pKdTree;
48 
49  for (int i = 0; i < m_nNumScenePoints; i++)
50  {
51  delete[] m_pValues[i];
52  }
53 
54  delete[] m_pValues;
55 }
56 
57 void
58 CColorICP::SetScenePointcloud(std::vector<CColorICP::CPointXYZRGBI> aScenePoints)
59 {
60  // clean up
61  m_aScenePoints.clear();
62 
63  for (int i = 0; i < m_nNumScenePoints; i++)
64  {
65  delete[] m_pValues[i];
66  }
67 
68  delete[] m_pValues;
69  delete m_pKdTree;
70 
71  // copy points
72  const int nSize = aScenePoints.size();
73 
74  for (int i = 0; i < nSize; i++)
75  {
76  m_aScenePoints.push_back(aScenePoints.at(i));
77  }
78 
79  m_pKdTree = new CKdTree(nSize);
80 
81  m_pValues = new float*[nSize];
82  m_nNumScenePoints = nSize;
83 
84  for (int i = 0; i < nSize; i++)
85  {
86  m_pValues[i] = new float[7];
87  m_pValues[i][0] = aScenePoints.at(i).x;
88  m_pValues[i][1] = aScenePoints.at(i).y;
89  m_pValues[i][2] = aScenePoints.at(i).z;
90  m_pValues[i][3] = m_fColorWeight * aScenePoints.at(i).r;
91  m_pValues[i][4] = m_fColorWeight * aScenePoints.at(i).g;
92  m_pValues[i][5] = m_fColorWeight * aScenePoints.at(i).b;
93  m_pValues[i][6] = m_fColorWeight * aScenePoints.at(i).i;
94  }
95 
96  bool bUseIntensity = OLP_EFFORT_POINTCLOUD_MATCHING > 0;
97 
98  if (bUseIntensity)
99  {
100  m_pKdTree->Build(m_pValues, 0, nSize - 1, m_nKdTreeBucketSize, 7, 0);
101  }
102  else
103  {
104  m_pKdTree->Build(m_pValues, 0, nSize - 1, m_nKdTreeBucketSize, 6, 1);
105  }
106 }
107 
108 float
109 CColorICP::SearchObject(const std::vector<CPointXYZRGBI>& aObjectPoints,
110  Mat3d& mRotation,
111  Vec3d& vTranslation,
112  const float fBestDistanceUntilNow)
113 {
114  Math3d::SetMat(mRotation, Math3d::unit_mat);
115  Math3d::SetVec(vTranslation, 0, 0, 0);
116 
117  if (aObjectPoints.size() < 3)
118  {
119  ARMARX_VERBOSE_S << "CColorICP::SearchObject: not enough object points!";
120  return FLT_MAX;
121  }
122 
123  if (m_aScenePoints.size() < 3)
124  {
125  ARMARX_WARNING_S << "CColorICP::SearchObject: not enough scene points!";
126  return FLT_MAX;
127  }
128 
129  float fLastDistance = FLT_MAX;
130  float fDistance = 0, fPointDistance;
131  Vec3d vPoint, vPointTransformed;
132  float* pPointData = new float[7];
133  float* pNearestNeighbor;
134  Vec3d* pPointPositions = new Vec3d[aObjectPoints.size()];
135  Vec3d* pCorrespondingPointPositions = new Vec3d[aObjectPoints.size()];
136  int nNumPointCorrespondences;
137 
138  // iterations of the ICP algorithm
139  for (int n = 0; n < m_nMaxIterations; n++)
140  {
141  fDistance = 0;
142  nNumPointCorrespondences = 0;
143 
144  // find nearest neighbor for each point in XYZRGB space
145  for (size_t i = 0; i < aObjectPoints.size(); i++)
146  {
147  Math3d::SetVec(
148  vPoint, aObjectPoints.at(i).x, aObjectPoints.at(i).y, aObjectPoints.at(i).z);
149  Math3d::MulMatVec(mRotation, vPoint, vTranslation, vPointTransformed);
150 
151  pPointData[0] = vPointTransformed.x;
152  pPointData[1] = vPointTransformed.y;
153  pPointData[2] = vPointTransformed.z;
154  pPointData[3] = m_fColorWeight * aObjectPoints.at(i).r;
155  pPointData[4] = m_fColorWeight * aObjectPoints.at(i).g;
156  pPointData[5] = m_fColorWeight * aObjectPoints.at(i).b;
157  pPointData[6] = m_fColorWeight * aObjectPoints.at(i).i;
158 
159  m_pKdTree->NearestNeighborBBF(pPointData, fPointDistance, pNearestNeighbor);
160  //FindNNBruteForce(pPointData, fPointDistance, pNearestNeighbor);
161 
162  fPointDistance = sqrtf(fPointDistance);
163 
164  // if (i%10==0)
165  // {
166  // ARMARX_WARNING_S << "(%.1f %.1f %.1f %.1f %.1f %.1f) , (%.1f %.1f %.1f %.1f %.1f %.1f) : %.1f\n",
167  // pPointData[0], pPointData[1], pPointData[2], pPointData[3], pPointData[4], pPointData[5],
168  // pNearestNeighbor[0], pNearestNeighbor[1], pNearestNeighbor[2], pNearestNeighbor[3], pNearestNeighbor[4], pNearestNeighbor[5], fPointDistance);
169  // }
170 
171  // if the correspondence is too far away, we ignore it in the estimation of the transformation
172  if (fPointDistance > m_fCutoffDistance)
173  {
174  fDistance += m_fCutoffDistance;
175  }
176  else
177  {
178  fDistance += fPointDistance;
179  Math3d::SetVec(pPointPositions[nNumPointCorrespondences], vPoint);
180  Math3d::SetVec(pCorrespondingPointPositions[nNumPointCorrespondences],
181  pNearestNeighbor[0],
182  pNearestNeighbor[1],
183  pNearestNeighbor[2]);
184  nNumPointCorrespondences++;
185  }
186  }
187 
188  if (nNumPointCorrespondences < 3)
189  {
190  ARMARX_IMPORTANT_S << "CColorICP::SearchObject: less than 3 correspondences found - no "
191  "transformation determined";
192  return FLT_MAX;
193  }
194 
195  // re-estimate the transformation between the two pointclouds using the correspondences
196  CICP::CalculateOptimalTransformation(pPointPositions,
197  pCorrespondingPointPositions,
198  nNumPointCorrespondences,
199  mRotation,
200  vTranslation);
201 
202 
203  // if the improvement is very small, finish
204 
205  if (0.8f * fDistance < fBestDistanceUntilNow)
206  {
207  // if it seems we might get a new best result, quit only if improvement is very very small
208  if (1.0f - fDistance / fLastDistance < 0.01f * m_fConvergenceDelta)
209  {
210  break;
211  }
212  }
213  else if ((1.0f - fDistance / fLastDistance < m_fConvergenceDelta) ||
214  (2 * n > m_nMaxIterations))
215  {
216  // otherwise quit if improvement is below threshold or already many iterations
217  break;
218  }
219  else if ((0.5f * fDistance > fBestDistanceUntilNow) && (3 * n > m_nMaxIterations))
220  {
221  // if we dont seem to get close to the best result, quit earlier
222  break;
223  }
224 
225  fLastDistance = fDistance;
226 
227  //ARMARX_WARNING_S << "%.1f ", fDistance/aObjectPoints.size());
228  }
229 
230  delete[] pPointData;
231  delete[] pPointPositions;
232  delete[] pCorrespondingPointPositions;
233 
234  return fDistance / aObjectPoints.size();
235 }
236 
237 void
238 CColorICP::SetParameters(float fColorWeight,
239  float fCutoffDistance,
240  float fConvergenceDelta,
241  int nMaxIterations,
242  int nKdTreeBucketSize)
243 {
244  m_fColorWeight = fColorWeight;
245  m_fCutoffDistance = fCutoffDistance;
246  m_fConvergenceDelta = fConvergenceDelta;
247  m_nMaxIterations = nMaxIterations;
248  m_nKdTreeBucketSize = nKdTreeBucketSize;
249 }
250 
251 void
252 CColorICP::FindNNBruteForce(const float* pPoint, float& fSquaredDistance, float*& pNeighbor)
253 {
254  float fMinDist = FLT_MAX;
255  float fDist;
256  int nBestIndex = -1;
257 
258  for (int i = 0; i < m_nNumScenePoints; i++)
259  {
260  fDist = 0;
261 
262  for (int j = 0; j < 6; j++)
263  {
264  fDist += (pPoint[j] - m_pValues[i][j]) * (pPoint[j] - m_pValues[i][j]);
265  }
266 
267  if (fDist < fMinDist)
268  {
269  fMinDist = fDist;
270  nBestIndex = i;
271  }
272  }
273 
274  fSquaredDistance = fMinDist;
275  pNeighbor = m_pValues[nBestIndex];
276 }
277 
278 void
279 CColorICP::GetPointMatchDistances(const std::vector<CPointXYZRGBI>& aObjectPoints,
280  std::vector<float>& aPointMatchDistances)
281 {
282  float* pPointData = new float[7];
283  float* pNearestNeighbor;
284  float fDistance;
285 
286  for (size_t i = 0; i < aObjectPoints.size(); i++)
287  {
288  pPointData[0] = aObjectPoints.at(i).x;
289  pPointData[1] = aObjectPoints.at(i).y;
290  pPointData[2] = aObjectPoints.at(i).z;
291  pPointData[3] = m_fColorWeight * aObjectPoints.at(i).r;
292  pPointData[4] = m_fColorWeight * aObjectPoints.at(i).g;
293  pPointData[5] = m_fColorWeight * aObjectPoints.at(i).b;
294  pPointData[6] = m_fColorWeight * aObjectPoints.at(i).i;
295 
296  m_pKdTree->NearestNeighborBBF(pPointData, fDistance, pNearestNeighbor);
297 
298  aPointMatchDistances.push_back(fDistance);
299  }
300 
301  delete[] pPointData;
302 }
303 
304 void
305 CColorICP::GetNearestNeighbors(const std::vector<CPointXYZRGBI>& aObjectPoints,
306  std::vector<CColorICP::CPointXYZRGBI>& aNeighbors,
307  std::vector<float>& aPointMatchDistances)
308 {
309  float* pPointData = new float[7];
310  float* pNearestNeighbor;
311  CColorICP::CPointXYZRGBI pNearestNeighborPoint;
312  float fDistance;
313  const float fColorWeightFactor = 1.0f / m_fColorWeight;
314 
315  for (size_t i = 0; i < aObjectPoints.size(); i++)
316  {
317  pPointData[0] = aObjectPoints.at(i).x;
318  pPointData[1] = aObjectPoints.at(i).y;
319  pPointData[2] = aObjectPoints.at(i).z;
320  pPointData[3] = m_fColorWeight * aObjectPoints.at(i).r;
321  pPointData[4] = m_fColorWeight * aObjectPoints.at(i).g;
322  pPointData[5] = m_fColorWeight * aObjectPoints.at(i).b;
323  pPointData[6] = m_fColorWeight * aObjectPoints.at(i).i;
324 
325  m_pKdTree->NearestNeighborBBF(pPointData, fDistance, pNearestNeighbor);
326 
327  pNearestNeighborPoint.x = pNearestNeighbor[0];
328  pNearestNeighborPoint.y = pNearestNeighbor[1];
329  pNearestNeighborPoint.z = pNearestNeighbor[2];
330  pNearestNeighborPoint.r = fColorWeightFactor * pNearestNeighbor[3];
331  pNearestNeighborPoint.g = fColorWeightFactor * pNearestNeighbor[4];
332  pNearestNeighborPoint.b = fColorWeightFactor * pNearestNeighbor[5];
333  pNearestNeighborPoint.i = fColorWeightFactor * pNearestNeighbor[6];
334 
335  aNeighbors.push_back(pNearestNeighborPoint);
336  aPointMatchDistances.push_back(fDistance);
337  }
338 
339  delete[] pPointData;
340 }
341 
344 {
346  ret.x = pPoint->vPosition.x;
347  ret.y = pPoint->vPosition.y;
348  ret.z = pPoint->vPosition.z;
349  ret.r = pPoint->fColorR;
350  ret.g = pPoint->fColorG;
351  ret.b = pPoint->fColorB;
352  ret.i = pPoint->fIntensity;
353 
354  return ret;
355 }
356 
359 {
360  CHypothesisPoint* pRet = new CHypothesisPoint();
362  Math3d::SetVec(pRet->vPosition, pPoint.x, pPoint.y, pPoint.z);
363  pRet->fColorR = pPoint.r;
364  pRet->fColorG = pPoint.g;
365  pRet->fColorB = pPoint.b;
366  pRet->fIntensity = pPoint.i;
367  pRet->fMembershipProbability = 0.8f;
368  return pRet;
369 }
370 
371 void
372 CColorICP::TransformPointXYZRGBI(CPointXYZRGBI& pPoint, Mat3d mRotation, Vec3d vTranslation)
373 {
374  const float x = pPoint.x;
375  const float y = pPoint.y;
376  const float z = pPoint.z;
377  pPoint.x = mRotation.r1 * x + mRotation.r2 * y + mRotation.r3 * z + vTranslation.x;
378  pPoint.y = mRotation.r4 * x + mRotation.r5 * y + mRotation.r6 * z + vTranslation.y;
379  pPoint.z = mRotation.r7 * x + mRotation.r8 * y + mRotation.r9 * z + vTranslation.z;
380 }
ARMARX_IMPORTANT_S
#define ARMARX_IMPORTANT_S
Definition: Logging.h:210
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:13
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:737
CColorICP::CColorICP
CColorICP()
Definition: ColorICP.cpp:36
CHypothesisPoint::fIntensity
float fIntensity
Definition: ObjectHypothesis.h:238
ColorICP.h
CColorICP::CPointXYZRGBI::x
float x
Definition: ColorICP.h:38
CColorICP::CPointXYZRGBI::y
float y
Definition: ColorICP.h:38
CHypothesisPoint::fColorG
float fColorG
Definition: ObjectHypothesis.h:238
CColorICP::GetPointMatchDistances
void GetPointMatchDistances(const std::vector< CPointXYZRGBI > &aObjectPoints, std::vector< float > &aPointMatchDistances)
Definition: ColorICP.cpp:279
CColorICP::SetScenePointcloud
void SetScenePointcloud(std::vector< CPointXYZRGBI > aScenePoints)
Definition: ColorICP.cpp:58
CColorICP::SetParameters
void SetParameters(float fColorWeight=OLP_ICP_COLOR_DISTANCE_WEIGHT, float fCutoffDistance=FLT_MAX, float fConvergenceDelta=0.01f, int nMaxIterations=30, int nKdTreeBucketSize=50)
Definition: ColorICP.cpp:238
CColorICP::SearchObject
float SearchObject(const std::vector< CPointXYZRGBI > &aObjectPoints, Mat3d &mRotation, Vec3d &vTranslation, const float fBestDistanceUntilNow=FLT_MAX)
Definition: ColorICP.cpp:109
CColorICP::CPointXYZRGBI::g
float g
Definition: ColorICP.h:38
CHypothesisPoint::vPosition
Vec3d vPosition
Definition: ObjectHypothesis.h:235
ObjectLearningByPushingDefinitions.h
CColorICP::CPointXYZRGBI::i
float i
Definition: ColorICP.h:38
CColorICP::CPointXYZRGBI::r
float r
Definition: ColorICP.h:38
CHypothesisPoint
Definition: ObjectHypothesis.h:166
OLP_EFFORT_POINTCLOUD_MATCHING
#define OLP_EFFORT_POINTCLOUD_MATCHING
Definition: ObjectLearningByPushingDefinitions.h:274
CColorICP::GetNearestNeighbors
void GetNearestNeighbors(const std::vector< CPointXYZRGBI > &aObjectPoints, std::vector< CColorICP::CPointXYZRGBI > &aNeighbors, std::vector< float > &aPointMatchDistances)
Definition: ColorICP.cpp:305
CColorICP::CPointXYZRGBI
Definition: ColorICP.h:36
CColorICP::CPointXYZRGBI::b
float b
Definition: ColorICP.h:38
CColorICP::~CColorICP
~CColorICP()
Definition: ColorICP.cpp:45
CHypothesisPoint::eDepthMapPoint
@ eDepthMapPoint
Definition: ObjectHypothesis.h:232
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:213
CHypothesisPoint::fColorR
float fColorR
Definition: ObjectHypothesis.h:238
CColorICP::ConvertToXYZRGBI
static CPointXYZRGBI ConvertToXYZRGBI(CHypothesisPoint *pPoint)
Definition: ColorICP.cpp:343
CHypothesisPoint::ePointType
EPointType ePointType
Definition: ObjectHypothesis.h:237
CColorICP::CPointXYZRGBI::z
float z
Definition: ColorICP.h:38
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
Logging.h
CHypothesisPoint::fColorB
float fColorB
Definition: ObjectHypothesis.h:238
CHypothesisPoint::fMembershipProbability
float fMembershipProbability
Definition: ObjectHypothesis.h:239
CColorICP::TransformPointXYZRGBI
static void TransformPointXYZRGBI(CPointXYZRGBI &pPoint, Mat3d mRotation, Vec3d vTranslation)
Definition: ColorICP.cpp:372
CColorICP::ConvertFromXYZRGBI
static CHypothesisPoint * ConvertFromXYZRGBI(CPointXYZRGBI pPoint)
Definition: ColorICP.cpp:358