ParticleFilterRobotHandLocalisation.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 */
25
26#include <cfloat>
27
28namespace visionx
29{
30 //******************************************************************************************************************
31 // Constructor and destructor
32 //******************************************************************************************************************
33
34 // constructor
36 int nParticles,
37 int nDimension,
38 int nNumParallelThreads,
39 CStereoCalibration* pCalibration,
40 std::string sHandModelFileName) :
41 CParticleFilterFrameworkParallelized(nParticles, nDimension, nNumParallelThreads)
42 {
43 // set hand model
45 for (int i = 0; i < m_nNumParallelThreads; i++)
46 {
47#ifdef DSHT_USE_ICUB
48 m_pHandModels[i] = new HandModeliCub(sHandModelFileName, pCalibration);
49#else
50 m_pHandModels[i] = new CHandModelV2(sHandModelFileName, pCalibration);
51#endif
52 }
53
54 // init array for the sensor values and the allowed deviation
55 sensor_config = new double[nDimension];
56 allowed_deviation = new double[nDimension];
57
58
60
61
62 // init array of preliminary probabilities
63 m_ppProbabilities = new double*[NUMBER_OF_CUES];
64 for (int i = 0; i < NUMBER_OF_CUES; i++)
65 {
66 m_ppProbabilities[i] = new double[m_nParticles];
67 }
68
69
70 c_total = 1; // c_total is sum of all pi. c[i] is the sum of all p[j] with j<=i.
71 // It is used to pick the random samples for the recalculation of the particles
72
73
74 // init spaces for temporary stuff
81 for (int i = 0; i < m_nNumParallelThreads; i++)
82 {
88 }
89 }
90
91 // Destructor
93 {
94 for (int i = 0; i < NUMBER_OF_CUES; i++)
95 {
96 delete[] m_ppProbabilities[i];
97 }
98 delete[] m_ppProbabilities;
99
100 for (int i = 0; i < m_nNumParallelThreads; i++)
101 {
103 delete m_pTempVecArrays[i];
106 delete m_pTempBoolArrays[i];
107 }
109 delete[] m_pTempVecArrays;
112 delete[] m_pTempBoolArrays;
113
114 delete[] sensor_config;
115 delete[] allowed_deviation;
116 }
117
118 //******************************************************************************************************************
119 // Set and change configurations of the particle filter
120 //******************************************************************************************************************
121
122
123 void
125 CByteImage* pRegionImageRight,
126 CByteImage* pSobelImageLeft,
127 CByteImage* pSobelImageRight,
128 CByteImage* pSobelXImageLeft,
129 CByteImage* pSobelXImageRight,
130 CByteImage* pSobelYImageLeft,
131 CByteImage* pSobelYImageRight)
132 {
133 // set images
134 m_pRegionImageLeft = pRegionImageLeft;
135 m_pRegionImageRight = pRegionImageRight;
136 m_pSobelImageLeft = pSobelImageLeft;
137 m_pSobelImageRight = pSobelImageRight;
138 m_pSobelXImageLeft = pSobelXImageLeft;
139 m_pSobelXImageRight = pSobelXImageRight;
140 m_pSobelYImageLeft = pSobelYImageLeft;
141 m_pSobelYImageRight = pSobelYImageRight;
142 }
143
144 // set the configuration of the particles
145 void
147 {
148 for (int i = 0; i < m_nParticles; i++)
149 for (int j = 0; j < m_nDimension; j++)
150 {
151 s[i][j] = pConfig[j];
152 }
153 }
154
155 // set the configuration of the first half of the particles, the rest is not changed
156 void
158 {
159 for (int i = 0; i < m_nParticles / 2; i++)
160 for (int j = 0; j < m_nDimension; j++)
161 {
162 s[i][j] = pConfig[j];
163 }
164 }
165
166 // set the configuration of ten percent of the particles, the rest is not changed
167 void
169 double* pConfig)
170 {
171 if (nTenthIndex >= 0 && nTenthIndex <= 9)
172 {
173 for (int i = m_nParticles / 10 * nTenthIndex; i < m_nParticles / 10 * (nTenthIndex + 1);
174 i++)
175 for (int j = 0; j < m_nDimension; j++)
176 {
177 s[i][j] = pConfig[j];
178 }
179 }
180 }
181
182 // set the array containing the sensor values
183 void
185 {
186 for (int i = 0; i < m_nDimension; i++)
187 {
188 sensor_config[i] = sconfig[i];
189 lower_limit[i] = sensor_config[i] - allowed_deviation[i];
190 upper_limit[i] = sensor_config[i] + allowed_deviation[i];
191 }
192 }
193
194 // set the allowed deviation of the particle configs from the sensor values
195 void
197 {
198 for (int i = 0; i < m_nDimension; i++)
199 {
200 allowed_deviation[i] = adeviation[i];
201 sigma[i] = allowed_deviation[i] / 2;
202 }
203 }
204
205 // set the tracking ball position and size
206 void
208 double* dPosY,
209 double* dRadius,
210 int nNumTrBallRegions,
211 bool bLeftCamImage)
212 {
213 if (bLeftCamImage)
214 {
218 m_nNumTrackingBallRegionsLeft = nNumTrBallRegions;
219 }
220 else
221 {
225 m_nNumTrackingBallRegionsRight = nNumTrBallRegions;
226 }
227 }
228
229 //******************************************************************************************************************
230 // Update the hand model according to the configuration nParticleIndex
231 //******************************************************************************************************************
232
233 void
234 CParticleFilterRobotHandLocalisation::UpdateModel(int nParticleIndex, int nModelIndex)
235 {
236 //printf("UpdateModel(%d)\n", nParticleIndex);
237 m_pHandModels[nModelIndex]->UpdateHand(s[nParticleIndex]);
238 }
239
240 //******************************************************************************************************************
241 // Predict new bases from the old ones. dSigmaFactor will be multiplied with all sigma[i] values
242 //******************************************************************************************************************
243
244 void
246 {
247 //printf("PredictNewBases\n");
248
249#pragma omp parallel for
250 for (int nNewIndex = 0; nNewIndex < m_nParticles; nNewIndex++)
251 {
252 int nOldIndex = PickBaseSample();
253
254 for (int i = 0; i < m_nDimension; i++)
255 {
256 double dNewValue = s[nOldIndex][i] + dSigmaFactor * sigma[i] * gaussian_random();
257 s_temp[nNewIndex][i] =
258 (dNewValue >= lower_limit[i] && dNewValue <= upper_limit[i])
259 ? dNewValue
260 : (0.7 * 0.5 * (lower_limit[i] + upper_limit[i]) + 0.3 * s[nOldIndex][i] +
261 0.5 * dSigmaFactor * sigma[i] * gaussian_random());
262 }
263 }
264
265 // switch old/new
266 double** temp = s_temp;
267 s_temp = s;
268 s = temp;
269 }
270
271 //******************************************************************************************************************
272 // Functions for the region cue
273 //******************************************************************************************************************
274
275 // sum up all pixel values of m_pRegionImageLeft that are inside the polygon pol, and count the number
276 // of pixels inside the polygon
277 inline void
280 int& region_sum,
281 int& region_length,
282 bool bLeftCamImage)
283 {
284 CByteImage* pImage = (bLeftCamImage) ? m_pRegionImageLeft : m_pRegionImageRight;
285 const int width = pImage->width;
286
287 int leftBorderInt, rightBorderInt, up, down, indexLeft, indexRight, indexMain, nTempOffset;
288 float leftBorder = 0, rightBorder = 0, leftOffset = 0, rightOffset = 0;
289
290 region_sum = 0;
291 region_length = 0;
292
293 indexLeft = 1;
294 indexRight = 1;
295 for (indexMain = 0; indexMain < pol->nCorners - 1; indexMain++)
296 {
297 if (pol->hull[indexMain].z != 2) // if this is not a right border point, we have
298 {
299 // to change left border and offset
300 leftBorder = pol->hullLeft[indexLeft].x;
301 leftOffset = (pol->hullLeft[indexLeft + 1].x - pol->hullLeft[indexLeft].x) /
302 (pol->hullLeft[indexLeft + 1].y - pol->hullLeft[indexLeft].y);
303 }
304
305 if (pol->hull[indexMain].z != 1) // if this is not a left border point, we have
306 {
307 // to change right border and offset
308 rightBorder = pol->hullRight[indexRight].x;
309 rightOffset = (pol->hullRight[indexRight + 1].x - pol->hullRight[indexRight].x) /
310 (pol->hullRight[indexRight + 1].y - pol->hullRight[indexRight].y);
311 }
312
313 up = (int)pol->hull[indexMain].y;
314 down = (int)pol->hull[indexMain + 1].y;
315
316 if (pol->hull[indexMain + 1].z != 2)
317 {
318 indexLeft++;
319 }
320 if (pol->hull[indexMain + 1].z != 1)
321 {
322 indexRight++;
323 }
324
325 if ((down > DSHT_IMAGE_HEIGHT - 1) || (up < 0))
326 {
327 goto skip_updown; // not in the image
328 }
329
330 // stay inside image
331 if (down < 0)
332 {
333 down = 0;
334 }
335 if (up > DSHT_IMAGE_HEIGHT - 1)
336 {
337 up = DSHT_IMAGE_HEIGHT - 1;
338 }
339
340 for (int j = up; j > down; j--, leftBorder -= leftOffset, rightBorder -= rightOffset)
341 {
342 // optim: width/2 sofort dazuaddieren
343 leftBorderInt = (int)leftBorder;
344 rightBorderInt = (int)rightBorder;
345
346 // stay inside image
347 if ((leftBorderInt > DSHT_IMAGE_WIDTH - 1) || (rightBorderInt < 0))
348 {
349 goto skip_leftright;
350 }
351
352 if (leftBorderInt < 0)
353 {
354 leftBorderInt = 0;
355 }
356 if (rightBorderInt > DSHT_IMAGE_WIDTH - 1)
357 {
358 rightBorderInt = DSHT_IMAGE_WIDTH - 1;
359 }
360
361 nTempOffset = j * width;
362
363 for (int k = leftBorderInt; k < rightBorderInt; k++)
364 {
365 region_sum += pImage->pixels[nTempOffset + k];
366 region_length++;
367 }
368 skip_leftright:;
369 }
370 skip_updown:;
371 }
372 }
373
374 // calculate the region cue
375 void
377 int& region_length,
378 int nModelIndex,
379 bool bLeftCamImage)
380 {
381 const int num_polygons = 5;
382 ConvexPolygonCalculations::Polygon* polygons[num_polygons];
383
384 if (bLeftCamImage)
385 {
386 for (int i = 0; i < num_polygons; i++)
387 {
388 polygons[i] = &m_pHandModels[nModelIndex]->m_aFingerTipPolygonsLeftCam.at(i);
389 }
390 }
391 else
392 {
393 for (int i = 0; i < num_polygons; i++)
394 {
395 polygons[i] = &m_pHandModels[nModelIndex]->m_aFingerTipPolygonsRightCam.at(i);
396 }
397 }
398
399 region_sum = 0;
400 region_length = 0;
401
402 int polygon_interior_sum, polygon_interior_size;
403
404
405 // sum up the pixels of correct color inside the fingertip polygons
406
407 for (int i = 0; i < num_polygons; i++)
408 {
410 polygons[i], polygon_interior_sum, polygon_interior_size, bLeftCamImage);
411 region_sum += polygon_interior_sum;
412 region_length += polygon_interior_size;
413 }
414
415
416 // subtract intersection regions which may have been counted two times
417
418 for (int i = 1; i < num_polygons; i++) // thumb with all other fingers
419 {
420 if (PolygonsMightIntersect(polygons[0], polygons[i]))
421 {
423 polygons[0],
424 polygons[i],
425 m_pTempIntersectionPolygons[nModelIndex],
426 m_pTempVecArrays[nModelIndex],
427 m_pTempBoolArrays[nModelIndex],
428 m_pTempClockwiseHullPolys1[nModelIndex],
429 m_pTempClockwiseHullPolys2[nModelIndex]);
431 polygon_interior_sum,
432 polygon_interior_size,
433 bLeftCamImage);
434 region_sum -= polygon_interior_sum;
435 region_length -= polygon_interior_size;
436 }
437 }
438
439 for (int i = 1; i < num_polygons - 1;
440 i++) // every other fingers only with its direct neighbour, to reduce
441 {
442 // multiple subtraction of overlapping intersection regions
443 if (PolygonsMightIntersect(polygons[i], polygons[i + 1]))
444 {
446 polygons[i],
447 polygons[i + 1],
448 m_pTempIntersectionPolygons[nModelIndex],
449 m_pTempVecArrays[nModelIndex],
450 m_pTempBoolArrays[nModelIndex],
451 m_pTempClockwiseHullPolys1[nModelIndex],
452 m_pTempClockwiseHullPolys2[nModelIndex]);
454 polygon_interior_sum,
455 polygon_interior_size,
456 bLeftCamImage);
457 region_sum -= polygon_interior_sum;
458 region_length -= polygon_interior_size;
459 }
460 }
461
462 // keep index and ringfinger from fusioning
463 if (PolygonsMightIntersect(polygons[1], polygons[3]))
464 {
466 polygons[1],
467 polygons[3],
468 m_pTempIntersectionPolygons[nModelIndex],
469 m_pTempVecArrays[nModelIndex],
470 m_pTempBoolArrays[nModelIndex],
471 m_pTempClockwiseHullPolys1[nModelIndex],
472 m_pTempClockwiseHullPolys2[nModelIndex]);
474 polygon_interior_sum,
475 polygon_interior_size,
476 bLeftCamImage);
477 region_sum -= polygon_interior_sum;
478 region_length -= polygon_interior_size;
479 }
480 }
481
482 //******************************************************************************************************************
483 // Functions for the edge cue
484 //******************************************************************************************************************
485
486 // sum up the pixel values on a sequence of lines
487 inline void
489 int nPoints,
490 int& edge_sum,
491 int& edge_length,
492 double& angle_diffs,
493 bool bLeftCamImage)
494 {
495 int up, down, left, right, lineSum;
496 double xOffset, xDiff, yOffset, yDiff, lineLength;
497
498#ifdef DSHT_USE_EDGE_DIRECTION
499 int absVal;
500 double angleSum, normalX, normalY;
501#endif // DSHT_USE_EDGE_DIRECTION
502
503 edge_sum = 0;
504 edge_length = 0;
505 angle_diffs = 0;
506
507 CByteImage* pImage = (bLeftCamImage) ? m_pSobelImageLeft : m_pSobelImageRight;
508 const int width = pImage->width;
509
510 for (int i = 0; i < nPoints - 1; i++)
511 {
512 lineSum = 0;
513
514 lineLength = sqrt(
515 (linePoints[i + 1].x - linePoints[i].x) * (linePoints[i + 1].x - linePoints[i].x) +
516 (linePoints[i + 1].y - linePoints[i].y) * (linePoints[i + 1].y - linePoints[i].y));
517
518#ifdef DSHT_USE_EDGE_DIRECTION
519 angleSum = 0;
520 normalX = (linePoints[i + 1].y -
521 linePoints[i].y); // / lineLength is not done, because at the end the sum
522 normalY =
523 -(linePoints[i + 1].x - linePoints[i].x); // has to be multiplied with lineLength
524#endif // DSHT_USE_EDGE_DIRECTION
525
526 if (linePoints[i].y > linePoints[i + 1].y)
527 {
528 up = (int)linePoints[i].y;
529 down = (int)linePoints[i + 1].y;
530 xOffset = linePoints[i + 1].x;
531 }
532 else
533 {
534 up = (int)linePoints[i + 1].y;
535 down = (int)linePoints[i].y;
536 xOffset = linePoints[i].x;
537 }
538
539 if (linePoints[i].x > linePoints[i + 1].x)
540 {
541 right = (int)linePoints[i].x;
542 left = (int)linePoints[i + 1].x;
543 yOffset = linePoints[i + 1].y;
544 }
545 else
546 {
547 right = (int)linePoints[i + 1].x;
548 left = (int)linePoints[i].x;
549 yOffset = linePoints[i].y;
550 }
551
552 if (up < DSHT_IMAGE_HEIGHT && down >= 0 && left >= 0 && right < DSHT_IMAGE_WIDTH)
553 {
554 xDiff = (linePoints[i + 1].x - linePoints[i].x) /
555 (linePoints[i + 1].y - linePoints[i].y);
556 yDiff = (linePoints[i + 1].y - linePoints[i].y) /
557 (linePoints[i + 1].x - linePoints[i].x);
558
559#ifdef DSHT_USE_EDGE_DIRECTION
560 for (int j = down; j < up; j++, xOffset += xDiff)
561 {
562 absVal = pImage->pixels[j * width + (int)xOffset];
563 lineSum += absVal;
564 angleSum += abs(((double)pImage->pixels[j * width + (int)xOffset] * normalX +
565 (double)pImage->pixels[j * width + (int)xOffset] * normalY) /
566 ((double)absVal + 0.001));
567 }
568
569
570 for (int j = left; j < right; j++, yOffset += yDiff)
571 {
572 absVal = pImage->pixels[((int)yOffset) * width + j];
573 lineSum += absVal;
574 angleSum += abs(((double)pImage->pixels[((int)yOffset) * width + j] * normalX +
575 (double)pImage->pixels[((int)yOffset) * width + j] * normalY) /
576 ((double)absVal + 0.001));
577 }
578
579 edge_length += (int)lineLength;
580 // set weight congruent to line length
581 edge_sum += (int)((double)lineSum * lineLength /
582 ((double)(up - down + right - left) + 0.001));
583 angle_diffs += angleSum / ((double)(up - down + right - left) +
584 0.001); // no *lineLength, because no
585 // /linelength done at normal calculation
586#else
587 for (int j = down; j < up; j++, xOffset += xDiff)
588 {
589 lineSum += pImage->pixels[j * width + (int)xOffset];
590 }
591
592 for (int j = left; j < right; j++, yOffset += yDiff)
593 {
594 lineSum += pImage->pixels[((int)yOffset) * width + j];
595 }
596
597 edge_length += (int)lineLength;
598 // set weight congruent to line length
599 edge_sum += (int)((double)lineSum * lineLength /
600 ((double)(up - down + right - left) + 0.001));
601#endif // DSHT_USE_EDGE_DIRECTION (else)
602 }
603 }
604 }
605
606 // calculate the edge cue
607 void
609 int& edge_length,
610 double& angle_diffs,
611 int nModelIndex,
612 bool bLeftCamImage)
613 {
614 const int num_polygons = 5;
615 ConvexPolygonCalculations::Polygon* polygons[num_polygons];
616
617 if (bLeftCamImage)
618 {
619 for (int i = 0; i < num_polygons; i++)
620 {
621 polygons[i] = &m_pHandModels[nModelIndex]->m_aFingerTipPolygonsLeftCam.at(i);
622 }
623 }
624 else
625 {
626 for (int i = 0; i < num_polygons; i++)
627 {
628 polygons[i] = &m_pHandModels[nModelIndex]->m_aFingerTipPolygonsRightCam.at(i);
629 }
630 }
631
632 int temp_edge_sum, temp_edge_length;
633 double temp_angle_diffs;
634 edge_sum = 0;
635 edge_length = 0;
636 angle_diffs = 0;
637
638 for (int i = 0; i < num_polygons; i++)
639 {
640 CalculatePixelSumOnLineSequence(polygons[i]->hullCircle,
641 polygons[i]->nCorners + 1,
642 temp_edge_sum,
643 temp_edge_length,
644 temp_angle_diffs,
645 bLeftCamImage);
646 edge_sum += temp_edge_sum;
647 edge_length += temp_edge_length;
648 angle_diffs += temp_angle_diffs;
649 }
650 }
651
652 //******************************************************************************************************************
653 // Calculate error distance to tracking ball
654 //******************************************************************************************************************
655
656
657 // calculate error distance to tracking ball
658 void
660 double& dDistanceZ,
661 int nModelIndex)
662 {
663 double dPosX, dPosY, dRadius;
664
665 double dMinDistance;
666 int nMinIndex;
667 double dTempDist;
668
669
670 // left image
671
672 dPosX = m_pHandModels[nModelIndex]->m_vTrackingBallPosLeftCam.x;
673 dPosY = m_pHandModels[nModelIndex]->m_vTrackingBallPosLeftCam.y;
674 dRadius = m_pHandModels[nModelIndex]->m_fTrackingBallRadiusLeftCam;
675
676 nMinIndex = 0;
677 dMinDistance = 1000000000;
678
679 for (int i = 0; i < m_nNumTrackingBallRegionsLeft; i++)
680 {
681 dTempDist =
682 (m_pdTrackingBallPosXLeft[i] - dPosX) * (m_pdTrackingBallPosXLeft[i] - dPosX) +
683 (m_pdTrackingBallPosYLeft[i] - dPosY) * (m_pdTrackingBallPosYLeft[i] - dPosY);
684 if (dTempDist < dMinDistance)
685 {
686 dMinDistance = dTempDist;
687 nMinIndex = i;
688 }
689 }
690
691 dDistanceXY = sqrt((m_pdTrackingBallPosXLeft[nMinIndex] - dPosX) *
692 (m_pdTrackingBallPosXLeft[nMinIndex] - dPosX) +
693 (m_pdTrackingBallPosYLeft[nMinIndex] - dPosY) *
694 (m_pdTrackingBallPosYLeft[nMinIndex] - dPosY));
695
696 dDistanceZ = fabs(1 / m_pdTrackingBallRadiusLeft[nMinIndex] - 1 / dRadius);
697 if (std::isnan(dDistanceZ))
698 {
699 dDistanceZ = FLT_MAX;
700 }
701
702
703 // right image
704
705 dPosX = m_pHandModels[nModelIndex]->m_vTrackingBallPosRightCam.x;
706 dPosY = m_pHandModels[nModelIndex]->m_vTrackingBallPosRightCam.y;
707 dRadius = m_pHandModels[nModelIndex]->m_fTrackingBallRadiusRightCam;
708
709 nMinIndex = 0;
710 dMinDistance = 1000000000;
711
712 for (int i = 0; i < m_nNumTrackingBallRegionsRight; i++)
713 {
714 dTempDist =
715 (m_pdTrackingBallPosXRight[i] - dPosX) * (m_pdTrackingBallPosXRight[i] - dPosX) +
716 (m_pdTrackingBallPosYRight[i] - dPosY) * (m_pdTrackingBallPosYRight[i] - dPosY);
717 if (dTempDist < dMinDistance)
718 {
719 dMinDistance = dTempDist;
720 nMinIndex = i;
721 }
722 }
723
724 // dDistanceXY += sqrt ( (m_pdTrackingBallPosXRight[nMinIndex]-dPosX)*(m_pdTrackingBallPosXRight[nMinIndex]-dPosX)
725 // + (m_pdTrackingBallPosYRight[nMinIndex]-dPosY)*(m_pdTrackingBallPosYRight[nMinIndex]-dPosY)
726 // );
727
728 // dDistanceZ += fabs(1/m_pdTrackingBallRadiusRight[nMinIndex]-1/dRadius);
729 }
730
731 //******************************************************************************************************************
732 // Evaluation and rating of the particles
733 //******************************************************************************************************************
734
735
736 // calculate the preliminary probabilities for the different cues
737 double
739 {
740 //printf("CalculateProbability 1\n");
741
742 int nRegionSumLeftImg, nRegionLengthLeftImg, nEdgeSumLeftImg, nEdgeLengthLeftImg;
743 int nRegionSumRightImg, nRegionLengthRightImg, nEdgeSumRightImg, nEdgeLengthRightImg;
744 double fAngleDiffsLeftImg, fAngleDiffsRightImg;
745
746 CalculateRegionCue(nRegionSumLeftImg, nRegionLengthLeftImg, nModelIndex, true);
747 CalculateRegionCue(nRegionSumRightImg, nRegionLengthRightImg, nModelIndex, false);
748
749 //printf("CalculateProbability 2\n");
750
752 nEdgeSumLeftImg, nEdgeLengthLeftImg, fAngleDiffsLeftImg, nModelIndex, true);
754 nEdgeSumRightImg, nEdgeLengthRightImg, fAngleDiffsRightImg, nModelIndex, false);
755
756 double dTrBallDistXY, dTrBallDistZ;
757 CalculateTrackingBallCue(dTrBallDistXY, dTrBallDistZ, nModelIndex);
758
759 //printf("CalculateProbability 3\n");
760
761 m_ppProbabilities[0][nParticleIndex] = 0.5 * (nRegionSumLeftImg + nRegionSumRightImg);
762 m_ppProbabilities[1][nParticleIndex] =
763 (double)(nRegionSumLeftImg + nRegionSumRightImg) /
764 ((double)(nRegionLengthLeftImg + nRegionLengthRightImg) + 0.001);
765
766 m_ppProbabilities[2][nParticleIndex] = 0.5 * (nEdgeSumLeftImg + nEdgeSumRightImg);
767 m_ppProbabilities[3][nParticleIndex] =
768 (double)(nEdgeSumLeftImg + nEdgeSumRightImg) /
769 ((double)(nEdgeLengthLeftImg + nEdgeLengthRightImg) + 0.001);
770#ifdef DSHT_USE_EDGE_DIRECTION
771 m_ppProbabilities[4][nParticleIndex] = -(fAngleDiffsLeftImg + fAngleDiffsRightImg) /
772 ((double)(nEdgeLengthLeftImg + nEdgeLengthRightImg) +
773 0.001); // TODO: find out if sign is correct
774#else
775 m_ppProbabilities[4][nParticleIndex] = 0;
776#endif // DSHT_USE_EDGE_DIRECTION
777
778 m_ppProbabilities[5][nParticleIndex] = -dTrBallDistXY;
779 m_ppProbabilities[6][nParticleIndex] = 0; //- dTrBallDistZ;
780
781 return (double)(nRegionSumLeftImg / 255) +
782 ((double)nRegionSumLeftImg / ((double)(nRegionLengthLeftImg * 255) + 0.001));
783 }
784
785 // calculate the real probabilities for the particles by normalizing the preliminary ones and giving
786 // specific weights to the different cues
787 void
789 {
790 //printf("CalculateFinalProbabilities 1\n");
791
792 // normalisation of the probabilities to the interval [0,1]
793 for (int i = 0; i < NUMBER_OF_CUES; i++)
794 {
795 double min = 99999999;
796 double max = -99999999;
797
798 for (int j = 0; j < m_nParticles; j++)
799 {
800 if (m_ppProbabilities[i][j] != m_ppProbabilities[i][j])
801 {
802 m_ppProbabilities[i][j] = 0;
803 }
804
805 if (m_ppProbabilities[i][j] < min)
806 {
807 min = m_ppProbabilities[i][j];
808 }
809
810 if (m_ppProbabilities[i][j] > max)
811 {
812 max = m_ppProbabilities[i][j];
813 }
814 }
815
816 if (max != min)
817 {
818 for (int j = 0; j < m_nParticles; j++)
819 {
820 m_ppProbabilities[i][j] = (m_ppProbabilities[i][j] - min) / (max - min);
821 }
822 }
823
824 m_pProbMin[i] = min;
825 m_pProbMax[i] = max;
826 }
827
828
829//debug
830//double xSum=0, ySum=0, fDistSum=0;
831
832// weightet influence of the different cues on the final probability
833#pragma omp parallel for
834 for (int j = 0; j < m_nParticles; j++)
835 {
836#ifdef DSHT_USE_EDGE_DIRECTION
837 pi[j] = exp(15.0 / 31.0 *
838 (6 * m_ppProbabilities[0][j] + 6 * m_ppProbabilities[1][j] +
839 1 * m_ppProbabilities[2][j] + 1 * m_ppProbabilities[3][j] +
840 2 * m_ppProbabilities[4][j] + 10 * m_ppProbabilities[5][j] +
841 5 * m_ppProbabilities[6][j])) -
842 0.95;
843#else
844 pi[j] = exp(15.0 / 31.0 *
845 (6 * m_ppProbabilities[0][j] + 6 * m_ppProbabilities[1][j] +
846 2 * m_ppProbabilities[2][j] + 2 * m_ppProbabilities[3][j] +
847 10 * m_ppProbabilities[5][j] + 5 * m_ppProbabilities[6][j])) -
848 0.95;
849
850#endif // DSHT_USE_EDGE_DIRECTION
851
852 // pi[j] = exp( 15.0/29.0 * (
853 // 5 * m_ppProbabilities[0][j]
854 // + 5 * m_ppProbabilities[1][j]
855 // + 2 * m_ppProbabilities[2][j]
856 // + 2 * m_ppProbabilities[3][j]
857 // + 2 * m_ppProbabilities[4][j]
858 // + 10 * m_ppProbabilities[5][j]
859 // + 5 * m_ppProbabilities[6][j]
860 // )
861 // ) - 0.95;
862
863 // m_pHandModels[0]->UpdateHand(s[j]);
864 // double x,y,r;
865 // m_pHandModels[0]->GetTrackingBallPositionLeftCam(x, y, r);
866 // //printf("Particle %d: (%.1f, %.1f) %.3f\n", j, x, y, pi[j]);
867 // xSum += x;
868 // ySum += y;
869 // fDistSum += sqrt((x-m_pdTrackingBallPosXLeft[0])*(x-m_pdTrackingBallPosXLeft[0]) + (y-m_pdTrackingBallPosYLeft[0])*(y-m_pdTrackingBallPosYLeft[0]));
870
871 if (pi[j] != pi[j])
872 {
873 if (j % 100 == 0)
874 printf("pi[i] is nan! m_ppProbabilities[0][j] = %f, m_ppProbabilities[1][j] = "
875 "%f, m_ppProbabilities[2][j] = %f, m_ppProbabilities[3][j] = %f, "
876 "m_ppProbabilities[4][j] = %f, m_ppProbabilities[5][j] = %f, "
877 "m_ppProbabilities[6][j] = %f\n",
878 m_ppProbabilities[0][j],
879 m_ppProbabilities[1][j],
880 m_ppProbabilities[2][j],
881 m_ppProbabilities[3][j],
882 m_ppProbabilities[4][j],
883 m_ppProbabilities[5][j],
884 m_ppProbabilities[6][j]);
885 }
886 }
887
888 // debug
889 //printf("TrBallPos: (%.1f, %.1f)\n", m_pdTrackingBallPosXLeft[0], m_pdTrackingBallPosYLeft[0]);
890 //printf("Avg: (%.1f, %.1f) Dist: %.1f\n", xSum/m_nParticles, ySum/m_nParticles, fDistSum/m_nParticles);
891 }
892
893 void
895 DetailedPFRating* pRating)
896 {
897 //printf("GetDetailedRating 1\n");
898 int i;
899
900 // copy config
901 for (i = 0; i < m_nDimension; i++)
902 {
903 pRating->dResultConfig[i] = pConf[i];
904 }
905
906 // count number of white pixels in color segmented image
907 pRating->nNumberOfWhitePixelsInImage = 0;
908 for (i = 0; i < DSHT_IMAGE_WIDTH * DSHT_IMAGE_HEIGHT; i++)
909 {
910 pRating->nNumberOfWhitePixelsInImage += m_pRegionImageLeft->pixels[i] == 255;
911 }
912
913 // calculate the rating for the config
914 //ISO C++ forbids variable length array [-Werror=vla] => use a vector (the array will be on the heap anyways)
915 std::vector<double> temp(m_nDimension);
916 for (i = 0; i < m_nDimension; i++)
917 {
918 temp[i] = s[0][i];
919 s[0][i] = pConf[i];
920 }
921
922 UpdateModel(0);
923
924 for (i = 0; i < m_nDimension; i++)
925 {
926 s[0][i] = temp[i];
927 }
928
929 // color regions
930 int nRegionSum = 0;
931 int nRegionLength = 0;
932 CalculateRegionCue(nRegionSum, nRegionLength, 0, true);
933 pRating->nOverallNumberOfFoundPixels = nRegionSum / 255;
935 (double)nRegionSum / ((double)(nRegionLength * 255) + 0.001);
936
937 for (i = 0; i < DSHT_NUM_FINGERS; i++)
938 {
939 nRegionSum = 0;
940 nRegionLength = 0;
941 CalculatePixelSumInPolygon(&(m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(i)),
942 nRegionSum,
943 nRegionLength,
944 true);
945 pRating->nNumberOfFoundPixelsOfFinger[i] = nRegionSum / 255;
947 (double)nRegionSum / ((double)(nRegionLength * 255) + 0.001);
948 }
949
950 // edges
951 nRegionSum = 0;
952 nRegionLength = 0;
953 double dAngleDiffs = 0;
954 CalculateEdgeCue(nRegionSum, nRegionLength, dAngleDiffs, 0, true);
955 pRating->nEdgeSum = nRegionSum;
956 pRating->dEdgePercentage = (double)nRegionSum / ((double)nRegionLength + 0.001);
957 pRating->dEdgeDirection = dAngleDiffs / ((double)nRegionLength + 0.001);
958
959 // PF cue rating
961 for (i = 0; i < NUMBER_OF_CUES; i++)
962 {
963 if (m_pProbMax[i] != m_pProbMin[i])
964 {
965 m_ppProbabilities[i][0] =
966 (m_ppProbabilities[i][0] - m_pProbMin[i]) / (m_pProbMax[i] - m_pProbMin[i]);
967 }
968 }
969#ifdef DSHT_USE_EDGE_DIRECTION
970 pRating->dPFCueRating = 1.0 / 29.0 *
971 (5 * m_ppProbabilities[0][0] + 5 * m_ppProbabilities[1][0] +
972 1 * m_ppProbabilities[2][0] + 1 * m_ppProbabilities[3][0] +
973 2 * m_ppProbabilities[4][0] + 10 * m_ppProbabilities[5][0] +
974 5 * m_ppProbabilities[6][0]);
975#else
976 pRating->dPFCueRating = 1.0 / 29.0 *
977 (5 * m_ppProbabilities[0][0] + 5 * m_ppProbabilities[1][0] +
978 2 * m_ppProbabilities[2][0] + 2 * m_ppProbabilities[3][0] +
979 10 * m_ppProbabilities[5][0] + 5 * m_ppProbabilities[6][0]);
980#endif // DSHT_USE_EDGE_DIRECTION
981
982 // final rating
983
984 UpdateModel(0);
985
986 // index is closer than pinky
987 if (m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(1).center3d.z <
988 m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(4).center3d.z)
989 {
990 // thumb and index should be visible
991 if (abs(m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(0).center3d.z -
992 m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(1).center3d.z) <= 30)
993 {
994 pRating->dRating = 0.3 * pRating->dFoundPercentageOfExpectedPixelsOfFinger[0] +
997 0.1 * 1.0;
998 }
999 // thumb is in front
1000 else if (m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(0).center3d.z <
1001 m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(1).center3d.z + 30)
1002 {
1003 pRating->dRating = 0.4 * pRating->dFoundPercentageOfExpectedPixelsOfFinger[0] +
1005 0.1 * 0.0;
1006 }
1007 else // other fingers are in front
1008 {
1009 pRating->dRating = 0.2 * pRating->dFoundPercentageOfExpectedPixelsOfFinger[1] +
1011 0.1 * 0.0;
1012 }
1013 }
1014 else // pinky is closer than index
1015 {
1016 // thumb is in front
1017 if (m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(0).center3d.z <
1018 m_pHandModels[0]->m_aFingerTipPolygonsLeftCam.at(4).center3d.z + 30)
1019 {
1020 pRating->dRating = 0.4 * pRating->dFoundPercentageOfExpectedPixelsOfFinger[0] +
1022 0.1 * 0.0;
1023 }
1024 else // other fingers are in front
1025 {
1026 pRating->dRating =
1027 0.8 * pRating->dOverallFoundPercentageOfExpectedPixels + 0.2 * 0.0;
1028 }
1029 }
1030
1031
1032 // enough pixels found for a good estimation? -> confidence of the rating
1033 if (pRating->nNumberOfWhitePixelsInImage > 400)
1034 {
1035 pRating->dConfidenceOfRating = (double)pRating->nOverallNumberOfFoundPixels /
1036 (double)pRating->nNumberOfWhitePixelsInImage;
1037 if (pRating->nNumberOfWhitePixelsInImage < 1200)
1038 {
1039 pRating->dConfidenceOfRating *=
1040 (double)pRating->nNumberOfWhitePixelsInImage / 1200.0;
1041 }
1042 }
1043 else
1044 {
1045 pRating->dConfidenceOfRating = 0;
1046 }
1047 }
1048
1049 double
1051 {
1052 double result = 0;
1053 for (int i = 0; i < 6; i++)
1054 {
1055 result += (pNewConf[i] - pOldConf[i]) * (pNewConf[i] - pOldConf[i]) /
1057 }
1058 for (int i = 6; i < m_nDimension; i++)
1059 {
1060 result += 0.1 * (pNewConf[i] - pOldConf[i]) * (pNewConf[i] - pOldConf[i]) /
1062 }
1063 return sqrt(result);
1064 }
1065} // namespace visionx
#define pi
#define DSHT_IMAGE_HEIGHT
#define DSHT_MAX_POLYGON_CORNERS
#define DSHT_NUM_FINGERS
#define DSHT_IMAGE_WIDTH
CParticleFilterFrameworkParallelized(int nParticles, int nDimension, int nNumParallelThreads=1)
void SetImages(CByteImage *pRegionImageLeft, CByteImage *pRegionImageRight, CByteImage *pSobelImageLeft, CByteImage *pSobelImageRight, CByteImage *pSobelXImageLeft, CByteImage *pSobelXImageRight, CByteImage *pSobelYImageLeft, CByteImage *pSobelYImageRight)
void SetConfigOfATenthOfTheParticles(int nTenthIndex, double *pConfig)
void CalculatePixelSumInPolygon(ConvexPolygonCalculations::Polygon *pol, int &region_sum, int &region_length, bool bLeftCamImage)
double CalculateProbability(int nParticleIndex, int nModelIndex) override
double DistanceBetweenConfigs(double *pOldConf, double *pNewConf)
CParticleFilterRobotHandLocalisation(int nParticles, int nDimension, int nNumParallelThreads, CStereoCalibration *pCalibration, std::string sHandModelFileName)
void SetTrackingBallPositions(double *dPosX, double *dPosY, double *dRadius, int nNumTrBallRegions, bool bLeftCamImage)
void CalculateTrackingBallCue(double &dDistanceXY, double &dDistanceZ, int nModelIndex)
void CalculateRegionCue(int &region_sum, int &region_length, int nModelIndex, bool bLeftCamImage)
void CalculatePixelSumOnLineSequence(Vec3d linePoints[], int nPoints, int &edge_sum, int &edge_length, double &angle_diffs, bool bLeftCamImage)
void UpdateModel(int nParticleIndex, int nModelIndex) override
void GetDetailedRating(double *pConf, DetailedPFRating *pRating)
void CalculateEdgeCue(int &edge_sum, int &edge_length, double &angle_diffs, int nModelIndex, bool bLeftCamImage)
T min(T t1, T t2)
Definition gdiam.h:44
T max(T t1, T t2)
Definition gdiam.h:51
This file offers overloads of toIce() and fromIce() functions for STL container types.
void GetPolygonIntersection(Polygon *p1, Polygon *p2, Polygon *pInter, Vec3d *pointAccu, bool *boolTable, Vec3d *clockwiseHullPoly1, Vec3d *clockwiseHullPoly2)
Definition Polygon.cpp:428
ArmarX headers.
const double DSHT_default_allowed_deviation[12]
Vec3d hull[2 *DSHT_MAX_POLYGON_CORNERS]
Definition Polygon.h:37
Vec3d hullLeft[2 *DSHT_MAX_POLYGON_CORNERS+1]
Definition Polygon.h:49
Vec3d hullRight[2 *DSHT_MAX_POLYGON_CORNERS+1]
Definition Polygon.h:52
double dFoundPercentageOfExpectedPixelsOfFinger[DSHT_NUM_FINGERS]