OLPTools.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 "OLPTools.h"
25 #include "ObjectHypothesis.h"
26 
27 
28 // IVT
29 #include <Calibration/StereoCalibration.h>
30 #include <Calibration/Calibration.h>
31 #include <Image/ByteImage.h>
32 #include <Image/ImageProcessor.h>
33 
34 // OpenCV
35 #include <opencv2/opencv.hpp>
36 
37 
39 
40 
41 
42 namespace COLPTools
43 {
44  void InterpolateRotation(const Mat3d m1, const Mat3d m2, const float fWeight, Mat3d& mResult)
45  {
46  Mat3d mTemp1, mTemp2;
47  Vec3d vTemp;
48  float fRotationAngle;
49  Math3d::Transpose(m1, mTemp1);
50  Math3d::MulMatMat(m2, mTemp1, mTemp2);
51  Math3d::GetAxisAndAngle(mTemp2, vTemp, fRotationAngle);
52 
53  if (Math3d::ScalarProduct(vTemp, vTemp) < 0.9f) // rotation matrices are identical
54  {
55  Math3d::SetMat(mResult, m1);
56  }
57  else
58  {
59  Math3d::SetRotationMatAxis(mTemp1, vTemp, fWeight * fRotationAngle);
60  Math3d::MulMatMat(mTemp1, m1, mResult);
61  }
62  }
63 
64 
65 
66 
67  void InterpolateTransformation(const Mat3d m1, const Vec3d v1, const Mat3d m2, const Vec3d v2, const float fWeight, Mat3d& mResult, Vec3d& vResult)
68  {
69  InterpolateRotation(m1, m2, fWeight, mResult);
70  Math3d::AddVecVec(v1, v2, vResult);
71  Math3d::MulVecScalar(vResult, fWeight, vResult);
72  }
73 
74 
75 
76  void ClusterXMeans(const std::vector<CHypothesisPoint*>& aPoints, const int nMinNumClusters, const int nMaxNumClusters, const float fBICFactor, std::vector<std::vector<CHypothesisPoint*> >& aaPointClusters)
77  {
78  std::vector<Vec3d> aPointsVec3d;
79  std::vector<std::vector<Vec3d> > aaPointClustersVec3d;
80  std::vector<std::vector<int> > aaOldIndices;
81 
82  for (size_t i = 0; i < aPoints.size(); i++)
83  {
84  aPointsVec3d.push_back(aPoints.at(i)->vPosition);
85  }
86 
87  // call pure 3D point clustering
88  ClusterXMeans(aPointsVec3d, nMinNumClusters, nMaxNumClusters, fBICFactor, aaPointClustersVec3d, aaOldIndices);
89 
90  //ARMARX_VERBOSE_S << "%ld clusters\n", aaPointClustersVec3d.size());
91 
92  // put hypothesis points into clusters according to the indices obtained from the pure 3D point clustering
93  aaPointClusters.clear();
94 
95  for (size_t i = 0; i < aaOldIndices.size(); i++)
96  {
97  std::vector<CHypothesisPoint*> aNewCluster;
98  aaPointClusters.push_back(aNewCluster);
99  }
100 
101  for (size_t i = 0; i < aaOldIndices.size(); i++)
102  {
103  for (size_t j = 0; j < aaOldIndices.at(i).size(); j++)
104  {
105  aaPointClusters.at(i).push_back(aPoints.at(aaOldIndices.at(i).at(j))->GetCopy());
106  }
107  }
108  }
109 
110 
111 
112 
113  void ClusterXMeans(const std::vector<Vec3d>& aPoints, const int nMinNumClusters, const int nMaxNumClusters, const float fBICFactor, std::vector<std::vector<Vec3d> >& aaPointClusters, std::vector<std::vector<int> >& aaOldIndices)
114  {
115  cv::Mat mSamples;
116  cv::Mat mClusterLabels;
117  const int nNumberOfDifferentInitialisations = 7; // 5
118  cv::TermCriteria tTerminationCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 50, 0.01);
119 
120  // copy the points
121  const int nNumberOfSamples = aPoints.size();
122  mSamples.create(nNumberOfSamples, 3, CV_32FC1);
123 
124  for (int i = 0; i < nNumberOfSamples; i++)
125  {
126  mSamples.at<float>(i, 0) = aPoints.at(i).x;
127  mSamples.at<float>(i, 1) = aPoints.at(i).y;
128  mSamples.at<float>(i, 2) = aPoints.at(i).z;
129  }
130 
131  mClusterLabels.create(nNumberOfSamples, 1, CV_32SC1);
132 
133  // execute k-means for several values of k and find the value for k that minimises the
134  // Bayesian Information Criterion (BIC)
135  double dMinBIC = FLT_MAX;
136  int nOptK = nMinNumClusters;
137  const int nMaxNumClustersSafe = (10 * nMaxNumClusters < nNumberOfSamples) ? nMaxNumClusters : nNumberOfSamples / 10;
138 
139  #pragma omp parallel for schedule(dynamic, 1)
140  for (int i = nMaxNumClustersSafe; i >= nMinNumClusters; i--)
141  {
142  // maybe we need to make parallel instances of mClusterLabels
143 #ifdef OLP_USE_NEW_OPENCV
144  cv::kmeans(mSamples, i, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_RANDOM_CENTERS);
145 #else
146  cv::Mat mClusterCenters;
147  cv::kmeans(mSamples, i, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_PP_CENTERS, &mClusterCenters);
148 #endif
149  double dLogVar, dBIC;
150  Vec3d* pvClusterMeans = new Vec3d[nMaxNumClusters];
151  double* pdClusterVariances = new double[nMaxNumClusters];
152  int* pnClusterSizes = new int[nMaxNumClusters];
153 
154  // calculate variances of the clusters
155  double dMLVariance = 0;
156 
157  for (int j = 0; j < i; j++)
158  {
159  pvClusterMeans[j].x = 0;
160  pvClusterMeans[j].y = 0;
161  pvClusterMeans[j].z = 0;
162  pdClusterVariances[j] = 0;
163  pnClusterSizes[j] = 0;
164 
165  for (int l = 0; l < nNumberOfSamples; l++)
166  {
167  if (mClusterLabels.at<int>(l, 0) == j)
168  {
169  pvClusterMeans[j].x += mSamples.at<float>(l, 0);
170  pvClusterMeans[j].y += mSamples.at<float>(l, 1);
171  pvClusterMeans[j].z += mSamples.at<float>(l, 2);
172  pnClusterSizes[j]++;
173  }
174  }
175 
176  pvClusterMeans[j].x /= (float)pnClusterSizes[j];
177  pvClusterMeans[j].y /= (float)pnClusterSizes[j];
178  pvClusterMeans[j].z /= (float)pnClusterSizes[j];
179 
180  for (int l = 0; l < nNumberOfSamples; l++)
181  {
182  if (mClusterLabels.at<int>(l, 0) == j)
183  {
184  pdClusterVariances[j] += (pvClusterMeans[j].x - mSamples.at<float>(l, 0)) * (pvClusterMeans[j].x - mSamples.at<float>(l, 0))
185  + (pvClusterMeans[j].y - mSamples.at<float>(l, 1)) * (pvClusterMeans[j].x - mSamples.at<float>(l, 1))
186  + (pvClusterMeans[j].z - mSamples.at<float>(l, 2)) * (pvClusterMeans[j].x - mSamples.at<float>(l, 2));
187  }
188  }
189 
190  if (pnClusterSizes[j] > 1)
191  {
192  pdClusterVariances[j] /= (float)(pnClusterSizes[j] - 1);
193  }
194  else
195  {
196  pdClusterVariances[j] = 0;
197  }
198 
199  dMLVariance += pdClusterVariances[j];
200  }
201 
202  const int nNumberOfFreeParameters = (i - 1) + (3 * i) + i;
203  //dLogVar = log(dMLVariance);
204  dLogVar = log(dMLVariance / i);
205  dBIC = fBICFactor * 0.35 * dLogVar + ((double)nNumberOfFreeParameters / (double)nNumberOfSamples) * log((double)nNumberOfSamples); // 0.4 // 1.5 with manual variance
206 
207  #pragma omp critical
208  {
209  if (dBIC < dMinBIC)
210  {
211  dMinBIC = dBIC;
212  nOptK = i;
213  }
214  }
215 
216  delete[] pvClusterMeans;
217  delete[] pdClusterVariances;
218  delete[] pnClusterSizes;
219 
220  //ARMARX_VERBOSE_S << "k-means with " << i << " clusters. log(var): " << dLogVar << " BIC: " << dBIC;
221  }
222 
223  // execute k-means with optimal k
224  if (nOptK > 1)
225  {
226 #ifdef OLP_USE_NEW_OPENCV
227  double dKMeansCompactness = cv::kmeans(mSamples, nOptK, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_RANDOM_CENTERS);
228 #else
229  cv::Mat mClusterCenters;
230  double dKMeansCompactness = cv::kmeans(mSamples, nOptK, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_PP_CENTERS, &mClusterCenters);
231 #endif
232 
233  // copy the points belonging to the clusters
234  Vec3d vPoint;
235  aaPointClusters.clear();
236  aaOldIndices.clear();
237 
238  for (int i = 0; i < nOptK; i++)
239  {
240  std::vector<Vec3d> aNewCluster;
241  aaPointClusters.push_back(aNewCluster);
242  std::vector<int> aClusterIndices;
243  aaOldIndices.push_back(aClusterIndices);
244  }
245 
246  for (int i = 0; i < nNumberOfSamples; i++)
247  {
248  const int nLabel = mClusterLabels.at<int>(i, 0);
249 
250  if ((nLabel >= 0) && (nLabel < nOptK))
251  {
252  vPoint.x = mSamples.at<float>(i, 0);
253  vPoint.y = mSamples.at<float>(i, 1);
254  vPoint.z = mSamples.at<float>(i, 2);
255  aaPointClusters.at(nLabel).push_back(vPoint);
256  aaOldIndices.at(nLabel).push_back(i);
257  }
258  else
259  {
260  ARMARX_WARNING_S << "Invalid cluster label: " << nLabel << "nOptK: " << nOptK << ", i: " << i << ", nNumberOfSamples: " << nNumberOfSamples << ", dKMeansCompactness: " << dKMeansCompactness;
261  break;
262  }
263  }
264  }
265  else
266  {
267  aaPointClusters.clear();
268  std::vector<Vec3d> aNewCluster;
269  aaPointClusters.push_back(aNewCluster);
270  aaOldIndices.clear();
271  std::vector<int> aClusterIndices;
272  aaOldIndices.push_back(aClusterIndices);
273  Vec3d vPoint;
274 
275  for (int i = 0; i < nNumberOfSamples; i++)
276  {
277  vPoint.x = mSamples.at<float>(i, 0);
278  vPoint.y = mSamples.at<float>(i, 1);
279  vPoint.z = mSamples.at<float>(i, 2);
280  aaPointClusters.at(0).push_back(vPoint);
281  aaOldIndices.at(0).push_back(i);
282  }
283  }
284  }
285 
286 
287 
288 
289  void FilterForegroundPoints(const std::vector<CHypothesisPoint*>& aAllPoints, const CByteImage* pForegroundImage, const CCalibration* calibration, std::vector<CHypothesisPoint*>& aForegroundPoints)
290  {
291  Vec2d vImagePoint;
292 
293  for (size_t i = 0; i < aAllPoints.size(); i++)
294  {
295  calibration->WorldToImageCoordinates(aAllPoints.at(i)->vPosition, vImagePoint, false);
296  const int nIndex = ((int)vImagePoint.y) * OLP_IMG_WIDTH + (int)vImagePoint.x;
297 
298  if ((nIndex >= 0) && (nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT))
299  {
300  if (pForegroundImage->pixels[nIndex] > 0)
301  {
302  aForegroundPoints.push_back(aAllPoints.at(i)->GetCopy());
303  }
304  }
305  }
306  }
307 
308 
309 
310  bool PointIsInForeground(const Vec3d vPoint, const CByteImage* pForegroundImage, const CCalibration* calibration)
311  {
312  Vec2d vImagePoint;
313  calibration->WorldToImageCoordinates(vPoint, vImagePoint, false);
314  const int nIndex = ((int)vImagePoint.y) * OLP_IMG_WIDTH + (int)vImagePoint.x;
315 
316  if ((nIndex >= 0) && (nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT))
317  {
318  return (pForegroundImage->pixels[nIndex] > 0);
319  }
320  else
321  {
322  return false;
323  }
324  }
325 
326 
327  bool PointIsInForeground(const CHypothesisPoint* pPoint, const CByteImage* pForegroundImage, const CCalibration* calibration)
328  {
329  return PointIsInForeground(pPoint->vPosition, pForegroundImage, calibration);
330  }
331 
332 
333 
334 
335 
336  void CalculateForegroundRatioOfHypothesis(const CObjectHypothesis* pHypothesis, const CByteImage* pForegroundImage, const CCalibration* calibration, float& fForegroundRatio, int& nNumForegroundPixels)
337  {
338  // get the 2D points
339  int nNumPoints;
340  Vec2d* pPoints2D;
341 
342  if (pHypothesis->aVisibleConfirmedPoints.size() > OLP_MIN_NUM_FEATURES)
343  {
344  nNumPoints = pHypothesis->aVisibleConfirmedPoints.size();
345  pPoints2D = new Vec2d[nNumPoints];
346 
347  for (int i = 0; i < nNumPoints; i++)
348  {
349  calibration->WorldToImageCoordinates(pHypothesis->aVisibleConfirmedPoints.at(i)->vPosition, pPoints2D[i], false);
350  }
351  }
352  else
353  {
354  nNumPoints = pHypothesis->aVisibleConfirmedPoints.size() + pHypothesis->aNewPoints.size();
355  pPoints2D = new Vec2d[nNumPoints];
356 
357  for (size_t i = 0; i < pHypothesis->aNewPoints.size(); i++)
358  {
359  calibration->WorldToImageCoordinates(pHypothesis->aNewPoints.at(i)->vPosition, pPoints2D[i], false);
360  }
361 
362  for (size_t i = 0; i < pHypothesis->aVisibleConfirmedPoints.size(); i++)
363  {
364  calibration->WorldToImageCoordinates(pHypothesis->aVisibleConfirmedPoints.at(i)->vPosition, pPoints2D[pHypothesis->aNewPoints.size() + i], false);
365  }
366  }
367 
368  int nNumForegroundPoints = 0;
369  long nForegroundSum = 0;
370 
371  for (int i = 0; i < nNumPoints; i++)
372  {
373  int nIndex = (OLP_IMG_WIDTH * (int)pPoints2D[i].y) + (int)pPoints2D[i].x;
374 
375  if ((nIndex > 0) && (nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT))
376  {
377  nForegroundSum += pForegroundImage->pixels[nIndex];
378 
379  if (pForegroundImage->pixels[nIndex] > 0)
380  {
381  nNumForegroundPoints++;
382  }
383  }
384  }
385 
386  nNumForegroundPixels = nNumForegroundPoints;
387  fForegroundRatio = (double)nForegroundSum / ((double)nNumPoints * 255.0);
388 
389 
390  /*
391  // calculate foreground ratio of enclosing rectangle
392 
393  // get enclosing rectangle
394  Vec2d p1, p2, p3, p4;
395  bool bRotated;
396  GetEnclosingRectangle(pPoints2d, nNumPoints, true, p1, p2, p3, p4, bRotated);
397 
398  // make sure points are within image
399  p1.x = (p1.x < 0) ? 0 : p1.x;
400  p1.x = (p1.x > OLP_IMG_WIDTH-1) ? OLP_IMG_WIDTH-1 : p1.x;
401  p1.y = (p1.y < 0) ? 0 : p1.y;
402  p1.y = (p1.y > OLP_IMG_HEIGHT-1) ? OLP_IMG_HEIGHT-1 : p1.y;
403  p2.x = (p2.x < 0) ? 0 : p2.x;
404  p2.x = (p2.x > OLP_IMG_WIDTH-1) ? OLP_IMG_WIDTH-1 : p2.x;
405  p2.y = (p2.y < 0) ? 0 : p2.y;
406  p2.y = (p2.y > OLP_IMG_HEIGHT-1) ? OLP_IMG_HEIGHT-1 : p2.y;
407  p3.x = (p3.x < 0) ? 0 : p3.x;
408  p3.x = (p3.x > OLP_IMG_WIDTH-1) ? OLP_IMG_WIDTH-1 : p3.x;
409  p3.y = (p3.y < 0) ? 0 : p3.y;
410  p3.y = (p3.y > OLP_IMG_HEIGHT-1) ? OLP_IMG_HEIGHT-1 : p3.y;
411  p4.x = (p4.x < 0) ? 0 : p4.x;
412  p4.x = (p4.x > OLP_IMG_WIDTH-1) ? OLP_IMG_WIDTH-1 : p4.x;
413  p4.y = (p4.y < 0) ? 0 : p4.y;
414  p4.y = (p4.y > OLP_IMG_HEIGHT-1) ? OLP_IMG_HEIGHT-1 : p4.y;
415 
416  // count the foreground pixels in the rectangle
417  if (!bRotated)
418  {
419  const int nMinX = (int)p1.x;
420  const int nMaxX = (int)p2.x;
421  const int nMinY = (int)p1.y;
422  const int nMaxY = (int)p3.y;
423 
424  int nForegroundSum = 0;
425  for (int i=nMinY; i<=nMaxY; i++)
426  {
427  for (int j=nMinX; j<nMaxX; j++)
428  {
429  nForegroundSum += pForegroundImage->pixels[i*OLP_IMG_WIDTH+j];
430  }
431  }
432  nNumForegroundPixels = nForegroundSum / 255;
433  fForegroundRatio = (float)nNumForegroundPixels / (float)((nMaxX-nMinX)*(nMaxY-nMinY));
434  }
435  else
436  {
437  // x ~ (x+y), y ~ (-x+y) =>
438  // p1 is (min, middle), p2 is (middle, min), p3 is (max, middle), p4 is (middle, max)
439  nNumForegroundPixels = CountForegroundPixelsInRectangle(p2, p1, p3, p4, pForegroundImage);
440  fForegroundRatio = (float)nNumForegroundPixels / ((p3.x-p1.x)*(p4.y-p2.y));
441  }
442  */
443 
444  delete[] pPoints2D;
445  }
446 
447 
448 
449 
450  void GetEnclosingRectangle(const Vec2d* pPoints, const int nNumPoints, const bool bUseSecondMaxPoints, Vec2d& p1, Vec2d& p2, Vec2d& p3, Vec2d& p4, bool& bRotated)
451  {
452  // calculate axis-parallel enclosing rectangle
453  float fMinX = pPoints[0].x;
454  float fMaxX = pPoints[0].x;
455  float fMinY = pPoints[0].y;
456  float fMaxY = pPoints[0].y;
457  float fSecondMinX = pPoints[0].x;
458  float fSecondMaxX = pPoints[0].x;
459  float fSecondMinY = pPoints[0].y;
460  float fSecondMaxY = pPoints[0].y;
461 
462  for (int i = 0; i < nNumPoints; i++)
463  {
464  if (pPoints[i].x < fMinX)
465  {
466  fSecondMinX = fMinX;
467  fMinX = pPoints[i].x;
468  }
469  else if (pPoints[i].x < fSecondMinX)
470  {
471  fSecondMinX = pPoints[i].x;
472  }
473 
474  if (pPoints[i].x > fMaxX)
475  {
476  fSecondMaxX = fMaxX;
477  fMaxX = pPoints[i].x;
478  }
479  else if (pPoints[i].x > fSecondMaxX)
480  {
481  fSecondMaxX = pPoints[i].x;
482  }
483 
484  if (pPoints[i].y < fMinY)
485  {
486  fSecondMinY = fMinY;
487  fMinY = pPoints[i].y;
488  }
489  else if (pPoints[i].y < fSecondMinY)
490  {
491  fSecondMinY = pPoints[i].y;
492  }
493 
494  if (pPoints[i].y > fMaxY)
495  {
496  fSecondMaxY = fMaxY;
497  fMaxY = pPoints[i].y;
498  }
499  else if (pPoints[i].y > fSecondMaxY)
500  {
501  fSecondMaxY = pPoints[i].y;
502  }
503  }
504 
505  // calculate rectangle that is rotated by 45 degrees
506  Vec2d* pRotatedPoints = new Vec2d[nNumPoints];
507 
508  for (int i = 0; i < nNumPoints; i++)
509  {
510  pRotatedPoints[i].x = pPoints[i].x - pPoints[i].y;
511  pRotatedPoints[i].y = pPoints[i].x + pPoints[i].y;
512  }
513 
514  float fMinXr = pRotatedPoints[0].x;
515  float fMaxXr = pRotatedPoints[0].x;
516  float fMinYr = pRotatedPoints[0].y;
517  float fMaxYr = pRotatedPoints[0].y;
518  float fSecondMinXr = pRotatedPoints[0].x;
519  float fSecondMaxXr = pRotatedPoints[0].x;
520  float fSecondMinYr = pRotatedPoints[0].y;
521  float fSecondMaxYr = pRotatedPoints[0].y;
522 
523  for (int i = 0; i < nNumPoints; i++)
524  {
525  if (pRotatedPoints[i].x < fMinXr)
526  {
527  fSecondMinXr = fMinXr;
528  fMinXr = pRotatedPoints[i].x;
529  }
530  else if (pRotatedPoints[i].x < fSecondMinXr)
531  {
532  fSecondMinXr = pRotatedPoints[i].x;
533  }
534 
535  if (pRotatedPoints[i].x > fMaxXr)
536  {
537  fSecondMaxXr = fMaxXr;
538  fMaxXr = pRotatedPoints[i].x;
539  }
540  else if (pRotatedPoints[i].x > fSecondMaxXr)
541  {
542  fSecondMaxXr = pRotatedPoints[i].x;
543  }
544 
545  if (pRotatedPoints[i].y < fMinYr)
546  {
547  fSecondMinYr = fMinYr;
548  fMinYr = pRotatedPoints[i].y;
549  }
550  else if (pRotatedPoints[i].y < fSecondMinYr)
551  {
552  fSecondMinYr = pRotatedPoints[i].y;
553  }
554 
555  if (pRotatedPoints[i].y > fMaxYr)
556  {
557  fSecondMaxYr = fMaxYr;
558  fMaxYr = pRotatedPoints[i].y;
559  }
560  else if (pRotatedPoints[i].y > fSecondMaxYr)
561  {
562  fSecondMaxYr = pRotatedPoints[i].y;
563  }
564  }
565 
566  const float fSqrt2Fact = 0.5f * sqrtf(2.0f);
567  fMinXr *= fSqrt2Fact;
568  fMaxXr *= fSqrt2Fact;
569  fMinYr *= fSqrt2Fact;
570  fMaxYr *= fSqrt2Fact;
571  fSecondMinXr *= fSqrt2Fact;
572  fSecondMaxXr *= fSqrt2Fact;
573  fSecondMinYr *= fSqrt2Fact;
574  fSecondMaxYr *= fSqrt2Fact;
575 
576  if (bUseSecondMaxPoints)
577  {
578  // choose the rectangle with the smaller volume
579  if ((fSecondMaxX - fSecondMinX) * (fSecondMaxY - fSecondMinY) < (fSecondMaxXr - fSecondMinXr) * (fSecondMaxYr - fSecondMinYr))
580  {
581  bRotated = false;
582  Math2d::SetVec(p1, fSecondMinX, fSecondMinY);
583  Math2d::SetVec(p2, fSecondMaxX, fSecondMinY);
584  Math2d::SetVec(p3, fSecondMaxX, fSecondMaxY);
585  Math2d::SetVec(p4, fSecondMinX, fSecondMaxY);
586  }
587  else
588  {
589  bRotated = true;
590  Math2d::SetVec(p1, fSqrt2Fact * (fSecondMinXr + fSecondMinYr), fSqrt2Fact * (-fSecondMinXr + fSecondMinYr));
591  Math2d::SetVec(p2, fSqrt2Fact * (fSecondMaxXr + fSecondMinYr), fSqrt2Fact * (-fSecondMaxXr + fSecondMinYr));
592  Math2d::SetVec(p3, fSqrt2Fact * (fSecondMaxXr + fSecondMaxYr), fSqrt2Fact * (-fSecondMaxXr + fSecondMaxYr));
593  Math2d::SetVec(p4, fSqrt2Fact * (fSecondMinXr + fSecondMaxYr), fSqrt2Fact * (-fSecondMinXr + fSecondMaxYr));
594  }
595  }
596  else
597  {
598  // choose the rectangle with the smaller volume
599  if ((fMaxX - fMinX) * (fMaxY - fMinY) < (fMaxXr - fMinXr) * (fMaxYr - fMinYr))
600  {
601  bRotated = false;
602  Math2d::SetVec(p1, fMinX, fMinY);
603  Math2d::SetVec(p2, fMaxX, fMinY);
604  Math2d::SetVec(p3, fMaxX, fMaxY);
605  Math2d::SetVec(p4, fMinX, fMaxY);
606  }
607  else
608  {
609  bRotated = true;
610  Math2d::SetVec(p1, fSqrt2Fact * (fMinXr + fMinYr), fSqrt2Fact * (-fMinXr + fMinYr));
611  Math2d::SetVec(p2, fSqrt2Fact * (fMaxXr + fMinYr), fSqrt2Fact * (-fMaxXr + fMinYr));
612  Math2d::SetVec(p3, fSqrt2Fact * (fMaxXr + fMaxYr), fSqrt2Fact * (-fMaxXr + fMaxYr));
613  Math2d::SetVec(p4, fSqrt2Fact * (fMinXr + fMaxYr), fSqrt2Fact * (-fMinXr + fMaxYr));
614  }
615  }
616 
617  delete[] pRotatedPoints;
618  }
619 
620 
621  int CountForegroundPixelsInRectangle(const Vec2d vMiddleMin, const Vec2d vMinMiddle, const Vec2d vMaxMiddle, const Vec2d vMiddleMax, const CByteImage* pForegroundImage)
622  {
623  int nStartY = (int)vMiddleMin.y;
624  int nEndY = (int)vMiddleMax.y;
625  int nMiddleY1, nMiddleY2;
626  float fDeltaLeft1, fDeltaLeft2, fDeltaLeft3, fDeltaRight1, fDeltaRight2, fDeltaRight3;
627 
628  int nSum = 0;
629 
630  // check if left or right corner comes first
631  if (vMinMiddle.y < vMaxMiddle.y)
632  {
633  nMiddleY1 = (int)vMinMiddle.y;
634  nMiddleY2 = (int)vMaxMiddle.y;
635  fDeltaLeft1 = (vMinMiddle.x - vMiddleMin.x) / (vMinMiddle.y - vMiddleMin.y);
636  fDeltaLeft2 = (vMiddleMax.x - vMinMiddle.x) / (vMiddleMax.y - vMinMiddle.y);
637  fDeltaLeft3 = fDeltaLeft2;
638  fDeltaRight1 = (vMaxMiddle.x - vMiddleMin.x) / (vMaxMiddle.y - vMiddleMin.y);
639  fDeltaRight2 = fDeltaRight1;
640  fDeltaRight3 = (vMiddleMax.x - vMaxMiddle.x) / (vMiddleMax.y - vMaxMiddle.y);
641  }
642  else
643  {
644  nMiddleY1 = (int)vMaxMiddle.y;
645  nMiddleY2 = (int)vMinMiddle.y;
646  fDeltaLeft1 = (vMinMiddle.x - vMiddleMin.x) / (vMinMiddle.y - vMiddleMin.y);
647  fDeltaLeft2 = fDeltaLeft1;
648  fDeltaLeft3 = (vMiddleMax.x - vMinMiddle.x) / (vMiddleMax.y - vMinMiddle.y);
649  fDeltaRight1 = (vMaxMiddle.x - vMiddleMin.x) / (vMaxMiddle.y - vMiddleMin.y);
650  fDeltaRight2 = (vMiddleMax.x - vMaxMiddle.x) / (vMiddleMax.y - vMaxMiddle.y);
651  fDeltaRight3 = fDeltaRight2;
652  }
653 
654  float fLeft = vMiddleMin.x;
655  float fRight = vMiddleMin.x;
656 
657  // go from start to first corner
658  for (int i = nStartY; i < nMiddleY1; i++)
659  {
660  for (int j = (int)fLeft; j <= (int)fRight; j++)
661  {
662  nSum += pForegroundImage->pixels[i * OLP_IMG_WIDTH + j];
663  }
664 
665  fLeft += fDeltaLeft1;
666  fRight += fDeltaRight1;
667  }
668 
669  // first corner to second corner
670  for (int i = nMiddleY1; i < nMiddleY2; i++)
671  {
672  for (int j = (int)fLeft; j <= (int)fRight; j++)
673  {
674  nSum += pForegroundImage->pixels[i * OLP_IMG_WIDTH + j];
675  }
676 
677  fLeft += fDeltaLeft2;
678  fRight += fDeltaRight2;
679  }
680 
681  // second corner to end
682  for (int i = nMiddleY2; i < nEndY; i++)
683  {
684  for (int j = (int)fLeft; j <= (int)fRight; j++)
685  {
686  nSum += pForegroundImage->pixels[i * OLP_IMG_WIDTH + j];
687  }
688 
689  fLeft += fDeltaLeft3;
690  fRight += fDeltaRight3;
691  }
692 
693  return nSum / 255;
694  }
695 
696 
697 
698 
699  void GetMeanAndVariance(const std::vector<CHypothesisPoint*>& pHypothesisPoints, Vec3d& vMean, float& fVariance)
700  {
701  std::vector<Vec3d> aPoints3d;
702 
703  for (size_t i = 0; i < pHypothesisPoints.size(); i++)
704  {
705  aPoints3d.push_back(pHypothesisPoints.at(i)->vPosition);
706  }
707 
708  GetMeanAndVariance(aPoints3d, vMean, fVariance);
709  }
710 
711 
712 
713 
714  void GetMeanAndVariance(const std::vector<Vec3d>& aPoints, Vec3d& vMean, float& fVariance)
715  {
716  vMean.x = 0;
717  vMean.y = 0;
718  vMean.z = 0;
719  fVariance = 0;
720 
721  const int nNumPoints = aPoints.size();
722 
723  if (nNumPoints > 0)
724  {
725  const float fNumPointsInv = 1.0f / (float)nNumPoints;
726 
727  // calculate mean
728  for (int i = 0; i < nNumPoints; i++)
729  {
730  vMean.x += aPoints.at(i).x;
731  vMean.y += aPoints.at(i).y;
732  vMean.z += aPoints.at(i).z;
733  }
734 
735  vMean.x *= fNumPointsInv;
736  vMean.y *= fNumPointsInv;
737  vMean.z *= fNumPointsInv;
738 
739  // calculate variance
740  for (int i = 0; i < nNumPoints; i++)
741  {
742  fVariance += (vMean.x - aPoints.at(i).x) * (vMean.x - aPoints.at(i).x)
743  + (vMean.y - aPoints.at(i).y) * (vMean.y - aPoints.at(i).y)
744  + (vMean.z - aPoints.at(i).z) * (vMean.z - aPoints.at(i).z);
745  }
746 
747  fVariance *= fNumPointsInv;
748  }
749  else
750  {
751  ARMARX_VERBOSE_S << "GetMeanAndVariance: no points in array!";
752  }
753  }
754 
755 
756 
757 
758 
759  void RemoveOutliers(std::vector<Vec3d>& aPoints, const float fStdDevFactor, std::vector<int>* pOldIndices)
760  {
761  if (aPoints.size() < 9)
762  {
763  if (pOldIndices != NULL)
764  {
765  pOldIndices->clear();
766 
767  for (size_t i = 0; i < aPoints.size(); i++)
768  {
769  pOldIndices->push_back(i);
770  }
771  }
772 
773  return;
774  }
775 
776  Vec3d vMean;
777  float fVariance;
778  GetMeanAndVariance(aPoints, vMean, fVariance);
779  const float fThreshold2 = fStdDevFactor * fStdDevFactor * fVariance;
780 
781  ARMARX_VERBOSE_S << "Mean: (" << vMean.x << ", " << vMean.y << ", " << vMean.z << "), std dev: " << sqrtf(fVariance);
782 
783  // remove all points that are further away from the mean than fStdDevFactor x standard deviation
784  float fDist2;
785 
786  if (pOldIndices != NULL)
787  {
788  pOldIndices->clear();
789 
790  for (size_t i = 0; i < aPoints.size(); i++)
791  {
792  pOldIndices->push_back(i);
793  }
794 
795  for (size_t i = 0; i < aPoints.size(); i++)
796  {
797  fDist2 = (vMean.x - aPoints.at(i).x) * (vMean.x - aPoints.at(i).x)
798  + (vMean.y - aPoints.at(i).y) * (vMean.y - aPoints.at(i).y)
799  + (vMean.z - aPoints.at(i).z) * (vMean.z - aPoints.at(i).z);
800 
801  if (fDist2 > fThreshold2)
802  {
803  Math3d::SetVec(aPoints.at(i), aPoints.at(aPoints.size() - 1));
804  pOldIndices->at(i) = pOldIndices->at(aPoints.size() - 1);
805  aPoints.pop_back();
806  pOldIndices->pop_back();
807  i--;
808  }
809  }
810  }
811  else
812  {
813  for (size_t i = 0; i < aPoints.size(); i++)
814  {
815  fDist2 = (vMean.x - aPoints.at(i).x) * (vMean.x - aPoints.at(i).x)
816  + (vMean.y - aPoints.at(i).y) * (vMean.y - aPoints.at(i).y)
817  + (vMean.z - aPoints.at(i).z) * (vMean.z - aPoints.at(i).z);
818 
819  if (fDist2 > fThreshold2)
820  {
821  aPoints[i] = aPoints[aPoints.size() - 1];
822  aPoints.pop_back();
823  i--;
824  }
825  }
826  }
827  }
828 
829 
830 
831  void RemoveOutliers(std::vector<CHypothesisPoint*>& aPoints, const float fStdDevFactor)
832  {
833  std::vector<Vec3d> aPointsVec3d;
834  std::vector<int> pOldIndices;
835 
836  for (size_t i = 0; i < aPoints.size(); i++)
837  {
838  aPointsVec3d.push_back(aPoints.at(i)->vPosition);
839  }
840 
841  RemoveOutliers(aPointsVec3d, fStdDevFactor, &pOldIndices);
842 
843  ARMARX_VERBOSE_S << "RemoveOutliers: " << pOldIndices.size() << " of " << aPoints.size() << " points left\n";
844 
845  // keep only the points with index contained in pOldIndices
846 
847  std::vector<CHypothesisPoint*> aPointsCopy;
848  std::vector<bool> aPointStillIncluded;
849 
850  for (size_t i = 0; i < aPoints.size(); i++)
851  {
852  aPointsCopy.push_back(aPoints.at(i));
853  aPointStillIncluded.push_back(false);
854  }
855 
856  for (size_t i = 0; i < pOldIndices.size(); i++)
857  {
858  aPointStillIncluded.at(pOldIndices.at(i)) = true;
859  }
860 
861  aPoints.clear();
862 
863  for (size_t i = 0; i < aPointsCopy.size(); i++)
864  {
865  if (aPointStillIncluded.at(i))
866  {
867  aPoints.push_back(aPointsCopy.at(i));
868  }
869  else
870  {
871  delete aPointsCopy.at(i);
872  }
873  }
874  }
875 
876 
877 
878  bool CheckIfPointIsAlreadyInHypothesis(const Vec3d vPoint, const CObjectHypothesis* pHypothesis)
879  {
880  float fMinDist = FLT_MAX;
881  float fDist;
882 
883  for (size_t i = 0; i < pHypothesis->aConfirmedPoints.size(); i++)
884  {
885  fDist = Math3d::Distance(vPoint, pHypothesis->aConfirmedPoints.at(i)->vPosition);
886 
887  if (fDist < fMinDist)
888  {
889  fMinDist = fDist;
890  }
891  }
892 
893  for (size_t i = 0; i < pHypothesis->aDoubtablePoints.size(); i++)
894  {
895  fDist = Math3d::Distance(vPoint, pHypothesis->aDoubtablePoints.at(i)->vPosition);
896 
897  if (fDist < fMinDist)
898  {
899  fMinDist = fDist;
900  }
901  }
902 
903  return (fMinDist < 0.1f * OLP_TOLERANCE_CONCURRENT_MOTION);
904  }
905 
906  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr ConfirmedPointsToPCL(const CObjectHypothesis* pHypothesis)
907  {
908  pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBA>);
909  cloud->resize(pHypothesis->aConfirmedPoints.size());
910 
911  Vec3d vCenter = pHypothesis->vCenter;
912 
913  for (size_t i = 0; i < pHypothesis->aConfirmedPoints.size(); i++)
914  {
915  const CHypothesisPoint* p = pHypothesis->aConfirmedPoints.at(i);
916 
917  cloud->points[i].x = p->vPosition.x - vCenter.x;
918  cloud->points[i].y = p->vPosition.y - vCenter.y;
919  cloud->points[i].z = p->vPosition.z - vCenter.z;
920  cloud->points[i].r = (int)(255.0f * p->fIntensity * p->fColorR);
921  cloud->points[i].g = (int)(255.0f * p->fIntensity * p->fColorG);
922  cloud->points[i].b = (int)(255.0f * p->fIntensity * p->fColorB);
923  cloud->points[i].a = 1;
924  }
925 
926  return cloud;
927  }
928 
929  // stolen from IVT: ImageProcessor
930  // (1 << 20) / i
931  static const int division_table[] =
932  {
933  0, 1048576, 524288, 349525, 262144, 209715, 174762, 149796,
934  131072, 116508, 104857, 95325, 87381, 80659, 74898, 69905,
935  65536, 61680, 58254, 55188, 52428, 49932, 47662, 45590,
936  43690, 41943, 40329, 38836, 37449, 36157, 34952, 33825,
937  32768, 31775, 30840, 29959, 29127, 28339, 27594, 26886,
938  26214, 25575, 24966, 24385, 23831, 23301, 22795, 22310,
939  21845, 21399, 20971, 20560, 20164, 19784, 19418, 19065,
940  18724, 18396, 18078, 17772, 17476, 17189, 16912, 16644,
941  16384, 16131, 15887, 15650, 15420, 15196, 14979, 14768,
942  14563, 14364, 14169, 13981, 13797, 13617, 13443, 13273,
943  13107, 12945, 12787, 12633, 12483, 12336, 12192, 12052,
944  11915, 11781, 11650, 11522, 11397, 11275, 11155, 11037,
945  10922, 10810, 10699, 10591, 10485, 10381, 10280, 10180,
946  10082, 9986, 9892, 9799, 9709, 9619, 9532, 9446,
947  9362, 9279, 9198, 9118, 9039, 8962, 8886, 8811,
948  8738, 8665, 8594, 8525, 8456, 8388, 8322, 8256,
949  8192, 8128, 8065, 8004, 7943, 7884, 7825, 7767,
950  7710, 7653, 7598, 7543, 7489, 7436, 7384, 7332,
951  7281, 7231, 7182, 7133, 7084, 7037, 6990, 6944,
952  6898, 6853, 6808, 6765, 6721, 6678, 6636, 6594,
953  6553, 6512, 6472, 6432, 6393, 6355, 6316, 6278,
954  6241, 6204, 6168, 6132, 6096, 6061, 6026, 5991,
955  5957, 5924, 5890, 5857, 5825, 5793, 5761, 5729,
956  5698, 5667, 5637, 5607, 5577, 5548, 5518, 5489,
957  5461, 5433, 5405, 5377, 5349, 5322, 5295, 5269,
958  5242, 5216, 5190, 5165, 5140, 5115, 5090, 5065,
959  5041, 5017, 4993, 4969, 4946, 4922, 4899, 4877,
960  4854, 4832, 4809, 4788, 4766, 4744, 4723, 4702,
961  4681, 4660, 4639, 4619, 4599, 4578, 4559, 4539,
962  4519, 4500, 4481, 4462, 4443, 4424, 4405, 4387,
963  4369, 4350, 4332, 4315, 4297, 4279, 4262, 4245,
964  4228, 4211, 4194, 4177, 4161, 4144, 4128, 4112
965  };
966 
967 
968 
969  void ConvertRGB2HSV(const unsigned char r, const unsigned char g, const unsigned char b, unsigned char& h, unsigned char& s, unsigned char& v)
970  {
971  // stolen from IVT: ImageProcessor
972  const int max = MY_MAX(MY_MAX(r, g), b);
973  const int min = MY_MIN(MY_MIN(r, g), b);
974  const int delta = max - min;
975 
976  // unoptimized: 30 * (g - b) / delta (etc.)
977  int hInt;
978 
979  if (r == max)
980  {
981  hInt = g > b ? 180 + ((30 * (g - b) * division_table[delta]) >> 20) : 180 - ((30 * (b - g) * division_table[delta]) >> 20);
982  }
983  else if (g == max)
984  {
985  hInt = b > r ? 60 + ((30 * (b - r) * division_table[delta]) >> 20) : 60 - ((30 * (r - b) * division_table[delta]) >> 20);
986  }
987  else
988  {
989  hInt = r > g ? 120 + ((30 * (r - g) * division_table[delta]) >> 20) : 120 - ((30 * (g - r) * division_table[delta]) >> 20);
990  }
991 
992  h = (hInt >= 180) ? hInt - 180 : hInt;
993 
994  // unoptimized: delta * 255 / max;
995  s = (255 * delta * division_table[max]) >> 20;
996 
997  v = max;
998  }
999 
1000 
1001 
1002 
1003  void CreateHueAndSaturationHistogram(const CObjectHypothesis* pHypothesis, std::vector<float>& aHueHistogram, std::vector<float>& aSaturationHistogram)
1004  {
1005  if ((pHypothesis->eType != CObjectHypothesis::eRGBD) && (pHypothesis->eType != CObjectHypothesis::eSingleColored) && false)
1006  {
1007  ARMARX_WARNING_S << "CreateHueHistogram: wrong hypothesis type (not RGBD or SingleColored)!";
1008  return;
1009  }
1010 
1011  aHueHistogram.resize(OLP_SIZE_OBJECT_HUE_HISTOGRAM);
1012  aSaturationHistogram.resize(OLP_SIZE_OBJECT_HUE_HISTOGRAM);
1013  const int nBucketSize = (int)(ceil(256.0f / (float)OLP_SIZE_OBJECT_HUE_HISTOGRAM));
1014 
1015  unsigned char r, g, b, h, s, v;
1016 
1017  // add the values for the confirmed points
1018  for (size_t i = 0; i < pHypothesis->aConfirmedPoints.size(); i++)
1019  {
1020  CHypothesisPoint* pPoint = pHypothesis->aConfirmedPoints.at(i);
1021  r = (unsigned char)(255.0f * pPoint->fColorR * pPoint->fIntensity);
1022  g = (unsigned char)(255.0f * pPoint->fColorG * pPoint->fIntensity);
1023  b = (unsigned char)(255.0f * pPoint->fColorB * pPoint->fIntensity);
1024  COLPTools::ConvertRGB2HSV(r, g, b, h, s, v);
1025 
1026  // saturation-weighted hue values
1027  const float fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (s * s)); // 0.5 when s=20
1028  const int nHistogramIndexHue = h / nBucketSize;
1029  aHueHistogram.at(nHistogramIndexHue) += fWeight;
1030  const int nHistogramIndexSaturation = s / nBucketSize;
1031  aSaturationHistogram.at(nHistogramIndexSaturation) += 1;
1032  }
1033 
1034  // add the values for the candidate points
1035  const float fCandidatePointWeightFactor = 0.01f; // smaller weight for candidate points
1036 
1037  for (size_t i = 0; i < pHypothesis->aNewPoints.size(); i++)
1038  {
1039  CHypothesisPoint* pPoint = pHypothesis->aNewPoints.at(i);
1040  r = (unsigned char)(255.0f * pPoint->fColorR * pPoint->fIntensity);
1041  g = (unsigned char)(255.0f * pPoint->fColorG * pPoint->fIntensity);
1042  b = (unsigned char)(255.0f * pPoint->fColorB * pPoint->fIntensity);
1043  COLPTools::ConvertRGB2HSV(r, g, b, h, s, v);
1044 
1045  // saturation-weighted hue values
1046  const float fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (s * s));
1047  const int nHistogramIndexHue = h / nBucketSize;
1048  aHueHistogram.at(nHistogramIndexHue) += fCandidatePointWeightFactor * fWeight;
1049  const int nHistogramIndexSaturation = s / nBucketSize;
1050  aSaturationHistogram.at(nHistogramIndexSaturation) += fCandidatePointWeightFactor;
1051  }
1052 
1053  SmoothHistogram(aHueHistogram);
1054  NormalizeHistogram(aHueHistogram);
1055  SmoothHistogram(aSaturationHistogram);
1056  NormalizeHistogram(aSaturationHistogram);
1057  }
1058 
1059 
1060 
1061  void CreateHueAndSaturationHistogramInWindow(const CByteImage* pHSVImage, const int nMinX, const int nMinY, const int nMaxX, const int nMaxY,
1062  std::vector<float>& aHueHistogram, std::vector<float>& aSaturationHistogram)
1063  {
1064  aHueHistogram.resize(OLP_SIZE_OBJECT_HUE_HISTOGRAM);
1065  aSaturationHistogram.resize(OLP_SIZE_OBJECT_HUE_HISTOGRAM);
1066  const int nBucketSize = (int)(ceil(256.0f / (float)OLP_SIZE_OBJECT_HUE_HISTOGRAM));
1067 
1068  // accumulate histogram
1069  unsigned char h, s;
1070 
1071  for (int i = nMinY; i < nMaxY; i++)
1072  {
1073  for (int j = nMinX; j < nMaxX; j++)
1074  {
1075  h = pHSVImage->pixels[3 * (i * OLP_IMG_WIDTH + j)];
1076  s = pHSVImage->pixels[3 * (i * OLP_IMG_WIDTH + j) + 1];
1077  // saturation-weighted hue values
1078  const float fWeight = 1.0f - 1.0f / (1.0f + 0.0025f * (s * s)); // 0.5 when s=20
1079  const int nHistogramIndexHue = h / nBucketSize;
1080  aHueHistogram.at(nHistogramIndexHue) += fWeight;
1081  const int nHistogramIndexSaturation = s / nBucketSize;
1082  aSaturationHistogram.at(nHistogramIndexSaturation) += 1;
1083  }
1084  }
1085 
1086  SmoothHistogram(aHueHistogram);
1087  NormalizeHistogram(aHueHistogram);
1088  SmoothHistogram(aSaturationHistogram);
1089  NormalizeHistogram(aSaturationHistogram);
1090  }
1091 
1092 
1093 
1094 
1095  void SmoothHistogram(std::vector<float>& aHistogram)
1096  {
1097  std::vector<float> aHistogramTemp;
1098  const int nHistogramSize = aHistogram.size();
1099  aHistogramTemp.resize(nHistogramSize);
1100 
1101  for (int i = 0; i < nHistogramSize; i++)
1102  {
1103  aHistogramTemp.at(i) = aHistogram.at(i);
1104  }
1105 
1106  // smooth the histogram
1107  for (int i = 0; i < nHistogramSize; i++)
1108  {
1109  // aHistogram.at(i) = 0.4f * aHistogramTemp.at(i)
1110  // + 0.2f * aHistogramTemp.at((i-1+nHistogramSize)%nHistogramSize)
1111  // + 0.2f * aHistogramTemp.at((i+1)%nHistogramSize)
1112  // + 0.1f * aHistogramTemp.at((i-2+nHistogramSize)%nHistogramSize)
1113  // + 0.1f * aHistogramTemp.at((i+2)%nHistogramSize);
1114  aHistogram.at(i) = 0.7f * aHistogramTemp.at(i)
1115  + 0.15f * aHistogramTemp.at((i - 1 + nHistogramSize) % nHistogramSize)
1116  + 0.15f * aHistogramTemp.at((i + 1) % nHistogramSize);
1117  }
1118  }
1119 
1120 
1121 
1122  void NormalizeHistogram(std::vector<float>& aHistogram)
1123  {
1124  float fSum = 0;
1125 
1126  for (size_t i = 0; i < aHistogram.size(); i++)
1127  {
1128  fSum += aHistogram.at(i);
1129  }
1130 
1131  const float fInverseSum = 1.0f / fSum;
1132 
1133  for (size_t i = 0; i < aHistogram.size(); i++)
1134  {
1135  aHistogram.at(i) *= fInverseSum;
1136  }
1137  }
1138 
1139 
1140 
1141 
1142  float GetHistogramDistanceL1(const std::vector<float>& aHistogram1, const std::vector<float>& aHistogram2)
1143  {
1144  const int n = (int)aHistogram1.size();
1145 
1146  float fDist = 0;
1147 
1148  for (int i = 0; i < n; i++)
1149  {
1150  fDist += fabsf(aHistogram1.at(i) - aHistogram2.at(i));
1151  }
1152 
1153  return fDist;
1154  }
1155 
1156 
1157  float GetHistogramDistanceL2(const std::vector<float>& aHistogram1, const std::vector<float>& aHistogram2)
1158  {
1159  const int n = (int)aHistogram1.size();
1160 
1161  float fDist = 0;
1162 
1163  for (int i = 0; i < n; i++)
1164  {
1165  fDist += (aHistogram1.at(i) - aHistogram2.at(i)) * (aHistogram1.at(i) - aHistogram2.at(i));
1166  }
1167 
1168  return sqrtf(fDist);
1169  }
1170 
1171 
1172  float GetHistogramDistanceX2(const std::vector<float>& aHistogram1, const std::vector<float>& aHistogram2)
1173  {
1174  const int n = (int)aHistogram1.size();
1175 
1176  float fDist = 0;
1177 
1178  for (int i = 0; i < n; i++)
1179  {
1180  fDist += (aHistogram1.at(i) - aHistogram2.at(i)) * (aHistogram1.at(i) - aHistogram2.at(i)) / (aHistogram1.at(i) + aHistogram2.at(i) + 0.00001f);
1181  }
1182 
1183  return sqrtf(fDist);
1184  }
1185 
1186 
1187 
1188 
1189  void DrawCross(CByteImage* pGreyImage, int x, int y, int nBrightness)
1190  {
1191  if (x > 2 && y > 2 && x < OLP_IMG_WIDTH - 3 && y < OLP_IMG_HEIGHT - 3)
1192  {
1193  for (int j = -3; j <= 3; j++)
1194  {
1195  pGreyImage->pixels[(y + j)*OLP_IMG_WIDTH + x] = nBrightness;
1196  pGreyImage->pixels[y * OLP_IMG_WIDTH + x + j] = nBrightness;
1197  }
1198  }
1199  }
1200 
1201 
1202  void DrawCross(CByteImage* pColorImage, int x, int y, int r, int g, int b)
1203  {
1204  if (x > 2 && y > 2 && x < OLP_IMG_WIDTH - 3 && y < OLP_IMG_HEIGHT - 3)
1205  {
1206  for (int j = -3; j <= 3; j++)
1207  {
1208  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x)] = r;
1209  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x) + 1] = g;
1210  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x) + 2] = b;
1211 
1212  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j)] = r;
1213  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j) + 1] = g;
1214  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j) + 2] = b;
1215  }
1216  }
1217  }
1218 
1219 
1220  void DrawFatCross(CByteImage* pColorImage, int x, int y, int r, int g, int b)
1221  {
1222  if (x > 2 && y > 2 && x < OLP_IMG_WIDTH - 5 && y < OLP_IMG_HEIGHT - 5)
1223  {
1224  for (int j = -3; j <= 4; j++)
1225  {
1226  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x)] = r;
1227  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x) + 1] = g;
1228  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x) + 2] = b;
1229 
1230  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x + 1)] = r;
1231  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x + 1) + 1] = g;
1232  pColorImage->pixels[3 * ((y + j)*OLP_IMG_WIDTH + x + 1) + 2] = b;
1233 
1234 
1235  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j)] = r;
1236  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j) + 1] = g;
1237  pColorImage->pixels[3 * (y * OLP_IMG_WIDTH + x + j) + 2] = b;
1238 
1239  pColorImage->pixels[3 * ((y + 1)*OLP_IMG_WIDTH + x + j)] = r;
1240  pColorImage->pixels[3 * ((y + 1)*OLP_IMG_WIDTH + x + j) + 1] = g;
1241  pColorImage->pixels[3 * ((y + 1)*OLP_IMG_WIDTH + x + j) + 2] = b;
1242  }
1243  }
1244  }
1245 
1246 
1247 
1248 
1249  void CreateObjectSegmentationMask(const CObjectHypothesis* pHypothesis, const CCalibration* calibration, CByteImage*& pForegroundImage)
1250  {
1251  if (pForegroundImage == NULL)
1252  {
1253  pForegroundImage = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1254  }
1255  else if (pForegroundImage->width != OLP_IMG_WIDTH || pForegroundImage->height != OLP_IMG_HEIGHT || pForegroundImage->type != CByteImage::eGrayScale)
1256  {
1257  delete pForegroundImage;
1258  pForegroundImage = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1259  }
1260 
1261  // reset pixels
1262  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1263  {
1264  pForegroundImage->pixels[i] = 0;
1265  }
1266 
1267 
1268  // pixels belonging to the hypothesis are foreground
1269  for (size_t i = 0; i < pHypothesis->aVisibleConfirmedPoints.size(); i++)
1270  {
1271  Vec2d vPoint2D;
1272  calibration->WorldToImageCoordinates(pHypothesis->aVisibleConfirmedPoints.at(i)->vPosition, vPoint2D, false);
1273  int nIndex = (int)vPoint2D.y * OLP_IMG_WIDTH + (int)vPoint2D.x;
1274 
1275  if (0 <= nIndex && nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT)
1276  {
1277  pForegroundImage->pixels[nIndex] = 255;
1278  }
1279  }
1280 
1281  if (pHypothesis->aVisibleConfirmedPoints.size() < OLP_MIN_NUM_FEATURES)
1282  {
1283  for (size_t i = 0; i < pHypothesis->aNewPoints.size(); i++)
1284  {
1285  Vec2d vPoint2D;
1286  calibration->WorldToImageCoordinates(pHypothesis->aNewPoints.at(i)->vPosition, vPoint2D, false);
1287  int nIndex = (int)vPoint2D.y * OLP_IMG_WIDTH + (int)vPoint2D.x;
1288 
1289  if (0 <= nIndex && nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT)
1290  {
1291  pForegroundImage->pixels[nIndex] = 255;
1292  }
1293  }
1294  }
1295 
1296 
1297  // apply morphological operators to cover the free space between the points and close holes
1298  CByteImage* pTempImage = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1299 
1300  for (int i = 0; i < OLP_DEPTH_MAP_PIXEL_DISTANCE + 1; i++)
1301  {
1302  ImageProcessor::Dilate(pForegroundImage, pTempImage);
1303  ImageProcessor::Dilate(pTempImage, pForegroundImage);
1304  }
1305  //ImageProcessor::Dilate(pForegroundImage, pTempImage);
1306  for (int i = 0; i < OLP_DEPTH_MAP_PIXEL_DISTANCE + 1; i++)
1307  {
1308  ImageProcessor::Erode(pForegroundImage, pTempImage);
1309  ImageProcessor::Erode(pTempImage, pForegroundImage);
1310  }
1311  //ImageProcessor::CopyImage(pTempImage, pForegroundImage);
1312 
1313  delete pTempImage;
1314 
1315  //pForegroundImage->SaveToFile("/home/staff/schieben/datalog/objseg.bmp");
1316  }
1317 
1318 
1319  void CreateSegmentationProbabilityMap(const CObjectHypothesis* pHypothesis, const CCalibration* calibration, CByteImage*& pProbabilityImage)
1320  {
1321  if (pProbabilityImage == NULL)
1322  {
1323  pProbabilityImage = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1324 
1325  }
1326 
1327  // reset pixels
1328  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1329  {
1330  pProbabilityImage->pixels[i] = 0;
1331  }
1332 
1333  // pixels belonging to the hypothesis are foreground
1334  const int probValueConfirmedPoints = 255;
1335  const int probValueCandidatePoints = 51;
1336  Vec2d vPoint2D;
1337 
1338  for (size_t i = 0; i < pHypothesis->aNewPoints.size(); i++)
1339  {
1340  calibration->WorldToImageCoordinates(pHypothesis->aNewPoints.at(i)->vPosition, vPoint2D, false);
1341  int nIndex = (int)vPoint2D.y * OLP_IMG_WIDTH + (int)vPoint2D.x;
1342 
1343  if (0 <= nIndex && nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT)
1344  {
1345  pProbabilityImage->pixels[nIndex] = probValueCandidatePoints;
1346  }
1347  }
1348 
1349  for (size_t i = 0; i < pHypothesis->aVisibleConfirmedPoints.size(); i++)
1350  {
1351  calibration->WorldToImageCoordinates(pHypothesis->aVisibleConfirmedPoints.at(i)->vPosition, vPoint2D, false);
1352  int nIndex = (int)vPoint2D.y * OLP_IMG_WIDTH + (int)vPoint2D.x;
1353 
1354  if (0 <= nIndex && nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT)
1355  {
1356  pProbabilityImage->pixels[nIndex] = probValueConfirmedPoints;
1357  }
1358  }
1359 
1360  CByteImage* tempImage = new CByteImage(pProbabilityImage);
1361  const float sigma = OLP_DEPTH_MAP_PIXEL_DISTANCE + 1;
1362  const int nKernelSize = 4 * sigma + 1; // >= 4*sigma+1
1363  ImageProcessor::GaussianSmooth(pProbabilityImage, tempImage, sigma * sigma, nKernelSize);
1364  ImageProcessor::HistogramStretching(tempImage, pProbabilityImage, 0.0f, 1.0f);
1365  ImageProcessor::GaussianSmooth(pProbabilityImage, tempImage, sigma * sigma, nKernelSize);
1366  ImageProcessor::HistogramStretching(tempImage, pProbabilityImage, 0.0f, 1.0f);
1367 
1368  // for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1369  // {
1370  // pTempImage->pixels[i] = (pTempImage->pixels[i] > 50) ? 255 : 5 * pTempImage->pixels[i];
1371  // }
1372  // ImageProcessor::GaussianSmooth(pTempImage, pProbabilityImage, sigma * sigma, nKernelSize);
1373  delete tempImage;
1374  }
1375 
1376 
1377 
1378  void SetNumberInFileName(std::string& sFileName, int nNumber, int nNumDigits)
1379  {
1380  for (int i = 0; i < nNumDigits; i++)
1381  {
1382  int nDecimalDivisor = 1;
1383 
1384  for (int j = 0; j < i; j++)
1385  {
1386  nDecimalDivisor *= 10;
1387  }
1388 
1389  sFileName.at(sFileName.length() - (5 + i)) = '0' + (nNumber / nDecimalDivisor) % 10;
1390  }
1391  }
1392 
1393 
1394 
1395  float GetHypothesesIntersectionRatio(const CObjectHypothesis* pHypothesis1, const CObjectHypothesis* pHypothesis2, const CCalibration* calibration)
1396  {
1397  CByteImage* pHypothesisRegionImage1 = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1398  CByteImage* pHypothesisRegionImage2 = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
1399  CreateObjectSegmentationMask(pHypothesis1, calibration, pHypothesisRegionImage1);
1400  CreateObjectSegmentationMask(pHypothesis2, calibration, pHypothesisRegionImage2);
1401 
1402  int nIntersectingPoints = 0;
1403  int nUnionPoints = 0;
1404 
1405  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1406  {
1407  nIntersectingPoints += (pHypothesisRegionImage1->pixels[i] * pHypothesisRegionImage2->pixels[i] != 0);
1408  nUnionPoints += (pHypothesisRegionImage1->pixels[i] + pHypothesisRegionImage2->pixels[i] != 0);
1409  }
1410 
1411  delete pHypothesisRegionImage1;
1412  delete pHypothesisRegionImage2;
1413 
1414  if (nUnionPoints > 0)
1415  {
1416  return (float)nIntersectingPoints / (float)nUnionPoints;
1417  }
1418  else
1419  {
1420  return 0;
1421  }
1422  }
1423 
1424 
1425  void DrawHypothesis(CObjectHypothesis* pHypothesis, const CCalibration* calibration, CByteImage* pImage, const int nNumFusedHypotheses)
1426  {
1427  // reorder points to draw closest ones last
1429  // invert order to decreasing
1430  CHypothesisPoint* pTempPoint;
1431  const int nSize = pHypothesis->aVisibleConfirmedPoints.size();
1432 
1433  for (int i = 0; 2 * i < nSize; i++)
1434  {
1435  pTempPoint = pHypothesis->aVisibleConfirmedPoints.at(i);
1436  pHypothesis->aVisibleConfirmedPoints.at(i) = pHypothesis->aVisibleConfirmedPoints.at(nSize - i - 1);
1437  pHypothesis->aVisibleConfirmedPoints.at(nSize - i - 1) = pTempPoint;
1438  }
1439 
1440  ImageProcessor::Zero(pImage);
1441 
1442  for (size_t i = 0; i < pHypothesis->aVisibleConfirmedPoints.size(); i++)
1443  {
1444  Vec2d vPoint2D;
1445  calibration->WorldToImageCoordinates(pHypothesis->aVisibleConfirmedPoints.at(i)->vPosition, vPoint2D, false);
1446  int nIndex = (int)vPoint2D.y * OLP_IMG_WIDTH + (int)vPoint2D.x;
1447 
1448  if (0 <= nIndex && nIndex < OLP_IMG_WIDTH * OLP_IMG_HEIGHT)
1449  {
1450  pImage->pixels[3 * nIndex] = 255 * pHypothesis->aVisibleConfirmedPoints.at(i)->fIntensity * pHypothesis->aVisibleConfirmedPoints.at(i)->fColorR;
1451  pImage->pixels[3 * nIndex + 1] = 255 * pHypothesis->aVisibleConfirmedPoints.at(i)->fIntensity * pHypothesis->aVisibleConfirmedPoints.at(i)->fColorG;
1452  pImage->pixels[3 * nIndex + 2] = 255 * pHypothesis->aVisibleConfirmedPoints.at(i)->fIntensity * pHypothesis->aVisibleConfirmedPoints.at(i)->fColorB;
1453  }
1454  }
1455 
1456  // fill holes
1457  CByteImage* pTempImg = new CByteImage(pImage);
1458  FillHolesRGB(pImage, pTempImg, 2);
1459  FillHolesRGB(pTempImg, pImage, 2);
1460  delete pTempImg;
1461 
1462  // remove regions with low foreground probability
1463  CByteImage* pSegmentationProbability = NULL;
1464  CreateSegmentationProbabilityMap(pHypothesis, calibration, pSegmentationProbability);
1465  std::string sFileName = OLP_OBJECT_LEARNING_DIR;
1466  sFileName += "SegmProb.bmp";
1467  pSegmentationProbability->SaveToFile(sFileName.c_str());
1468 
1469  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1470  {
1471  if (pSegmentationProbability->pixels[i] < 1 + nNumFusedHypotheses / 3)
1472  {
1473  pImage->pixels[3 * i] *= 0.3;
1474  pImage->pixels[3 * i + 1] *= 0.3;
1475  pImage->pixels[3 * i + 2] *= 0.3;
1476  }
1477  }
1478  }
1479 
1480 
1481  void FillHolesRGB(const CByteImage* pInputImage, CByteImage* pOutputImage, const int nRadius)
1482  {
1483  for (int i = 0; i < 3 * OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1484  {
1485  pOutputImage->pixels[i] = pInputImage->pixels[i];
1486  }
1487 
1488  for (int i = nRadius; i < OLP_IMG_HEIGHT - nRadius; i++)
1489  {
1490  for (int j = nRadius; j < OLP_IMG_WIDTH - nRadius; j++)
1491  {
1492  int nIndex = i * OLP_IMG_WIDTH + j;
1493 
1494  if (pInputImage->pixels[3 * nIndex] + pInputImage->pixels[3 * nIndex + 1] + pInputImage->pixels[3 * nIndex + 2] == 0)
1495  {
1496  int r, g, b, nNumPixels;
1497  r = g = b = nNumPixels = 0;
1498 
1499  for (int l = -nRadius; l <= nRadius; l++)
1500  {
1501  for (int k = -nRadius; k <= nRadius; k++)
1502  {
1503  int nTempIndex = 3 * (nIndex + l * OLP_IMG_WIDTH + k);
1504 
1505  if (pInputImage->pixels[nTempIndex] + pInputImage->pixels[nTempIndex + 1] + pInputImage->pixels[nTempIndex + 2] != 0)
1506  {
1507  r += pInputImage->pixels[nTempIndex];
1508  g += pInputImage->pixels[nTempIndex + 1];
1509  b += pInputImage->pixels[nTempIndex + 2];
1510  nNumPixels++;
1511  }
1512  }
1513  }
1514 
1515  if (nNumPixels > 0)
1516  {
1517  pOutputImage->pixels[3 * nIndex] = r / nNumPixels;
1518  pOutputImage->pixels[3 * nIndex + 1] = g / nNumPixels;
1519  pOutputImage->pixels[3 * nIndex + 2] = b / nNumPixels;
1520  }
1521  }
1522  }
1523  }
1524  }
1525 
1526 
1527  void FillHolesGray(const CByteImage* pInputImage, CByteImage* pOutputImage, const int nRadius)
1528  {
1529  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1530  {
1531  pOutputImage->pixels[i] = pInputImage->pixels[i];
1532  }
1533 
1534  for (int i = nRadius; i < OLP_IMG_HEIGHT - nRadius; i++)
1535  {
1536  for (int j = nRadius; j < OLP_IMG_WIDTH - nRadius; j++)
1537  {
1538  int nIndex = i * OLP_IMG_WIDTH + j;
1539 
1540  if (pInputImage->pixels[nIndex] == 0)
1541  {
1542  int nSum = 0;
1543  int nNumPixels = 0;
1544 
1545  for (int l = -nRadius; l <= nRadius; l++)
1546  {
1547  for (int k = -nRadius; k <= nRadius; k++)
1548  {
1549  int nTempIndex = nIndex + l * OLP_IMG_WIDTH + k;
1550 
1551  if (pInputImage->pixels[nTempIndex] != 0)
1552  {
1553  nSum += pInputImage->pixels[nTempIndex];
1554  nNumPixels++;
1555  }
1556  }
1557  }
1558 
1559  if (nNumPixels > 0)
1560  {
1561  pOutputImage->pixels[nIndex] = nSum / nNumPixels;
1562  }
1563  }
1564  }
1565  }
1566  }
1567 
1568 
1569  // Quicksort from slide of Prof. Sanders
1570  void SortByPositionZ(std::vector<CHypothesisPoint*>& aHypothesisPoints, const int nLeftLimit, const int nRightLimit)
1571  {
1572  if (aHypothesisPoints.size() <= 1 || nRightLimit - nLeftLimit <= 0)
1573  {
1574  return;
1575  }
1576 
1577  float fPivot = aHypothesisPoints.at((nLeftLimit + nRightLimit) / 2)->vPosition.z;
1578 
1579  int nLeftIndex = nLeftLimit;
1580  int nRightIndex = nRightLimit;
1581 
1582  while (nLeftIndex <= nRightIndex)
1583  {
1584  while (aHypothesisPoints.at(nLeftIndex)->vPosition.z < fPivot && (nLeftIndex <= nRightIndex))
1585  {
1586  nLeftIndex++;
1587  }
1588 
1589  while (aHypothesisPoints.at(nRightIndex)->vPosition.z > fPivot && (nLeftIndex <= nRightIndex))
1590  {
1591  nRightIndex--;
1592  }
1593 
1594  if (nLeftIndex <= nRightIndex)
1595  {
1596  CHypothesisPoint* pTemp = aHypothesisPoints.at(nLeftIndex);
1597  aHypothesisPoints.at(nLeftIndex) = aHypothesisPoints.at(nRightIndex);
1598  aHypothesisPoints.at(nRightIndex) = pTemp;
1599  nLeftIndex++;
1600  nRightIndex--;
1601  }
1602  }
1603 
1604  SortByPositionZ(aHypothesisPoints, nLeftLimit, nRightIndex);
1605  SortByPositionZ(aHypothesisPoints, nLeftIndex, nRightLimit);
1606  }
1607 
1608  void SortByPositionZ(std::vector<CHypothesisPoint*>& aHypothesisPoints)
1609  {
1610  SortByPositionZ(aHypothesisPoints, 0, aHypothesisPoints.size() - 1);
1611  }
1612 
1613 
1614 
1615  void CalculateEdgeImageFromImageAndDisparity(CByteImage* pImageGray, CByteImage* pDisparity, CByteImage* pEdgeImage)
1616  {
1617  // edges from the image
1618  CByteImage* pTempImage = new CByteImage(pImageGray);
1619  float pEdgesFromImage[OLP_IMG_WIDTH * OLP_IMG_HEIGHT];
1620  ImageProcessor::GaussianSmooth5x5(pImageGray, pTempImage);
1621  ImageProcessor::CalculateGradientImageSobel(pTempImage, pEdgeImage);
1622 
1623  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1624  {
1625  pEdgesFromImage[i] = pEdgeImage->pixels[i];
1626  }
1627 
1628  std::string sScreenshotFile = OLP_SCREENSHOT_PATH;
1629  sScreenshotFile += "edge-img.bmp";
1630  pEdgeImage->SaveToFile(sScreenshotFile.c_str());
1631 
1632 
1633  // edges from disparity
1634  float pEdgesFromDisparity[OLP_IMG_WIDTH * OLP_IMG_HEIGHT];
1635  // count number of disparity pixels that are zero to allow histogram stretching
1636  int nNumZeroDisparityPixels = 0;
1637 
1638  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1639  {
1640  if (pDisparity->pixels[i] == 0)
1641  {
1642  nNumZeroDisparityPixels++;
1643  }
1644  }
1645 
1646  float fZeroDisparityPixelRatio = (float)nNumZeroDisparityPixels / (float)(OLP_IMG_WIDTH * OLP_IMG_HEIGHT);
1647  ImageProcessor::HistogramStretching(pDisparity, pTempImage, fZeroDisparityPixelRatio + 0.1f, 0.9f);
1648  sScreenshotFile = OLP_SCREENSHOT_PATH;
1649  sScreenshotFile += "disp.bmp";
1650  pTempImage->SaveToFile(sScreenshotFile.c_str());
1651 
1652  const float fSigma = 7;
1653  const int nKernelSize = 4 * fSigma + 1; // >= 4*fSigma+1
1654  ImageProcessor::GaussianSmooth(pTempImage, pEdgeImage, fSigma * fSigma, nKernelSize);
1655 
1656  ImageProcessor::CalculateGradientImageSobel(pEdgeImage, pTempImage);
1657 
1658  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1659  {
1660  pEdgesFromDisparity[i] = pTempImage->pixels[i];
1661  }
1662 
1663  sScreenshotFile = OLP_SCREENSHOT_PATH;
1664  sScreenshotFile += "edge-disp.bmp";
1665  pTempImage->SaveToFile(sScreenshotFile.c_str());
1666 
1667 
1668  // combine edges
1669  float fValue;
1670 
1671  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
1672  {
1673  fValue = sqrtf(pEdgesFromImage[i] * pEdgesFromDisparity[i] * sqrtf(pEdgesFromDisparity[i]));
1674  pEdgeImage->pixels[i] = (fValue > 255) ? 255 : fValue;
1675  }
1676 
1677  sScreenshotFile = OLP_SCREENSHOT_PATH;
1678  sScreenshotFile += "edge-full.bmp";
1679  pEdgeImage->SaveToFile(sScreenshotFile.c_str());
1680  }
1681 
1682 }
1683 
1684 
OLP_IMG_HEIGHT
#define OLP_IMG_HEIGHT
Definition: ObjectLearningByPushingDefinitions.h:69
COLPTools::InterpolateRotation
void InterpolateRotation(const Mat3d m1, const Mat3d m2, const float fWeight, Mat3d &mResult)
Definition: OLPTools.cpp:44
COLPTools::GetMeanAndVariance
void GetMeanAndVariance(const std::vector< CHypothesisPoint * > &pHypothesisPoints, Vec3d &vMean, float &fVariance)
Definition: OLPTools.cpp:699
OLP_IMG_WIDTH
#define OLP_IMG_WIDTH
Definition: ObjectLearningByPushingDefinitions.h:68
COLPTools::CreateObjectSegmentationMask
void CreateObjectSegmentationMask(const CObjectHypothesis *pHypothesis, const CCalibration *calibration, CByteImage *&pForegroundImage)
Definition: OLPTools.cpp:1249
ObjectHypothesis.h
OLP_DEPTH_MAP_PIXEL_DISTANCE
#define OLP_DEPTH_MAP_PIXEL_DISTANCE
Definition: ObjectLearningByPushingDefinitions.h:256
CHypothesisPoint::fIntensity
float fIntensity
Definition: ObjectHypothesis.h:241
COLPTools::GetHistogramDistanceX2
float GetHistogramDistanceX2(const std::vector< float > &aHistogram1, const std::vector< float > &aHistogram2)
Definition: OLPTools.cpp:1172
COLPTools::SortByPositionZ
void SortByPositionZ(std::vector< CHypothesisPoint * > &aHypothesisPoints, const int nLeftLimit, const int nRightLimit)
Definition: OLPTools.cpp:1570
COLPTools::GetHistogramDistanceL2
float GetHistogramDistanceL2(const std::vector< float > &aHistogram1, const std::vector< float > &aHistogram2)
Definition: OLPTools.cpp:1157
COLPTools::GetHypothesesIntersectionRatio
float GetHypothesesIntersectionRatio(const CObjectHypothesis *pHypothesis1, const CObjectHypothesis *pHypothesis2, const CCalibration *calibration)
Definition: OLPTools.cpp:1395
COLPTools::SetNumberInFileName
void SetNumberInFileName(std::string &sFileName, int nNumber, int nNumDigits)
Definition: OLPTools.cpp:1378
GfxTL::Vec2d
VectorXD< 2, double > Vec2d
Definition: VectorXD.h:694
COLPTools::DrawCross
void DrawCross(CByteImage *pGreyImage, int x, int y, int nBrightness)
Definition: OLPTools.cpp:1189
CObjectHypothesis::eType
eObjectType eType
Definition: ObjectHypothesis.h:289
CHypothesisPoint::fColorG
float fColorG
Definition: ObjectHypothesis.h:241
COLPTools::GetHistogramDistanceL1
float GetHistogramDistanceL1(const std::vector< float > &aHistogram1, const std::vector< float > &aHistogram2)
Definition: OLPTools.cpp:1142
COLPTools::CalculateForegroundRatioOfHypothesis
void CalculateForegroundRatioOfHypothesis(const CObjectHypothesis *pHypothesis, const CByteImage *pForegroundImage, const CCalibration *calibration, float &fForegroundRatio, int &nNumForegroundPixels)
Definition: OLPTools.cpp:336
COLPTools::CreateHueAndSaturationHistogramInWindow
void CreateHueAndSaturationHistogramInWindow(const CByteImage *pHSVImage, const int nMinX, const int nMinY, const int nMaxX, const int nMaxY, std::vector< float > &aHueHistogram, std::vector< float > &aSaturationHistogram)
Definition: OLPTools.cpp:1061
CHypothesisPoint::vPosition
Vec3d vPosition
Definition: ObjectHypothesis.h:238
COLPTools::RemoveOutliers
void RemoveOutliers(std::vector< Vec3d > &aPoints, const float fStdDevFactor, std::vector< int > *pOldIndices)
Definition: OLPTools.cpp:759
COLPTools::InterpolateTransformation
void InterpolateTransformation(const Mat3d m1, const Vec3d v1, const Mat3d m2, const Vec3d v2, const float fWeight, Mat3d &mResult, Vec3d &vResult)
Definition: OLPTools.cpp:67
COLPTools::ConfirmedPointsToPCL
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr ConfirmedPointsToPCL(const CObjectHypothesis *pHypothesis)
Definition: OLPTools.cpp:906
COLPTools::NormalizeHistogram
void NormalizeHistogram(std::vector< float > &aHistogram)
Definition: OLPTools.cpp:1122
CObjectHypothesis::eRGBD
@ eRGBD
Definition: ObjectHypothesis.h:285
COLPTools::FillHolesGray
void FillHolesGray(const CByteImage *pInputImage, CByteImage *pOutputImage, const int nRadius)
Definition: OLPTools.cpp:1527
COLPTools::DrawFatCross
void DrawFatCross(CByteImage *pColorImage, int x, int y, int r, int g, int b)
Definition: OLPTools.cpp:1220
COLPTools::PointIsInForeground
bool PointIsInForeground(const Vec3d vPoint, const CByteImage *pForegroundImage, const CCalibration *calibration)
Definition: OLPTools.cpp:310
COLPTools::CalculateEdgeImageFromImageAndDisparity
void CalculateEdgeImageFromImageAndDisparity(CByteImage *pImageGray, CByteImage *pDisparity, CByteImage *pEdgeImage)
Definition: OLPTools.cpp:1615
OLPTools.h
CHypothesisPoint
Definition: ObjectHypothesis.h:171
OLP_MIN_NUM_FEATURES
#define OLP_MIN_NUM_FEATURES
Definition: ObjectLearningByPushingDefinitions.h:109
OLP_TOLERANCE_CONCURRENT_MOTION
#define OLP_TOLERANCE_CONCURRENT_MOTION
Definition: ObjectLearningByPushingDefinitions.h:224
if
if(!yyvaluep)
Definition: Grammar.cpp:724
OLP_SIZE_OBJECT_HUE_HISTOGRAM
#define OLP_SIZE_OBJECT_HUE_HISTOGRAM
Definition: ObjectLearningByPushingDefinitions.h:220
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:695
CObjectHypothesis::vCenter
Vec3d vCenter
Definition: ObjectHypothesis.h:308
COLPTools::GetEnclosingRectangle
void GetEnclosingRectangle(const Vec2d *pPoints, const int nNumPoints, const bool bUseSecondMaxPoints, Vec2d &p1, Vec2d &p2, Vec2d &p3, Vec2d &p4, bool &bRotated)
Definition: OLPTools.cpp:450
OLP_OBJECT_LEARNING_DIR
#define OLP_OBJECT_LEARNING_DIR
Definition: ObjectLearningByPushingDefinitions.h:162
CObjectHypothesis::aVisibleConfirmedPoints
std::vector< CHypothesisPoint * > aVisibleConfirmedPoints
Definition: ObjectHypothesis.h:294
EPS
#define EPS
Definition: gdiam.cpp:2021
COLPTools::CreateHueAndSaturationHistogram
void CreateHueAndSaturationHistogram(const CObjectHypothesis *pHypothesis, std::vector< float > &aHueHistogram, std::vector< float > &aSaturationHistogram)
Definition: OLPTools.cpp:1003
max
T max(T t1, T t2)
Definition: gdiam.h:48
COLPTools::CreateSegmentationProbabilityMap
void CreateSegmentationProbabilityMap(const CObjectHypothesis *pHypothesis, const CCalibration *calibration, CByteImage *&pProbabilityImage)
Definition: OLPTools.cpp:1319
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:206
CObjectHypothesis::eSingleColored
@ eSingleColored
Definition: ObjectHypothesis.h:285
CHypothesisPoint::fColorR
float fColorR
Definition: ObjectHypothesis.h:241
COLPTools::ClusterXMeans
void ClusterXMeans(const std::vector< CHypothesisPoint * > &aPoints, const int nMinNumClusters, const int nMaxNumClusters, const float fBICFactor, std::vector< std::vector< CHypothesisPoint * > > &aaPointClusters)
Definition: OLPTools.cpp:76
COLPTools
Definition: OLPTools.cpp:42
CObjectHypothesis
Definition: ObjectHypothesis.h:249
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
float
#define float
Definition: 16_Level.h:22
CObjectHypothesis::aNewPoints
std::vector< CHypothesisPoint * > aNewPoints
Definition: ObjectHypothesis.h:291
COLPTools::FillHolesRGB
void FillHolesRGB(const CByteImage *pInputImage, CByteImage *pOutputImage, const int nRadius)
Definition: OLPTools.cpp:1481
COLPTools::DrawHypothesis
void DrawHypothesis(CObjectHypothesis *pHypothesis, const CCalibration *calibration, CByteImage *pImage, const int nNumFusedHypotheses)
Definition: OLPTools.cpp:1425
CObjectHypothesis::aDoubtablePoints
std::vector< CHypothesisPoint * > aDoubtablePoints
Definition: ObjectHypothesis.h:293
COLPTools::SmoothHistogram
void SmoothHistogram(std::vector< float > &aHistogram)
Definition: OLPTools.cpp:1095
CObjectHypothesis::aConfirmedPoints
std::vector< CHypothesisPoint * > aConfirmedPoints
Definition: ObjectHypothesis.h:292
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:200
COLPTools::ConvertRGB2HSV
void ConvertRGB2HSV(const unsigned char r, const unsigned char g, const unsigned char b, unsigned char &h, unsigned char &s, unsigned char &v)
Definition: OLPTools.cpp:969
COLPTools::FilterForegroundPoints
void FilterForegroundPoints(const std::vector< CHypothesisPoint * > &aAllPoints, const CByteImage *pForegroundImage, const CCalibration *calibration, std::vector< CHypothesisPoint * > &aForegroundPoints)
Definition: OLPTools.cpp:289
OLP_SCREENSHOT_PATH
#define OLP_SCREENSHOT_PATH
Definition: ObjectLearningByPushingDefinitions.h:206
Logging.h
CHypothesisPoint::fColorB
float fColorB
Definition: ObjectHypothesis.h:241
min
T min(T t1, T t2)
Definition: gdiam.h:42
COLPTools::CountForegroundPixelsInRectangle
int CountForegroundPixelsInRectangle(const Vec2d vMiddleMin, const Vec2d vMinMiddle, const Vec2d vMaxMiddle, const Vec2d vMiddleMax, const CByteImage *pForegroundImage)
Definition: OLPTools.cpp:621
COLPTools::CheckIfPointIsAlreadyInHypothesis
bool CheckIfPointIsAlreadyInHypothesis(const Vec3d vPoint, const CObjectHypothesis *pHypothesis)
Definition: OLPTools.cpp:878
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33