30 #include <Image/ByteImage.h>
31 #include <Image/ImageProcessor.h>
32 #include <Features/SIFTFeatures/SIFTFeatureEntry.h>
33 #include <Features/SIFTFeatures/SIFTFeatureCalculator.h>
34 #include <Calibration/Calibration.h>
35 #include "Math/LinearAlgebra.h"
36 #include "Math/FloatMatrix.h"
37 #include "Math/FloatVector.h"
54 this->calibration = calibration;
57 m_pSIFTFeatureCalculator =
new CSIFTFeatureCalculator();
73 lccpSegmentation1 =
new LCCPSegmentationWrapper(6, 15.0, 0.0, 1.0, 4.0,
false, 10.0, 0.1, 0,
false,
true, 800);
74 lccpSegmentation2 =
new LCCPSegmentationWrapper(15, 26.0, 0.0, 1.0, 4.0,
false, 10.0, 0.1, 0,
false,
true, 800);
93 delete m_pSIFTFeatureCalculator;
94 delete m_pSaliencyImage;
95 delete m_pHypothesesCoveringImage;
96 delete m_pSaliencyHypothesisRegionsImage;
97 delete m_pTempImageGray;
100 delete lccpSegmentation1;
101 delete lccpSegmentation2;
111 CSIFTFeatureArray& aAllSIFTPoints, std::vector<CMSERDescriptor3D*>& aAllMSERs, std::vector<CHypothesisPoint*>& aPointsFromDisparity,
116 omp_set_nested(
true);
118 timeval tStartAll, tEndAll;
119 timeval tStart, tEnd;
121 gettimeofday(&tStartAll, 0);
128 m_vFeaturePoints3d.Clear();
132 for (
int i = 0; i < aAllSIFTPoints.GetSize(); i++)
134 m_vFeaturePoints3d.AddElement(aAllSIFTPoints[i]->point3d);
141 SortMSERsByX(aAllMSERs);
143 std::vector<Vec3d> aMSERSigmaPoints;
146 for (
int i = 0; i < (int)aAllMSERs.size(); i++)
148 m_vFeaturePoints3d.AddElement(aAllMSERs.at(i)->vPosition);
152 if (aAllMSERs.at(i)->pRegionLeft->fEigenvalue1 > 25.0f)
154 m_vFeaturePoints3d.AddElement(aAllMSERs.at(i)->vSigmaPoint1a);
155 m_vFeaturePoints3d.AddElement(aAllMSERs.at(i)->vSigmaPoint1b);
156 aMSERSigmaPoints.push_back(aAllMSERs.at(i)->vSigmaPoint1a);
157 aMSERSigmaPoints.push_back(aAllMSERs.at(i)->vSigmaPoint1b);
160 if (aAllMSERs.at(i)->pRegionLeft->fEigenvalue2 > 25.0f)
162 m_vFeaturePoints3d.AddElement(aAllMSERs.at(i)->vSigmaPoint2a);
163 m_vFeaturePoints3d.AddElement(aAllMSERs.at(i)->vSigmaPoint2b);
164 aMSERSigmaPoints.push_back(aAllMSERs.at(i)->vSigmaPoint2a);
165 aMSERSigmaPoints.push_back(aAllMSERs.at(i)->vSigmaPoint2b);
179 int nNumSingleColoredRegionHypotheses = 0;
181 #ifdef OLP_FIND_UNICOLORED_HYPOTHESES
183 gettimeofday(&tStart, 0);
186 const int nNumPoints = aPointsFromDisparity.size();
187 Vec2d* pDepthMapPoints2D =
new Vec2d[nNumPoints];
189 for (
int i = 0; i < nNumPoints; i++)
191 calibration->WorldToImageCoordinates(aPointsFromDisparity.at(i)->vPosition, pDepthMapPoints2D[i],
false);
195 std::vector<CMSERDescriptor3D*> aFilteredMSERs;
197 for (
size_t i = 0; i < aAllMSERs.size(); i++)
201 aFilteredMSERs.push_back(aAllMSERs.at(i));
206 SortMSERsBySize(aFilteredMSERs);
208 for (
size_t i = 0; i < aFilteredMSERs.size(); i++)
210 for (
size_t j = i + 1; j < aFilteredMSERs.size(); j++)
216 for (
size_t k = j + 1; k < aFilteredMSERs.size(); k++)
218 aFilteredMSERs.at(k - 1) = aFilteredMSERs.at(k);
221 aFilteredMSERs.pop_back();
228 const float fPixelDistanceTolerance2 = fPixelDistanceTolerance * fPixelDistanceTolerance;
229 #pragma omp parallel for schedule (dynamic, 1)
230 for (
size_t i = 0; i < aFilteredMSERs.size(); i++)
237 const std::vector<Vec2d>* pRegionPoints = aFilteredMSERs.at(i)->pRegionLeft->pPoints2D;
240 float minX = pRegionPoints->at(0).x;
241 float minY = pRegionPoints->at(0).y;
242 float maxX = pRegionPoints->at(0).x;
243 float maxY = pRegionPoints->at(0).y;
245 for (
size_t k = 1; k < pRegionPoints->size(); k++)
247 minX = (pRegionPoints->at(k).x < minX) ? pRegionPoints->at(k).x : minX;
248 minY = (pRegionPoints->at(k).y < minY) ? pRegionPoints->at(k).y : minY;
249 maxX = (pRegionPoints->at(k).x > maxX) ? pRegionPoints->at(k).x : maxX;
250 maxY = (pRegionPoints->at(k).y > maxY) ? pRegionPoints->at(k).y : maxY;
253 minX -= fPixelDistanceTolerance;
254 minY -= fPixelDistanceTolerance;
255 maxX += fPixelDistanceTolerance;
256 maxY += fPixelDistanceTolerance;
258 CVec3dArray pNewColorHypothesisPoints;
260 for (
int j = 0; j < nNumPoints; j++)
262 const float x = pDepthMapPoints2D[j].x;
263 const float y = pDepthMapPoints2D[j].y;
265 if (minX < x && minY < y && x < maxX && y < maxY)
268 for (
size_t k = 0; k < pRegionPoints->size(); k++)
270 if ((x - pRegionPoints->at(k).x) * (x - pRegionPoints->at(k).x) + (y - pRegionPoints->at(k).y) * (y - pRegionPoints->at(k).y) < fPixelDistanceTolerance2)
272 pNewColorHypothesisPoints.AddElement(aPointsFromDisparity.at(j)->vPosition);
285 for (
int j = 0; j < pNewColorHypothesisPoints.GetSize(); j++)
287 paSingleColoredRegions[nNumSingleColoredRegionHypotheses].AddElement(pNewColorHypothesisPoints[j]);
290 nNumSingleColoredRegionHypotheses++;
293 pNewColorHypothesisPoints.Clear();
298 gettimeofday(&tEnd, 0);
299 tTimeDiff = (1000 * tEnd.tv_sec + tEnd.tv_usec / 1000) - (1000 * tStart.tv_sec + tStart.tv_usec / 1000);
301 ARMARX_VERBOSE_S <<
"Number of MSERs: " << aAllMSERs.size() <<
" total, " << aFilteredMSERs.size() <<
" unique MSERs. Found " << nNumSingleColoredRegionHypotheses <<
" unicolored object hypotheses. Took " << tTimeDiff <<
"ms.";
313 gettimeofday(&tStart, 0);
314 const int maxNumLccpHypotheses = 3000;
315 CVec3dArray* lccpSegmentPoints1 =
new CVec3dArray[maxNumLccpHypotheses];
316 CVec3dArray* lccpSegmentPoints2 =
new CVec3dArray[maxNumLccpHypotheses];
317 int nNumLCCPSegmentHypotheses1 = 0;
318 int nNumLCCPSegmentHypotheses2 = 0;
320 lccpSegmentation1->CreateHypothesesFromLCCPSegments(aPointsFromDisparity, maxNumLccpHypotheses, lccpSegmentPoints1, nNumLCCPSegmentHypotheses1);
321 lccpSegmentation2->CreateHypothesesFromLCCPSegments(aPointsFromDisparity, maxNumLccpHypotheses, lccpSegmentPoints2, nNumLCCPSegmentHypotheses2);
323 int nNumLCCPSegmentHypotheses = nNumLCCPSegmentHypotheses1 + nNumLCCPSegmentHypotheses2;
324 CVec3dArray* lccpSegmentPoints =
new CVec3dArray[nNumLCCPSegmentHypotheses];
325 for (
int i = 0; i < nNumLCCPSegmentHypotheses1; i++)
327 lccpSegmentPoints[i] = lccpSegmentPoints1[i];
329 for (
int i = 0; i < nNumLCCPSegmentHypotheses2; i++)
331 lccpSegmentPoints[nNumLCCPSegmentHypotheses1 + i] = lccpSegmentPoints2[i];
337 gettimeofday(&tEnd, 0);
338 tTimeDiff = (1000 * tEnd.tv_sec + tEnd.tv_usec / 1000) - (1000 * tStart.tv_sec + tStart.tv_usec / 1000);
339 ARMARX_VERBOSE_S <<
"Time for finding LCCP segments: " << tTimeDiff <<
" ms";
348 gettimeofday(&tStart, 0);
353 int nNumberOfPlanes = 0;
355 int nNumberOfPlanesAfterClustering = 0;
357 CVec3dArray** pPlanePointsAfterClustering =
new CVec3dArray*[nMaxNumberOfClustersPerPlane *
OLP_MAX_NUM_HYPOTHESES];
363 int nNumberOfCylinders = 0;
364 const int nMaxNumberOfClustersPerCylinder = nMaxNumberOfClustersPerPlane;
365 int nNumberOfCylindersAfterClustering = 0;
366 const float fBICFactorCylinders = fBICFactorPlanes;
367 CVec3dArray** pCylinderPointsAfterClustering =
new CVec3dArray*[nMaxNumberOfClustersPerCylinder *
OLP_MAX_NUM_HYPOTHESES];
370 float* pCylinderRadiusesAfterClustering =
new float[nMaxNumberOfClustersPerCylinder *
OLP_MAX_NUM_HYPOTHESES];
375 int nNumberOfSpheres = 0;
377 #ifdef OLP_FIND_PLANES
381 #ifdef OLP_FIND_CYLINDERS
383 const float fMaxCylinderRadius = 50.0f;
386 #ifdef OLP_FIND_SPHERES
389 const float fMaxSphereRadius = 80.0f;
393 bool bFoundObject =
true;
395 int nNumberOfPointsOnPlane, nNumberOfPointsOnSphere;
396 int nNumberOfPointsOnCylinder = 1000000;
401 #ifdef OLP_FIND_PLANES
403 bFoundPlane = RANSACPlane(m_vFeaturePoints3d, fRansacThresholdPlanes, nRansacIterationsPlanes, paPlanes[nNumberOfPlanes],
404 pPlaneNormals[nNumberOfPlanes], pPlaneDs[nNumberOfPlanes]);
405 nNumberOfPointsOnPlane = bFoundPlane ? paPlanes[nNumberOfPlanes].GetSize() : 0;
412 nNumberOfPointsOnPlane = 0;
415 #ifdef OLP_FIND_SPHERES
416 bFoundSphere = RANSACSphere(m_vFeaturePoints3d, fRansacThresholdSpheres, fMaxSphereRadius, nRansacIterationsSpheres,
417 paSpheres[nNumberOfSpheres], pSphereCenters[nNumberOfSpheres], pSphereRadiuses[nNumberOfSpheres]);
421 nNumberOfPointsOnSphere = (paSpheres[nNumberOfSpheres].GetSize() >
OLP_MIN_NUM_FEATURES) ? paSpheres[nNumberOfSpheres].GetSize() : 0;
425 nNumberOfPointsOnSphere = 0;
430 nNumberOfPointsOnSphere = 0;
433 #ifdef OLP_FIND_CYLINDERS
435 if ((nNumberOfPointsOnPlane < nNumberOfPointsOnCylinder) && (nNumberOfPointsOnSphere < nNumberOfPointsOnCylinder))
438 bFoundCylinder = RANSACCylinders2(m_vFeaturePoints3d, calibration, fRansacThresholdCylinders, fMaxCylinderRadius, paCylinders[nNumberOfCylinders],
439 pCylinderAxes[nNumberOfCylinders], pCylinderCenters[nNumberOfCylinders], pCylinderRadiuses[nNumberOfCylinders]);
443 nNumberOfPointsOnCylinder = (paCylinders[nNumberOfCylinders].GetSize() >
OLP_MIN_NUM_FEATURES) ? paCylinders[nNumberOfCylinders].GetSize() : 0;
447 nNumberOfPointsOnCylinder = 0;
456 nNumberOfPointsOnCylinder = 0;
461 if ((nNumberOfPointsOnCylinder > nNumberOfPointsOnPlane) && (nNumberOfPointsOnCylinder > nNumberOfPointsOnSphere))
463 RemoveOutliers(paCylinders[nNumberOfCylinders], 1.7f, NULL);
466 std::vector<CVec3dArray*> aaPointClusters;
467 ClusterXMeans(paCylinders[nNumberOfCylinders], nMaxNumberOfClustersPerCylinder, fBICFactorCylinders, aaPointClusters);
470 for (
int i = 0; i < (int)aaPointClusters.size(); i++)
472 RemoveOutliers(*aaPointClusters.at(i), 1.7f, NULL);
476 if (aaPointClusters.at(i)->GetSize() / GetVariance(*aaPointClusters.at(i), vTemp) > 0.004f)
478 pCylinderPointsAfterClustering[nNumberOfCylindersAfterClustering] = aaPointClusters.at(i);
479 pCylinderAxesAfterClustering[nNumberOfCylindersAfterClustering] = pCylinderAxes[nNumberOfCylinders];
480 pCylinderCentersAfterClustering[nNumberOfCylindersAfterClustering] = pCylinderCenters[nNumberOfCylinders];
481 pCylinderRadiusesAfterClustering[nNumberOfCylindersAfterClustering] = pCylinderRadiuses[nNumberOfCylinders];
484 for (
int j = 0; j < pCylinderPointsAfterClustering[nNumberOfCylindersAfterClustering]->GetSize(); j++)
486 for (
int k = 0; k < m_vFeaturePoints3d.GetSize(); k++)
488 if (m_vFeaturePoints3d[k].x == (*pCylinderPointsAfterClustering[nNumberOfCylindersAfterClustering])[j].x
489 && m_vFeaturePoints3d[k].y == (*pCylinderPointsAfterClustering[nNumberOfCylindersAfterClustering])[j].y
490 && m_vFeaturePoints3d[k].z == (*pCylinderPointsAfterClustering[nNumberOfCylindersAfterClustering])[j].z)
492 const int nEnd = m_vFeaturePoints3d.GetSize() - 1;
493 m_vFeaturePoints3d[k] = m_vFeaturePoints3d[nEnd];
494 m_vFeaturePoints3d.DeleteElement(nEnd);
500 nNumberOfCylindersAfterClustering++;
505 aaPointClusters.clear();
509 nNumberOfCylinders++;
511 else if (nNumberOfPointsOnSphere > nNumberOfPointsOnPlane)
513 RemoveOutliers(paSpheres[nNumberOfSpheres], 1.6f, NULL);
518 for (
int j = 0; j < paSpheres[nNumberOfSpheres].GetSize(); j++)
520 for (
int l = 0; l < m_vFeaturePoints3d.GetSize(); l++)
522 if (m_vFeaturePoints3d[l].x == paSpheres[nNumberOfSpheres][j].x
523 && m_vFeaturePoints3d[l].y == paSpheres[nNumberOfSpheres][j].y
524 && m_vFeaturePoints3d[l].z == paSpheres[nNumberOfSpheres][j].z)
526 const int nEnd = m_vFeaturePoints3d.GetSize() - 1;
527 m_vFeaturePoints3d[l] = m_vFeaturePoints3d[nEnd];
528 m_vFeaturePoints3d.DeleteElement(nEnd);
537 else if (bFoundPlane)
539 RemoveOutliers(paPlanes[nNumberOfPlanes], 1.7f, NULL);
542 std::vector<CVec3dArray*> aaPointClusters;
543 ClusterXMeans(paPlanes[nNumberOfPlanes], nMaxNumberOfClustersPerPlane, fBICFactorPlanes, aaPointClusters);
546 for (
int i = 0; i < (int)aaPointClusters.size(); i++)
548 RemoveOutliers(*aaPointClusters.at(i), 1.7f, NULL);
549 RemoveOutliers(*aaPointClusters.at(i), 2.0f, NULL);
553 if (aaPointClusters.at(i)->GetSize() / GetVariance(*aaPointClusters.at(i), vTemp) > 0.004f)
555 pPlanePointsAfterClustering[nNumberOfPlanesAfterClustering] = aaPointClusters.at(i);
558 for (
int j = 0; j < pPlanePointsAfterClustering[nNumberOfPlanesAfterClustering]->GetSize(); j++)
560 for (
int k = 0; k < m_vFeaturePoints3d.GetSize(); k++)
562 if (m_vFeaturePoints3d[k].x == (*pPlanePointsAfterClustering[nNumberOfPlanesAfterClustering])[j].x
563 && m_vFeaturePoints3d[k].y == (*pPlanePointsAfterClustering[nNumberOfPlanesAfterClustering])[j].y
564 && m_vFeaturePoints3d[k].z == (*pPlanePointsAfterClustering[nNumberOfPlanesAfterClustering])[j].z)
566 const int nEnd = m_vFeaturePoints3d.GetSize() - 1;
567 m_vFeaturePoints3d[k] = m_vFeaturePoints3d[nEnd];
568 m_vFeaturePoints3d.DeleteElement(nEnd);
574 nNumberOfPlanesAfterClustering++;
579 aaPointClusters.clear();
587 bFoundObject =
false;
592 ARMARX_VERBOSE_S <<
"Found " << nNumberOfCylinders <<
" cylinders and " << nNumberOfPlanes <<
" planes (" << nNumberOfPlanesAfterClustering <<
" planes after clustering)";
594 gettimeofday(&tEnd, 0);
595 tTimeDiff = (1000 * tEnd.tv_sec + tEnd.tv_usec / 1000) - (1000 * tStart.tv_sec + tStart.tv_usec / 1000);
596 ARMARX_VERBOSE_S <<
"Time for finding planes, cylinders and spheres: " << tTimeDiff <<
" ms";
608 gettimeofday(&tStart, 0);
611 int nNumberOfUnstructuredClusters = 0;
612 CVec3dArray** pUnstructuredPointClusters = NULL;
613 #ifdef OLP_FIND_IRREGULAR_CLUSTERS
614 std::vector<CVec3dArray*> aaUnstructuredPointClusters;
622 pUnstructuredPointClusters =
new CVec3dArray*[nMaxNumberOfUnstructuredClusters];
625 RemoveOutliers(m_vFeaturePoints3d, 2.0f);
628 ClusterXMeans(m_vFeaturePoints3d, nMaxNumberOfUnstructuredClusters, fBICFactorLeftoverPoints, aaUnstructuredPointClusters);
632 for (
int i = 0; i < (int)aaUnstructuredPointClusters.size(); i++)
634 RemoveOutliers(*aaUnstructuredPointClusters.at(i), 1.5f, NULL);
635 RemoveOutliers(*aaUnstructuredPointClusters.at(i), 2.0f, NULL);
639 if (aaUnstructuredPointClusters.at(i)->GetSize() / GetVariance(*aaUnstructuredPointClusters.at(i), vTemp) > 0.004f)
641 pUnstructuredPointClusters[nNumberOfUnstructuredClusters] = aaUnstructuredPointClusters.at(i);
644 for (
int j = 0; j < pUnstructuredPointClusters[nNumberOfUnstructuredClusters]->GetSize(); j++)
646 for (
int k = 0; k < m_vFeaturePoints3d.GetSize(); k++)
648 if (m_vFeaturePoints3d[k].x == (*pUnstructuredPointClusters[nNumberOfUnstructuredClusters])[j].x
649 && m_vFeaturePoints3d[k].y == (*pUnstructuredPointClusters[nNumberOfUnstructuredClusters])[j].y
650 && m_vFeaturePoints3d[k].z == (*pUnstructuredPointClusters[nNumberOfUnstructuredClusters])[j].z)
652 const int nEnd = m_vFeaturePoints3d.GetSize() - 1;
653 m_vFeaturePoints3d[k] = m_vFeaturePoints3d[nEnd];
654 m_vFeaturePoints3d.DeleteElement(nEnd);
660 nNumberOfUnstructuredClusters++;
665 aaUnstructuredPointClusters.clear();
690 for (
int i = 0; i < nNumberOfPlanesAfterClustering; i++)
693 aObjectHypotheses.AddElement(pHypothesis);
697 for (
int i = 0; i < nNumberOfCylindersAfterClustering; i++)
700 pCylinderCentersAfterClustering[i], pCylinderRadiusesAfterClustering[i], aAllMSERs, aMSERSigmaPoints, pImageLeftColor, pImageLeftGrey);
701 aObjectHypotheses.AddElement(pHypothesis);
706 for (
int i = 0; i < nNumberOfSpheres; i++)
709 aAllMSERs, aMSERSigmaPoints, pImageLeftColor, pImageLeftGrey);
710 aObjectHypotheses.AddElement(pHypothesis);
715 for (
int i = 0; i < nNumberOfUnstructuredClusters; i++)
719 aObjectHypotheses.AddElement(pHypothesis);
723 for (
int i = 0; i < nNumSingleColoredRegionHypotheses; i++)
727 aObjectHypotheses.AddElement(pHypothesis);
732 ARMARX_VERBOSE_S <<
"Adding " << nNumLCCPSegmentHypotheses <<
" hypotheses from LCCP";
734 for (
int i = 0; i < nNumLCCPSegmentHypotheses; i++)
740 aObjectHypotheses.AddElement(pHypothesis);
742 #ifdef OLP_MAKE_LCCP_SEG_IMAGES
747 fileName.append(
"lccp0000.bmp");
748 int fileNumber = m_nIterations * 1000 + counter;
751 ARMARX_VERBOSE_S <<
"Saving LCCP segmentation image for segment " << i <<
": " << fileName;
752 segmentationImage->SaveToFile(fileName.c_str());
753 delete segmentationImage;
765 #ifdef OLP_FIND_SALIENCY_HYPOTHESES
767 gettimeofday(&tStart, 0);
773 ImageProcessor::Zero(m_pHypothesesCoveringImage);
775 for (
int i = 0; i < aObjectHypotheses.GetSize(); i++)
778 ImageProcessor::Or(m_pHypothesesCoveringImage, m_pTempImageGray, m_pHypothesesCoveringImage);
781 ImageProcessor::Dilate(m_pHypothesesCoveringImage, m_pTempImageGray);
782 ImageProcessor::Dilate(m_pTempImageGray, m_pHypothesesCoveringImage);
783 ImageProcessor::Dilate(m_pHypothesesCoveringImage, m_pTempImageGray);
784 ImageProcessor::Dilate(m_pTempImageGray, m_pHypothesesCoveringImage);
785 ImageProcessor::Dilate(m_pHypothesesCoveringImage, m_pTempImageGray);
786 ImageProcessor::Erode(m_pTempImageGray, m_pHypothesesCoveringImage);
787 ImageProcessor::Erode(m_pHypothesesCoveringImage, m_pTempImageGray);
788 ImageProcessor::Erode(m_pTempImageGray, m_pHypothesesCoveringImage);
792 ImageProcessor::HistogramStretching(m_pSaliencyImage, m_pSaliencyHypothesisRegionsImage, 0.5f, 1.0f);
796 m_pSaliencyHypothesisRegionsImage->pixels[i] = (m_pHypothesesCoveringImage->pixels[i]) ? 0 : m_pSaliencyHypothesisRegionsImage->pixels[i];
802 std::vector<CHypothesisPoint*> aPointsInSalientRegions;
805 std::vector<std::vector<CHypothesisPoint*> > aSalientRegionsPointsClusters;
807 ARMARX_VERBOSE_S << aSalientRegionsPointsClusters.size() <<
" clusters in salient regions";
810 for (
size_t i = 0; i < aSalientRegionsPointsClusters.size(); i++)
812 CVec3dArray aTempArray;
814 for (
size_t j = 0; j < aSalientRegionsPointsClusters.at(i).size(); j++)
816 aTempArray.AddElement(aSalientRegionsPointsClusters.at(i).at(j)->vPosition);
819 RemoveOutliers(aTempArray, 1.5f, NULL);
825 aObjectHypotheses.AddElement(pHypothesis);
829 gettimeofday(&tEnd, 0);
830 tTimeDiff = (1000 * tEnd.tv_sec + tEnd.tv_usec / 1000) - (1000 * tStart.tv_sec + tStart.tv_usec / 1000);
842 for (
int i = 1; i < aObjectHypotheses.GetSize(); i++)
844 pHypothesis = aObjectHypotheses[i];
845 nSize = (int)aObjectHypotheses[i]->aNewPoints.size();
848 while ((j > 0) && ((int)aObjectHypotheses[j - 1]->aNewPoints.size() < nSize))
850 aObjectHypotheses[j] = aObjectHypotheses[j - 1];
854 aObjectHypotheses[j] = pHypothesis;
860 delete aObjectHypotheses[i];
861 aObjectHypotheses.DeleteElement(i);
865 for (
int i = 0; i < aObjectHypotheses.GetSize(); i++)
902 delete[] pPlaneNormals;
905 for (
int i = 0; i < nNumberOfPlanesAfterClustering; i++)
907 delete pPlanePointsAfterClustering[i];
910 delete[] pPlanePointsAfterClustering;
912 delete[] paCylinders;
913 delete[] pCylinderAxes;
914 delete[] pCylinderCenters;
915 delete[] pCylinderRadiuses;
917 for (
int i = 0; i < nNumberOfCylindersAfterClustering; i++)
919 delete pCylinderPointsAfterClustering[i];
922 delete[] pCylinderPointsAfterClustering;
923 delete[] pCylinderAxesAfterClustering;
924 delete[] pCylinderCentersAfterClustering;
925 delete[] pCylinderRadiusesAfterClustering;
928 delete[] pSphereCenters;
929 delete[] pSphereRadiuses;
931 delete[] pUnstructuredPointClusters;
936 gettimeofday(&tEndAll, 0);
937 tTimeDiff = (1000 * tEndAll.tv_sec + tEndAll.tv_usec / 1000) - (1000 * tStartAll.tv_sec + tStartAll.tv_usec / 1000);
938 ARMARX_VERBOSE_S <<
"Time for complete hypothesis generation: " << tTimeDiff <<
" ms";
948 float CHypothesisGeneration::GetVariance(
const CVec3dArray& avPoints,
Vec3d& vMean)
956 for (
int i = 0; i < avPoints.GetSize(); i++)
958 vMean.x += avPoints[i].x;
959 vMean.y += avPoints[i].y;
960 vMean.z += avPoints[i].z;
963 vMean.x /= (
float)avPoints.GetSize();
964 vMean.y /= (
float)avPoints.GetSize();
965 vMean.z /= (
float)avPoints.GetSize();
968 for (
int i = 0; i < avPoints.GetSize(); i++)
970 fVariance += (vMean.x - avPoints[i].x) * (vMean.x - avPoints[i].x)
971 + (vMean.y - avPoints[i].y) * (vMean.y - avPoints[i].y)
972 + (vMean.z - avPoints[i].z) * (vMean.z - avPoints[i].z);
975 return (fVariance / (
float)avPoints.GetSize());
983 void CHypothesisGeneration::RemoveOutliers(CVec3dArray& avPoints,
float fStdDevFactor, std::vector<int>* paIndices)
985 if (avPoints.GetSize() < 9)
991 const float fStandardDeviation = sqrtf(GetVariance(avPoints, vMean));
992 const float fThreshold2 = fStdDevFactor * fStdDevFactor * fStandardDeviation * fStandardDeviation;
997 if (paIndices != NULL)
999 for (
int i = 0; i < avPoints.GetSize(); i++)
1001 fDist2 = (vMean.x - avPoints[i].x) * (vMean.x - avPoints[i].x)
1002 + (vMean.y - avPoints[i].y) * (vMean.y - avPoints[i].y)
1003 + (vMean.z - avPoints[i].z) * (vMean.z - avPoints[i].z);
1005 if (fDist2 > fThreshold2)
1007 avPoints[i] = avPoints[avPoints.GetSize() - 1];
1008 paIndices->at(i) = paIndices->at(avPoints.GetSize() - 1);
1009 avPoints.DeleteElement(avPoints.GetSize() - 1);
1010 paIndices->pop_back();
1017 for (
int i = 0; i < avPoints.GetSize(); i++)
1019 fDist2 = (vMean.x - avPoints[i].x) * (vMean.x - avPoints[i].x)
1020 + (vMean.y - avPoints[i].y) * (vMean.y - avPoints[i].y)
1021 + (vMean.z - avPoints[i].z) * (vMean.z - avPoints[i].z);
1023 if (fDist2 > fThreshold2)
1025 avPoints[i] = avPoints[avPoints.GetSize() - 1];
1026 avPoints.DeleteElement(avPoints.GetSize() - 1);
1038 bool CHypothesisGeneration::FindCylinder(
const CVec3dArray& avSamplePoints,
const CVec3dArray& avAllPoints,
const float fToleranceThreshold,
const float fMaxRadius,
1039 CVec3dArray& avResultPoints,
Vec3d& vCylinderAxis,
Vec3d& vCylinderCenter,
float& fCylinderRadius)
1041 avResultPoints.Clear();
1043 const int nNumberOfSamples = avSamplePoints.GetSize();
1045 if (nNumberOfSamples < 5)
1050 const int nNumberOfAllPoints = avAllPoints.GetSize();
1052 const Vec3d vZAxis = {0.0f, 0.0f, 1.0f};
1054 Vec3d vBestCylinderCenter, vBestCylinderAxis;
1055 float fBestCylinderRadius = 0;
1056 int nMaxNumberOfPointsOnCylinder = 0;
1058 Vec3d vAvgPoint = {0.0f, 0.0f, 0.0f};
1060 for (
int i = 0; i < nNumberOfSamples; i++)
1062 vAvgPoint.x += avSamplePoints[i].x;
1063 vAvgPoint.y += avSamplePoints[i].y;
1064 vAvgPoint.z += avSamplePoints[i].z;
1067 vAvgPoint.x /= (
float)nNumberOfSamples;
1068 vAvgPoint.y /= (
float)nNumberOfSamples;
1069 vAvgPoint.z /= (
float)nNumberOfSamples;
1071 CFloatMatrix mSamplePoints(3, nNumberOfSamples);
1073 for (
int i = 0; i < nNumberOfSamples; i++)
1075 mSamplePoints(0, i) = avSamplePoints[i].x - vAvgPoint.x;
1076 mSamplePoints(1, i) = avSamplePoints[i].y - vAvgPoint.y;
1077 mSamplePoints(2, i) = avSamplePoints[i].z - vAvgPoint.z;
1080 CFloatMatrix mEigenVectors(3, 3);
1081 CFloatMatrix mEigenValues(1, 3);
1082 CFloatMatrix mProjection(2, 3);
1083 Mat3d mTransformation;
1085 LinearAlgebra::PCA(&mSamplePoints, &mEigenVectors, &mEigenValues);
1093 Vec3d vTemp1, vTemp2;
1095 for (
int n = 0; n < 3; n++)
1101 vCylinderAxis.x = mEigenVectors(0, 0);
1102 vCylinderAxis.y = mEigenVectors(0, 1);
1103 vCylinderAxis.z = mEigenVectors(0, 2);
1104 Math3d::NormalizeVec(vCylinderAxis);
1108 mProjection(0, 0) = mEigenVectors(1, 0);
1109 mProjection(0, 1) = mEigenVectors(1, 1);
1110 mProjection(0, 2) = mEigenVectors(1, 2);
1111 mProjection(1, 0) = mEigenVectors(2, 0);
1112 mProjection(1, 1) = mEigenVectors(2, 1);
1113 mProjection(1, 2) = mEigenVectors(2, 2);
1117 mTransformation.r1 = mEigenVectors(0, 0);
1118 mTransformation.r2 = mEigenVectors(1, 0);
1119 mTransformation.r3 = mEigenVectors(2, 0);
1120 mTransformation.r4 = mEigenVectors(0, 1);
1121 mTransformation.r5 = mEigenVectors(1, 1);
1122 mTransformation.r6 = mEigenVectors(2, 1);
1123 mTransformation.r7 = mEigenVectors(0, 2);
1124 mTransformation.r8 = mEigenVectors(1, 2);
1125 mTransformation.r9 = mEigenVectors(2, 2);
1131 vCylinderAxis.x = mEigenVectors(1, 0);
1132 vCylinderAxis.y = mEigenVectors(1, 1);
1133 vCylinderAxis.z = mEigenVectors(1, 2);
1134 Math3d::NormalizeVec(vCylinderAxis);
1138 mProjection(0, 0) = mEigenVectors(0, 0);
1139 mProjection(0, 1) = mEigenVectors(0, 1);
1140 mProjection(0, 2) = mEigenVectors(0, 2);
1141 mProjection(1, 0) = mEigenVectors(2, 0);
1142 mProjection(1, 1) = mEigenVectors(2, 1);
1143 mProjection(1, 2) = mEigenVectors(2, 2);
1147 mTransformation.r1 = mEigenVectors(1, 0);
1148 mTransformation.r2 = mEigenVectors(0, 0);
1149 mTransformation.r3 = mEigenVectors(2, 0);
1150 mTransformation.r4 = mEigenVectors(1, 1);
1151 mTransformation.r5 = mEigenVectors(0, 1);
1152 mTransformation.r6 = mEigenVectors(2, 1);
1153 mTransformation.r7 = mEigenVectors(1, 2);
1154 mTransformation.r8 = mEigenVectors(0, 2);
1155 mTransformation.r9 = mEigenVectors(2, 2);
1162 if (fabs(mEigenVectors(0, 1)) > fabs(mEigenVectors(1, 1)))
1164 if (fabs(mEigenVectors(0, 1)) > fabs(mEigenVectors(2, 1)))
1166 vCylinderAxis.x = mEigenVectors(0, 0);
1167 vCylinderAxis.y = 2.0f * mEigenVectors(0, 1);
1168 vCylinderAxis.z = mEigenVectors(0, 2);
1172 vCylinderAxis.x = mEigenVectors(2, 0);
1173 vCylinderAxis.y = 2.0f * mEigenVectors(2, 1);
1174 vCylinderAxis.z = mEigenVectors(2, 2);
1179 if (fabs(mEigenVectors(1, 1)) > fabs(mEigenVectors(2, 1)))
1181 vCylinderAxis.x = mEigenVectors(1, 0);
1182 vCylinderAxis.y = 2.0f * mEigenVectors(1, 1);
1183 vCylinderAxis.z = mEigenVectors(1, 2);
1184 Math3d::NormalizeVec(vCylinderAxis);
1188 vCylinderAxis.x = mEigenVectors(2, 0);
1189 vCylinderAxis.y = 2.0f * mEigenVectors(2, 1);
1190 vCylinderAxis.z = mEigenVectors(2, 2);
1194 Math3d::NormalizeVec(vCylinderAxis);
1197 Math3d::CrossProduct(vCylinderAxis, vZAxis, vTemp1);
1198 Math3d::NormalizeVec(vTemp1);
1199 Math3d::CrossProduct(vCylinderAxis, vTemp1, vTemp2);
1202 mProjection(0, 0) = vTemp1.x;
1203 mProjection(0, 1) = vTemp1.y;
1204 mProjection(0, 2) = vTemp1.z;
1205 mProjection(1, 0) = vTemp2.x;
1206 mProjection(1, 1) = vTemp2.y;
1207 mProjection(1, 2) = vTemp2.z;
1211 mTransformation.r1 = vCylinderAxis.x;
1212 mTransformation.r2 = vTemp1.x;
1213 mTransformation.r3 = vTemp2.x;
1214 mTransformation.r4 = vCylinderAxis.y;
1215 mTransformation.r5 = vTemp1.y;
1216 mTransformation.r6 = vTemp2.y;
1217 mTransformation.r7 = vCylinderAxis.z;
1218 mTransformation.r8 = vTemp1.z;
1219 mTransformation.r9 = vTemp2.z;
1225 vCylinderAxis.x = 0.0f;
1226 vCylinderAxis.y = 1.0f;
1227 vCylinderAxis.z = 0.0f;
1231 mProjection(0, 0) = 1.0f;
1232 mProjection(0, 1) = 0.0f;
1233 mProjection(0, 2) = 0.0f;
1234 mProjection(1, 0) = 0.0f;
1235 mProjection(1, 1) = 0.0f;
1236 mProjection(1, 2) = 1.0f;
1240 mTransformation.r1 = 0.0f;
1241 mTransformation.r2 = 1.0f;
1242 mTransformation.r3 = 0.0f;
1243 mTransformation.r4 = 1.0f;
1244 mTransformation.r5 = 0.0f;
1245 mTransformation.r6 = 0.0f;
1246 mTransformation.r7 = 0.0f;
1247 mTransformation.r8 = 0.0f;
1248 mTransformation.r9 = 1.0f;
1254 CFloatMatrix mProjectedPoints(2, nNumberOfSamples);
1255 LinearAlgebra::MulMatMat(&mSamplePoints, &mProjection, &mProjectedPoints);
1265 QuickSort2DPointsX(mProjectedPoints, 0, nNumberOfSamples - 1);
1273 float fCenterX = 0, fCenterY = 0;
1277 float xi = 0, yi = 0, xj = 0, yj = 0, xk = 0, yk = 0;
1279 int nTwentyPercent = nNumberOfSamples / 5;
1295 for (
int i = 0; i < nTwentyPercent; i++)
1297 xi += mProjectedPoints(0, i);
1298 yi += mProjectedPoints(1, i);
1301 for (
int i = 2 * nTwentyPercent; i < 3 * nTwentyPercent; i++)
1303 xj += mProjectedPoints(0, i);
1304 yj += mProjectedPoints(1, i);
1307 for (
int i = 4 * nTwentyPercent; i < nNumberOfSamples; i++)
1309 xk += mProjectedPoints(0, i);
1310 yk += mProjectedPoints(1, i);
1313 const float fOneByNumUsedSamples = 1.0f / (
float)nNumberOfSamples;
1314 xi *= fOneByNumUsedSamples;
1315 yi *= fOneByNumUsedSamples;
1316 xj *= fOneByNumUsedSamples;
1317 yj *= fOneByNumUsedSamples;
1318 xk *= fOneByNumUsedSamples;
1319 yk *= fOneByNumUsedSamples;
1322 const float fDelta1 = (xi * (yk - yj) + xj * (yi - yk) + xk * (yj - yi));
1328 if (fabs(fDelta1) > 0.001f)
1330 fCenterX = 0.5f / fDelta1 * ((yk - yj) * (xi * xi + yi * yi) + (yi - yk) * (xj * xj + yj * yj) + (yj - yi) * (xk * xk + yk * yk));
1331 fCenterY = - 0.5f / fDelta1 * ((xk - xj) * (xi * xi + yi * yi) + (xi - xk) * (xj * xj + yj * yj) + (xj - xi) * (xk * xk + yk * yk));
1417 Vec3d vCenter2D = {0.0f, fCenterX, fCenterY};
1420 Mat3d mInverseTransformation;
1421 Math3d::Invert(mTransformation, mInverseTransformation);
1422 Math3d::MulMatVec(mInverseTransformation, vCenter2D, vCylinderCenter);
1424 vCylinderCenter.x += vAvgPoint.x;
1425 vCylinderCenter.y += vAvgPoint.y;
1426 vCylinderCenter.z += vAvgPoint.z;
1430 fCylinderRadius = 0;
1432 for (
int i = 0; i < nNumberOfSamples; i++)
1434 Math3d::SubtractVecVec(avSamplePoints[i], vCylinderCenter, vTemp1);
1435 Math3d::CrossProduct(vCylinderAxis, vTemp1, vTemp2);
1436 fCylinderRadius += Math3d::Length(vTemp2);
1439 fCylinderRadius /= (
float)nNumberOfSamples;
1449 if (fCylinderRadius < fMaxRadius)
1455 Math3d::CrossProduct(vCylinderAxis, vZAxis, vTemp1);
1456 Math3d::CrossProduct(vCylinderAxis, vTemp1, vPlaneNormal);
1457 const float fD = - Math3d::ScalarProduct(vPlaneNormal, vCylinderCenter);
1462 int nNumberOfPointsOnCylinder = 0;
1464 for (
int i = 0; i < nNumberOfAllPoints; i++)
1469 fTemp = Math3d::ScalarProduct(vPlaneNormal, avAllPoints[i]) + fD;
1474 Math3d::SubtractVecVec(avAllPoints[i], vCylinderCenter, vTemp1);
1475 Math3d::CrossProduct(vCylinderAxis, vTemp1, vTemp2);
1476 fDist = Math3d::Length(vTemp2);
1479 if (fabsf(fDist - fCylinderRadius) <= fToleranceThreshold)
1481 nNumberOfPointsOnCylinder++;
1486 if (nNumberOfPointsOnCylinder > nMaxNumberOfPointsOnCylinder)
1488 nMaxNumberOfPointsOnCylinder = nNumberOfPointsOnCylinder;
1490 Math3d::SetVec(vBestCylinderCenter, vCylinderCenter);
1491 Math3d::SetVec(vBestCylinderAxis, vCylinderAxis);
1492 fBestCylinderRadius = fCylinderRadius;
1500 if (nMaxNumberOfPointsOnCylinder == 0)
1506 Math3d::SetVec(vCylinderCenter, vBestCylinderCenter);
1507 Math3d::SetVec(vCylinderAxis, vBestCylinderAxis);
1508 fCylinderRadius = fBestCylinderRadius;
1513 for (
int i = 0; i < nNumberOfAllPoints; i++)
1515 Math3d::SubtractVecVec(avAllPoints[i], vBestCylinderCenter, vTemp1);
1516 Math3d::CrossProduct(vBestCylinderAxis, vTemp1, vTemp2);
1517 fDist = Math3d::Length(vTemp2);
1521 if (fabsf(fDist - fBestCylinderRadius) <= fToleranceThreshold)
1523 avResultPoints.AddElement(avAllPoints[i]);
1534 void CHypothesisGeneration::QuickSort2DPointsX(CFloatMatrix& mPoints,
int nLeft,
int nRight)
1536 int nPivotPos, i, j;
1537 float fPivotElemX, fTempElemX, fTempElemY;
1539 while (nRight - nLeft >= 16)
1543 nPivotPos = nLeft + rand() % (nRight - nLeft);
1546 fTempElemX = mPoints(0, nLeft);
1547 fTempElemY = mPoints(1, nLeft);
1548 mPoints(0, nLeft) = mPoints(0, nPivotPos);
1549 mPoints(1, nLeft) = mPoints(1, nPivotPos);
1550 mPoints(0, nPivotPos) = fTempElemX;
1551 mPoints(1, nPivotPos) = fTempElemY;
1556 fPivotElemX = mPoints(0, nLeft);
1562 while (mPoints(0, i) < fPivotElemX)
1567 while (mPoints(0, j) > fPivotElemX)
1575 fTempElemX = mPoints(0, i);
1576 fTempElemY = mPoints(1, i);
1577 mPoints(0, i) = mPoints(0, j);
1578 mPoints(1, i) = mPoints(1, j);
1579 mPoints(0, j) = fTempElemX;
1580 mPoints(1, j) = fTempElemY;
1588 if (i < (nLeft + nRight) / 2)
1590 QuickSort2DPointsX(mPoints, nLeft, j);
1595 QuickSort2DPointsX(mPoints, i, nRight);
1603 for (i = nLeft + 1; i <= nRight; i++)
1605 fTempElemX = mPoints(0, i);
1606 fTempElemY = mPoints(1, i);
1609 while ((j > nLeft) && (mPoints(0, j - 1) > fTempElemX))
1611 mPoints(0, j) = mPoints(0, j - 1);
1612 mPoints(1, j) = mPoints(1, j - 1);
1616 mPoints(0, j) = fTempElemX;
1617 mPoints(1, j) = fTempElemY;
1626 void CHypothesisGeneration::ClusterPointsRegularGrid2D(
const CVec3dArray& avPoints,
const CCalibration* calibration,
1627 const int nNumSectionsX,
const int nNumSectionsY, CVec3dArray*& pClusters,
1630 nNumClusters = nNumSectionsX * nNumSectionsY + (nNumSectionsX + 1) * (nNumSectionsY + 1);
1631 int nShiftOffset = nNumSectionsX * nNumSectionsY;
1632 pClusters =
new CVec3dArray[nNumClusters];
1635 const int nNumPoints = avPoints.GetSize();
1637 int nIndex, nIndexShifted;
1643 for (
int i = 0; i < nNumPoints; i++)
1645 calibration->CameraToImageCoordinates(avPoints[i], vPoint2D,
false);
1647 nIndex = nNumSectionsX * ((int)vPoint2D.y / nIntervalY) + (int)vPoint2D.x / nIntervalX;
1649 nIndexShifted = (nNumSectionsX + 1) * (((int)vPoint2D.y + nIntervalY2) / nIntervalY) + ((
int)vPoint2D.x + nIntervalX2) / nIntervalX;
1655 if (nIndex + nIndex < nNumClusters)
1657 pClusters[nIndex].AddElement(avPoints[i]);
1660 if (nShiftOffset + nIndexShifted < nNumClusters)
1662 pClusters[nShiftOffset + nIndexShifted].AddElement(avPoints[i]);
1847 bool CHypothesisGeneration::RANSACCylinders2(
const CVec3dArray& avPoints,
const CCalibration* calibration,
1848 const float fToleranceThreshold,
const float fMaxRadius, CVec3dArray& avCylinder,
1849 Vec3d& vCylinderAxis,
Vec3d& vCylinderCenter,
float& fCylinderRadius)
1853 CVec3dArray avAxisBlacklist(nMaxAxisIterations);
1854 bool bBreakIfNextAxisIsBad =
false;
1855 Vec3d vBestCylinderAxis, vBestCylinderCenter;
1856 float fBestRadius = 0;
1867 int nNumGridClusters;
1870 nNumGridClusters = 1;
1871 const CVec3dArray* pRegularGridClusters = &avPoints;
1875 const int nOverallNumberOfPoints = avPoints.GetSize();
1876 CVec3dArray avGaussMap(nOverallNumberOfPoints);
1877 CVec3dArray avCorrespondingPoints(nOverallNumberOfPoints);
1878 int nMaxSupport = 0;
1881 for (
int i = 0; i < nNumGridClusters; i++)
1883 const int nClusterSize = pRegularGridClusters[i].GetSize();
1885 if (nClusterSize >= 5)
1887 #pragma omp parallel
1889 CFloatMatrix mSampleMatrix(3, 5);
1890 CFloatMatrix mU(5, 5);
1891 CFloatMatrix mSigma(3, 5);
1892 CFloatMatrix mV(3, 3);
1893 Vec3d vPoint, vNeighbour1, vNeighbour2, vNeighbour3, vNeighbour4, vNormal, vMean, vTemp1, vTemp2;
1894 float fMinDist1, fMinDist2, fMinDist3, fMinDist4, fDist;
1896 #pragma omp for schedule(static, 10)
1897 for (
int j = 0; j < nClusterSize; j++)
1900 Math3d::SetVec(vPoint, pRegularGridClusters[i][j]);
1901 fMinDist1 = 1000000;
1902 fMinDist2 = 1000000;
1903 fMinDist3 = 1000000;
1904 fMinDist4 = 1000000;
1906 for (
int k = 0; k < nClusterSize; k++)
1910 fDist = Math3d::Distance(vPoint, pRegularGridClusters[i][k]);
1912 if (fDist < fMinDist1)
1914 fMinDist4 = fMinDist3;
1915 Math3d::SetVec(vNeighbour4, vNeighbour3);
1916 fMinDist3 = fMinDist2;
1917 Math3d::SetVec(vNeighbour3, vNeighbour2);
1918 fMinDist2 = fMinDist1;
1919 Math3d::SetVec(vNeighbour2, vNeighbour1);
1921 Math3d::SetVec(vNeighbour1, pRegularGridClusters[i][k]);
1923 else if (fDist < fMinDist2)
1925 fMinDist4 = fMinDist3;
1926 Math3d::SetVec(vNeighbour4, vNeighbour3);
1927 fMinDist3 = fMinDist2;
1928 Math3d::SetVec(vNeighbour3, vNeighbour2);
1930 Math3d::SetVec(vNeighbour2, pRegularGridClusters[i][k]);
1932 else if (fDist < fMinDist3)
1934 fMinDist4 = fMinDist3;
1935 Math3d::SetVec(vNeighbour4, vNeighbour3);
1937 Math3d::SetVec(vNeighbour3, pRegularGridClusters[i][k]);
1939 else if (fDist < fMinDist4)
1942 Math3d::SetVec(vNeighbour4, pRegularGridClusters[i][k]);
1954 if (fMinDist2 < 25.0f)
1957 Math3d::SubtractVecVec(vNeighbour1, vPoint, vTemp1);
1958 Math3d::SubtractVecVec(vNeighbour2, vPoint, vTemp2);
1959 Math3d::CrossProduct(vTemp1, vTemp2, vNormal);
1960 Math3d::NormalizeVec(vNormal);
1962 if (Math3d::Length(vNormal) > 0.9f)
1964 #pragma omp critical
1966 avGaussMap.AddElement(vNormal);
1967 avCorrespondingPoints.AddElement(vPoint);
1972 if (fMinDist4 < 50.0f)
1974 vMean.x = 0.2f * (vPoint.x + vNeighbour1.x + vNeighbour2.x + vNeighbour3.x + vNeighbour4.x);
1975 vMean.y = 0.2f * (vPoint.y + vNeighbour1.y + vNeighbour2.y + vNeighbour3.y + vNeighbour4.y);
1976 vMean.z = 0.2f * (vPoint.z + vNeighbour1.z + vNeighbour2.z + vNeighbour3.z + vNeighbour4.z);
1978 mSampleMatrix(0, 0) = vPoint.x - vMean.x;
1979 mSampleMatrix(1, 0) = vPoint.y - vMean.y;
1980 mSampleMatrix(2, 0) = vPoint.z - vMean.z;
1981 mSampleMatrix(0, 1) = vNeighbour1.x - vMean.x;
1982 mSampleMatrix(1, 1) = vNeighbour1.y - vMean.y;
1983 mSampleMatrix(2, 1) = vNeighbour1.z - vMean.z;
1984 mSampleMatrix(0, 2) = vNeighbour2.x - vMean.x;
1985 mSampleMatrix(1, 2) = vNeighbour2.y - vMean.y;
1986 mSampleMatrix(2, 2) = vNeighbour2.z - vMean.z;
1987 mSampleMatrix(0, 3) = vNeighbour3.x - vMean.x;
1988 mSampleMatrix(1, 3) = vNeighbour3.y - vMean.y;
1989 mSampleMatrix(2, 3) = vNeighbour3.z - vMean.z;
1990 mSampleMatrix(0, 4) = vNeighbour4.x - vMean.x;
1991 mSampleMatrix(1, 4) = vNeighbour4.y - vMean.y;
1992 mSampleMatrix(2, 4) = vNeighbour4.z - vMean.z;
1994 LinearAlgebra::SVD(&mSampleMatrix, &mSigma, &mU, &mV);
1996 vNormal.x = mV(2, 0);
1997 vNormal.y = mV(2, 1);
1998 vNormal.z = mV(2, 2);
1999 Math3d::NormalizeVec(vNormal);
2001 if (Math3d::Length(vNormal) < 0.9f)
2009 #pragma omp critical
2011 avGaussMap.AddElement(vNormal);
2012 avCorrespondingPoints.AddElement(vPoint);
2167 for (
int n = 0; n < nMaxAxisIterations; n++)
2178 const int nNumberOfPointsInGaussMap = avGaussMap.GetSize();
2179 const float fGaussMapThreshold = 0.15f;
2180 const float fBadAxisFactor = 0.1f;
2181 int nMaxAxisSupport = 0;
2184 #pragma omp parallel
2186 int nFirstIndex, nSecondIndex, nSupport;
2187 Vec3d vPoint1, vPoint2, vNormal;
2188 bool bCloseToBadAxis;
2190 #pragma omp for schedule(static, 16)
2191 for (
int i = 0; i < nGaussCircleIterations; i++)
2194 srand((rand() % 17)*i + i);
2195 nFirstIndex = rand() % nNumberOfPointsInGaussMap;
2199 nSecondIndex = rand() % nNumberOfPointsInGaussMap;
2201 while (nSecondIndex == nFirstIndex);
2203 vPoint1 = avGaussMap[nFirstIndex];
2204 vPoint2 = avGaussMap[nSecondIndex];
2208 Math3d::CrossProduct(vPoint1, vPoint2, vNormal);
2209 Math3d::NormalizeVec(vNormal);
2212 if (Math3d::ScalarProduct(vNormal, vNormal) > 0.9f)
2215 bCloseToBadAxis =
false;
2217 for (
int j = 0; j < avAxisBlacklist.GetSize(); j++)
2219 bCloseToBadAxis |= (fabsf(Math3d::ScalarProduct(vNormal, avAxisBlacklist[j])) > 1.0f - fBadAxisFactor * fGaussMapThreshold);
2222 if (!bCloseToBadAxis)
2227 for (
int j = 0; j < nNumberOfPointsInGaussMap; j++)
2229 if (fabsf(Math3d::ScalarProduct(vNormal, avGaussMap[j])) < fGaussMapThreshold)
2236 if (nSupport > nMaxAxisSupport)
2238 #pragma omp critical
2239 if (nSupport > nMaxAxisSupport)
2241 nMaxAxisSupport = nSupport;
2242 Math3d::SetVec(vBestNormal, vNormal);
2258 if (bBreakIfNextAxisIsBad)
2264 else if (2 * n > nMaxAxisIterations)
2266 bBreakIfNextAxisIsBad =
true;
2268 avAxisBlacklist.AddElement(vBestNormal);
2274 avAxisBlacklist.AddElement(vBestNormal);
2288 CVec3dArray avCylinderCandidates;
2290 for (
int j = 0; j < nNumberOfPointsInGaussMap; j++)
2292 if (fabsf(Math3d::ScalarProduct(vBestNormal, avGaussMap[j])) <= 1.0f * fGaussMapThreshold)
2295 bool bDouble =
false;
2297 for (
int i = 0; i < avCylinderCandidates.GetSize(); i++)
2299 if (avCorrespondingPoints[j].x == avCylinderCandidates[i].x)
2301 if ((avCorrespondingPoints[j].y == avCylinderCandidates[i].y) && (avCorrespondingPoints[j].z == avCylinderCandidates[i].z))
2311 avCylinderCandidates.AddElement(avCorrespondingPoints[j]);
2320 const Vec3d vCylinderAxis = {vBestNormal.x, vBestNormal.y, vBestNormal.z};
2321 const Vec3d vZAxis = {0, 0, 1};
2322 Vec3d vTemp1, vTemp2;
2323 Math3d::CrossProduct(vCylinderAxis, vZAxis, vTemp1);
2324 Math3d::CrossProduct(vCylinderAxis, vTemp1, vTemp2);
2325 const Mat3d mTransform = {vCylinderAxis.x, vTemp1.x, vTemp2.x,
2326 vCylinderAxis.y, vTemp1.y, vTemp2.y,
2327 vCylinderAxis.z, vTemp1.z, vTemp2.z
2329 Mat3d mTransformInv;
2330 Math3d::Invert(mTransform, mTransformInv);
2331 const int nNumCylinderCandidates = avCylinderCandidates.GetSize();
2332 CVec3dArray avCylinderCandidatesTransformed(nNumCylinderCandidates);
2334 for (
int i = 0; i < nNumCylinderCandidates; i++)
2336 Math3d::MulMatVec(mTransform, avCylinderCandidates[i], vTemp1);
2337 avCylinderCandidatesTransformed.AddElement(vTemp1);
2353 const float fMaxRadius2 = fMaxRadius * fMaxRadius;
2354 const float fToleranceThreshold2 = fToleranceThreshold * fToleranceThreshold;
2356 const int nCircleIterationsPrep = (int)(
OLP_EFFORT_MODIFICATOR * (
float)nNumCylinderCandidates * 4.0f * sqrtf((
float)nNumCylinderCandidates));
2357 const int nCircleIterations = (nCircleIterationsPrep < nMaxCircleIterations) ? nCircleIterationsPrep : nMaxCircleIterations;
2369 #pragma omp parallel
2371 int nFirstIndex, nSecondIndex, nThirdIndex, nSupport;
2372 float xi, yi, xj, yj, xk, yk, fCenterX, fCenterY, fRadius2, fDist2;
2373 Vec3d vCylinderCenter, vTemp1, vTemp2;
2375 Vec3d vBestCylinderCenterLocal;
2376 float fBestRadiusLocal = 0;
2378 #pragma omp for schedule(static, 32)
2379 for (
int i = 0; i < nCircleIterations; i++)
2384 srand((rand() % 17)*i + i);
2385 nFirstIndex = rand() % nNumCylinderCandidates;
2389 nSecondIndex = rand() % nNumCylinderCandidates;
2391 while (nSecondIndex == nFirstIndex);
2395 nThirdIndex = rand() % nNumCylinderCandidates;
2397 while (nThirdIndex == nFirstIndex || nThirdIndex == nSecondIndex);
2399 xi = avCylinderCandidatesTransformed[nFirstIndex].y;
2400 yi = avCylinderCandidatesTransformed[nFirstIndex].z;
2401 xj = avCylinderCandidatesTransformed[nSecondIndex].y;
2402 yj = avCylinderCandidatesTransformed[nSecondIndex].z;
2403 xk = avCylinderCandidatesTransformed[nThirdIndex].y;
2404 yk = avCylinderCandidatesTransformed[nThirdIndex].z;
2407 const float fDelta = (xi * (yk - yj) + xj * (yi - yk) + xk * (yj - yi));
2410 if (fabs(fDelta) > 0.001f)
2412 fCenterX = 0.5f / fDelta * ((yk - yj) * (xi * xi + yi * yi) + (yi - yk) * (xj * xj + yj * yj) + (yj - yi) * (xk * xk + yk * yk));
2413 fCenterY = - 0.5f / fDelta * ((xk - xj) * (xi * xi + yi * yi) + (xi - xk) * (xj * xj + yj * yj) + (xj - xi) * (xk * xk + yk * yk));
2414 fRadius2 = (fCenterX - xi) * (fCenterX - xi) + (fCenterY - yi) * (fCenterY - yi);
2423 if (fRadius2 < fMaxRadius2)
2429 Math3d::SetVec(vTemp1, 0, fCenterX, fCenterY);
2430 Math3d::MulMatVec(mTransformInv, vTemp1, vCylinderCenter);
2435 Math3d::CrossProduct(vCylinderAxis, vZAxis, vTemp1);
2436 Math3d::CrossProduct(vCylinderAxis, vTemp1, vPlaneNormal);
2437 const float fD = - Math3d::ScalarProduct(vPlaneNormal, vCylinderCenter);
2478 for (
int j = 0; j < nNumCylinderCandidates; j++)
2483 fTemp = Math3d::ScalarProduct(vPlaneNormal, avCylinderCandidates[j]) + fD;
2487 Math3d::SubtractVecVec(avCylinderCandidates[j], vCylinderCenter, vTemp1);
2488 Math3d::CrossProduct(vCylinderAxis, vTemp1, vTemp2);
2489 fTemp = Math3d::ScalarProduct(vTemp2, vTemp2);
2492 fDist2 = fTemp - 2.0f * sqrtf(fTemp * fRadius2) + fRadius2;
2494 if (fDist2 < fToleranceThreshold2)
2501 if (nSupport > nMaxSupportLocal)
2503 nMaxSupportLocal = nSupport;
2504 Math3d::SetVec(vBestCylinderCenterLocal, vCylinderCenter);
2505 fBestRadiusLocal = sqrtf(fRadius2);
2513 #pragma omp critical
2514 if (nMaxSupportLocal > nMaxSupportForThisAxis)
2516 nMaxSupportForThisAxis = nMaxSupportLocal;
2518 if (nMaxSupportLocal > nMaxSupport)
2520 nMaxSupport = nMaxSupportLocal;
2521 Math3d::SetVec(vBestCylinderCenter, vBestCylinderCenterLocal);
2522 Math3d::SetVec(vBestCylinderAxis, vCylinderAxis);
2523 fBestRadius = fBestRadiusLocal;
2534 avAxisBlacklist.AddElement(vCylinderAxis);
2547 Vec3d vTemp1, vTemp2;
2549 for (
int j = 0; j < nOverallNumberOfPoints; j++)
2551 Math3d::SubtractVecVec(avPoints[j], vBestCylinderCenter, vTemp1);
2552 Math3d::CrossProduct(vBestCylinderAxis, vTemp1, vTemp2);
2553 fDist = Math3d::Length(vTemp2);
2555 if (fabsf(fDist - fBestRadius) <= fToleranceThreshold)
2557 avCylinder.AddElement(avPoints[j]);
2563 Math3d::SetVec(vCylinderAxis, vBestCylinderAxis);
2564 Math3d::SetVec(vCylinderCenter, vBestCylinderCenter);
2565 fCylinderRadius = fBestRadius;
2582 std::vector<Vec3d>& aSigmaPoints,
const CByteImage* pLeftColorImage,
const CByteImage* pLeftGreyImage)
2588 const int nNum3dPoints = avPlanePoints.GetSize();
2595 for (
int i = 0; i < nNum3dPoints; i++)
2599 if (CreateFeatureDescriptorForPoint(pPoint, avPlanePoints[i], aMSERs, aSigmaPoints, pLeftColorImage, pLeftGreyImage))
2612 Math3d::SetVec(hResult->
vCenter, 0, 0, 0);
2614 for (
int i = 0; i < nNum3dPoints; i++)
2616 hResult->
vCenter.x += avPlanePoints[i].x;
2617 hResult->
vCenter.y += avPlanePoints[i].y;
2618 hResult->
vCenter.z += avPlanePoints[i].z;
2627 CFloatMatrix mPoints(3, nNum3dPoints);
2628 CFloatMatrix mEigenVectors(3, 3);
2629 CFloatMatrix mEigenValues(1, 3);
2631 for (
int i = 0; i < nNum3dPoints; i++)
2633 mPoints(0, i) = avPlanePoints[i].x - hResult->
vCenter.x;
2634 mPoints(1, i) = avPlanePoints[i].y - hResult->
vCenter.y;
2635 mPoints(2, i) = avPlanePoints[i].z - hResult->
vCenter.z;
2638 LinearAlgebra::PCA(&mPoints, &mEigenVectors, &mEigenValues);
2641 if (mEigenVectors(2, 2) < 0)
2643 hResult->
vNormal.x = mEigenVectors(2, 0);
2644 hResult->
vNormal.y = mEigenVectors(2, 1);
2645 hResult->
vNormal.z = mEigenVectors(2, 2);
2653 hResult->
vNormal.x = - mEigenVectors(2, 0);
2654 hResult->
vNormal.y = - mEigenVectors(2, 1);
2655 hResult->
vNormal.z = - mEigenVectors(2, 2);
2667 Math3d::NormalizeVec(hResult->
vNormal);
2671 hResult->
fStdDev1 = mEigenValues(0, 0);
2672 hResult->
fStdDev2 = mEigenValues(0, 1);
2677 for (
int i = 0; i < nNum3dPoints; i++)
2679 fDist = Math3d::Distance(hResult->
vCenter, avPlanePoints[i]);
2697 const float fCylinderRadius, std::vector<CMSERDescriptor3D*>& aMSERs,
2698 std::vector<Vec3d>& aSigmaPoints,
const CByteImage* pLeftColorImage,
const CByteImage* pLeftGreyImage)
2704 const int nNum3dPoints = avCylinderPoints.GetSize();
2706 #pragma omp parallel
2710 #pragma omp for schedule(static, 5)
2711 for (
int i = 0; i < nNum3dPoints; i++)
2715 if (CreateFeatureDescriptorForPoint(pPoint, avCylinderPoints[i], aMSERs, aSigmaPoints, pLeftColorImage, pLeftGreyImage))
2717 #pragma omp critical
2729 hResult->
fRadius = fCylinderRadius;
2733 const float fVariance = GetVariance(avCylinderPoints, vMean);
2738 Vec3d vCenterOnAxis = vCylinderCenter;
2739 Vec3d vTemp1, vTemp2;
2740 Math3d::SubtractVecVec(vMean, vCylinderCenter, vTemp1);
2741 Math3d::MulVecScalar(vCylinderAxis, Math3d::ScalarProduct(vCylinderAxis, vTemp1), vTemp2);
2742 Math3d::AddToVec(vCenterOnAxis, vTemp2);
2743 Math3d::SetVec(hResult->
vCenter, vCenterOnAxis);
2746 Math3d::SubtractVecVec(vMean, vCenterOnAxis, hResult->
vNormal);
2747 Math3d::NormalizeVec(hResult->
vNormal);
2763 for (
int i = 0; i < nNum3dPoints; i++)
2765 fDist = Math3d::Distance(hResult->
vCenter, avCylinderPoints[i]);
2782 std::vector<CMSERDescriptor3D*>& aMSERs, std::vector<Vec3d>& aSigmaPoints,
const CByteImage* pLeftColorImage,
2783 const CByteImage* pLeftGreyImage)
2789 const int nNum3dPoints = avSpherePoints.GetSize();
2791 #pragma omp parallel
2795 #pragma omp for schedule(static, 5)
2796 for (
int i = 0; i < nNum3dPoints; i++)
2798 if (CreateFeatureDescriptorForPoint(pPoint, avSpherePoints[i], aMSERs, aSigmaPoints, pLeftColorImage, pLeftGreyImage))
2800 #pragma omp critical
2811 Math3d::SetVec(hResult->
vCenter, vSphereCenter);
2812 hResult->
fRadius = fSphereRadius;
2817 const float fVariance = GetVariance(avSpherePoints, vMean);
2818 Math3d::SubtractVecVec(vMean, vSphereCenter, hResult->
vNormal);
2819 Math3d::NormalizeVec(hResult->
vNormal);
2823 Vec3d vXAxis = {1, 0, 0};
2835 for (
int i = 0; i < nNum3dPoints; i++)
2837 fDist = Math3d::Distance(hResult->
vCenter, avSpherePoints[i]);
2855 bool CHypothesisGeneration::CreateFeatureDescriptorForPoint(
CHypothesisPoint* pPoint,
Vec3d vPosition, std::vector<CMSERDescriptor3D*>& aMSERs,
2856 std::vector<Vec3d>& aSigmaPoints,
const CByteImage* pLeftColorImage,
const CByteImage* pLeftGreyImage)
2864 calibration->WorldToImageCoordinates(vPosition, vPos2d,
false);
2865 const int nIndexX = round(vPos2d.x);
2866 const int nIndexY = round(vPos2d.y);
2873 const float fIntensity = pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX)] + pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX) + 1] + pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX) + 2] + 3;
2874 pPoint->
fIntensity = (fIntensity - 3) / (3 * 255);
2875 pPoint->
fColorR = (pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX)] + 1) / fIntensity;
2876 pPoint->
fColorG = (pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX) + 1] + 1) / fIntensity;
2877 pPoint->
fColorB = (pLeftColorImage->pixels[3 * (nIndexY *
OLP_IMG_WIDTH + nIndexX) + 2] + 1) / fIntensity;
2880 int nRegionIndex = FindRegionForPoint(vPosition, aMSERs);
2882 if (nRegionIndex >= 0)
2892 if (PointIsInList(vPosition, aSigmaPoints))
2908 bool CHypothesisGeneration::RANSACPlane(
const CVec3dArray& pointCandidates,
const float fRANSACThreshold,
2909 const int nIterations, CVec3dArray& resultPoints,
Vec3d& vAxis,
float& d)
2911 const int nPointCandidates = pointCandidates.GetSize();
2913 if (nPointCandidates < 3)
2915 ARMARX_WARNING_S <<
"At least 3 point candidates must be provided for RANSAC::RANSAC3DPlane (" << nPointCandidates <<
" provided)";
2919 const int nParallelityFactor = omp_get_num_procs();
2920 omp_set_num_threads(nParallelityFactor);
2922 int* pMaxPar =
new int[nParallelityFactor];
2923 float* pBestC =
new float[nParallelityFactor];
2924 Vec3d* pBestN =
new Vec3d[nParallelityFactor];
2926 for (
int i = 0; i < nParallelityFactor; i++)
2930 pBestN[i] = Math3d::zero_vec;
2934 #pragma omp parallel
2936 const int nProcIndex = omp_get_thread_num();
2938 #pragma omp for schedule(dynamic, 200)
2939 for (
int i = 0; i < nIterations; i++)
2942 srand((rand() % 17)*i + i);
2943 const int nFirstIndex = rand() % nPointCandidates;
2949 nTempIndex = rand() % nPointCandidates;
2951 while (nTempIndex == nFirstIndex);
2953 const int nSecondIndex = nTempIndex;
2957 nTempIndex = rand() % nPointCandidates;
2959 while (nTempIndex == nFirstIndex || nTempIndex == nSecondIndex);
2961 const Vec3d& p1 = pointCandidates[nFirstIndex];
2962 const Vec3d& p2 = pointCandidates[nSecondIndex];
2963 const Vec3d& p3 = pointCandidates[nTempIndex];
2966 Math3d::SubtractVecVec(p2, p1, u1);
2967 Math3d::SubtractVecVec(p3, p1, u2);
2968 Math3d::CrossProduct(u1, u2, n);
2969 Math3d::NormalizeVec(n);
2970 const float c = Math3d::ScalarProduct(n, p1);
2973 if (Math3d::ScalarProduct(n, n) < 0.9f)
2981 for (
int j = 0; j < nPointCandidates; j++)
2982 if (fabsf(Math3d::ScalarProduct(n, pointCandidates[j]) -
c) <= fRANSACThreshold)
2988 if (nSupport > pMaxPar[nProcIndex])
2990 pMaxPar[nProcIndex] = nSupport;
2991 Math3d::SetVec(pBestN[nProcIndex], n);
2992 pBestC[nProcIndex] =
c;
2999 Vec3d vBestN = {0, 0, 0};
3001 for (
int i = 0; i < nParallelityFactor; i++)
3003 if (pMaxPar[i] > nMax)
3007 Math3d::SetVec(vBestN, pBestN[i]);
3012 resultPoints.Clear();
3014 for (
int i = 0; i < nPointCandidates; i++)
3016 if (fabsf(Math3d::ScalarProduct(pointCandidates[i], vBestN) - fBestC) <= fRANSACThreshold)
3018 resultPoints.AddElement(pointCandidates[i]);
3022 Math3d::SetVec(vAxis, vBestN);
3035 void CHypothesisGeneration::AddSIFTFeatureDescriptors(
CSIFTFeatureArray* pFeatures,
Vec2d vPoint2d,
const CByteImage* pLeftGreyImage)
3037 CDynamicArray afSIFTDescriptors(10);
3038 m_pSIFTFeatureCalculator->CreateSIFTDescriptors(pLeftGreyImage, &afSIFTDescriptors, vPoint2d.x, vPoint2d.y, 0.8f,
false,
true);
3039 m_pSIFTFeatureCalculator->CreateSIFTDescriptors(pLeftGreyImage, &afSIFTDescriptors, vPoint2d.x, vPoint2d.y, 1.0f,
false,
true);
3040 m_pSIFTFeatureCalculator->CreateSIFTDescriptors(pLeftGreyImage, &afSIFTDescriptors, vPoint2d.x, vPoint2d.y, 1.25f,
false,
true);
3041 const int n = afSIFTDescriptors.GetSize();
3042 CSIFTFeatureEntry** ppFeatures =
new CSIFTFeatureEntry*[n];
3044 for (
int i = 0; i < n; i++)
3046 pFeatures->AddElement((CSIFTFeatureEntry*)((CSIFTFeatureEntry*)afSIFTDescriptors[i])->Clone());
3047 afSIFTDescriptors[i]->bDelete =
false;
3048 ppFeatures[i] = (CSIFTFeatureEntry*)afSIFTDescriptors[i];
3051 afSIFTDescriptors.Clear();
3053 for (
int i = 0; i < n; i++)
3055 delete ppFeatures[i];
3058 delete[] ppFeatures;
3064 void CHypothesisGeneration::ClusterXMeans(
const CVec3dArray& aPoints,
const int nMaxNumClusters,
const float fBICFactor,
3065 std::vector<CVec3dArray*>& aaPointClusters)
3068 cv::Mat mClusterLabels;
3069 cv::Mat pmClusterCenters;
3070 const int nNumberOfDifferentInitialisations = 5;
3074 const int nNumberOfSamples = aPoints.GetSize();
3075 mSamples.create(nNumberOfSamples, 3, CV_32FC1);
3077 for (
int i = 0; i < nNumberOfSamples; i++)
3079 mSamples.at<
float>(i, 0) = aPoints[i].x;
3080 mSamples.at<
float>(i, 1) = aPoints[i].y;
3081 mSamples.at<
float>(i, 2) = aPoints[i].z;
3084 mClusterLabels.create(nNumberOfSamples, 1, CV_32SC1);
3088 Vec3d* pvClusterMeans =
new Vec3d[nMaxNumClusters];
3089 double* pdClusterVariances =
new double[nMaxNumClusters];
3090 int* pnClusterSizes =
new int[nMaxNumClusters];
3091 double dMinBIC = 10000000;
3093 double dKMeansCompactness, dLogVar, dBIC;
3095 for (
int i = 1; (i <= nMaxNumClusters) && (i < nNumberOfSamples); i++)
3097 #ifdef OLP_USE_NEW_OPENCV
3098 dKMeansCompactness = cv::kmeans(mSamples, i, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_RANDOM_CENTERS, pmClusterCenters);
3101 dKMeansCompactness = cv::kmeans(mSamples, i, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_PP_CENTERS, &pmClusterCenters);
3107 double dMLVariance = 0;
3109 for (
int j = 0; j < i; j++)
3111 pvClusterMeans[j].x = 0;
3112 pvClusterMeans[j].y = 0;
3113 pvClusterMeans[j].z = 0;
3114 pdClusterVariances[j] = 0;
3115 pnClusterSizes[j] = 0;
3117 for (
int l = 0; l < nNumberOfSamples; l++)
3119 if (mClusterLabels.at<
int>(l, 0) == j)
3121 pvClusterMeans[j].x += mSamples.at<
float>(l, 0);
3122 pvClusterMeans[j].y += mSamples.at<
float>(l, 1);
3123 pvClusterMeans[j].z += mSamples.at<
float>(l, 2);
3124 pnClusterSizes[j]++;
3128 pvClusterMeans[j].x /= (
float)pnClusterSizes[j];
3129 pvClusterMeans[j].y /= (
float)pnClusterSizes[j];
3130 pvClusterMeans[j].z /= (
float)pnClusterSizes[j];
3132 for (
int l = 0; l < nNumberOfSamples; l++)
3134 if (mClusterLabels.at<
int>(l, 0) == j)
3136 pdClusterVariances[j] += (pvClusterMeans[j].x - mSamples.at<
float>(l, 0)) * (pvClusterMeans[j].x - mSamples.at<
float>(l, 0))
3137 + (pvClusterMeans[j].y - mSamples.at<
float>(l, 1)) * (pvClusterMeans[j].x - mSamples.at<
float>(l, 1))
3138 + (pvClusterMeans[j].z - mSamples.at<
float>(l, 2)) * (pvClusterMeans[j].x - mSamples.at<
float>(l, 2));
3142 if (pnClusterSizes[j] > 1)
3144 pdClusterVariances[j] /= (
float)(pnClusterSizes[j] - 1);
3148 pdClusterVariances[j] = 0;
3151 dMLVariance += pdClusterVariances[j];
3155 const int nNumberOfFreeParameters = (i - 1) + (3 * i) + i;
3156 dLogVar = log(dMLVariance);
3157 dBIC = fBICFactor * 0.35 * dLogVar + ((double)nNumberOfFreeParameters / (
double)nNumberOfSamples) * log((
double)nNumberOfSamples);
3171 #ifdef OLP_USE_NEW_OPENCV
3172 dKMeansCompactness = cv::kmeans(mSamples, nOptK, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_RANDOM_CENTERS, pmClusterCenters);
3175 dKMeansCompactness = cv::kmeans(mSamples, nOptK, mClusterLabels, tTerminationCriteria, nNumberOfDifferentInitialisations, cv::KMEANS_PP_CENTERS, &pmClusterCenters);
3197 aaPointClusters.clear();
3198 CVec3dArray* paDummy;
3200 for (
int i = 0; i < nOptK; i++)
3202 paDummy =
new CVec3dArray();
3203 aaPointClusters.push_back(paDummy);
3206 for (
int i = 0; i < nNumberOfSamples; i++)
3208 if ((mClusterLabels.at<
int>(i, 0) >= 0) && (mClusterLabels.at<
int>(i, 0) < nOptK))
3210 vPoint.x = mSamples.at<
float>(i, 0);
3211 vPoint.y = mSamples.at<
float>(i, 1);
3212 vPoint.z = mSamples.at<
float>(i, 2);
3213 aaPointClusters.at(mClusterLabels.at<
int>(i, 0))->AddElement(vPoint);
3217 ARMARX_WARNING_S <<
"Invalid cluster label: " << mClusterLabels.at<
int>(i, 0) <<
"nOptK: " << nOptK <<
", i: " << i <<
", nNumberOfSamples: "
3218 << nNumberOfSamples <<
", dKMeansCompactness: " << dKMeansCompactness;
3225 aaPointClusters.clear();
3226 CVec3dArray* paDummy =
new CVec3dArray();
3227 aaPointClusters.push_back(paDummy);
3230 for (
int i = 0; i < nNumberOfSamples; i++)
3232 vPoint.x = mSamples.at<
float>(i, 0);
3233 vPoint.y = mSamples.at<
float>(i, 1);
3234 vPoint.z = mSamples.at<
float>(i, 2);
3235 aaPointClusters.at(0)->AddElement(vPoint);
3240 delete[] pvClusterMeans;
3241 delete[] pdClusterVariances;
3242 delete[] pnClusterSizes;
3250 inline void CHypothesisGeneration::SortMSERsBySize(std::vector<CMSERDescriptor3D*>& aRegions3D)
3255 for (
int i = 1; i < (int)aRegions3D.size(); i++)
3257 pTemp = aRegions3D.at(i);
3260 while ((j > 0) && (aRegions3D.at(j - 1)->pRegionLeft->nSize < pTemp->
pRegionLeft->
nSize))
3262 aRegions3D.at(j) = aRegions3D.at(j - 1);
3266 aRegions3D.at(j) = pTemp;
3275 inline void CHypothesisGeneration::SortMSERsByX(std::vector<CMSERDescriptor3D*>& aRegions3D)
3280 for (
int i = 1; i < (int)aRegions3D.size(); i++)
3282 pTemp = aRegions3D.at(i);
3285 while ((j > 0) && (aRegions3D.at(j - 1)->vPosition.x > pTemp->
vPosition.x))
3287 aRegions3D.at(j) = aRegions3D.at(j - 1);
3291 aRegions3D.at(j) = pTemp;
3299 inline int CHypothesisGeneration::FindRegionForPoint(
Vec3d vPoint, std::vector<CMSERDescriptor3D*>& aRegions3D)
3303 int nRight = (int)aRegions3D.size() - 1;
3306 while (nRight > nLeft + 1)
3308 nIndex = nLeft + ((nRight - nLeft) >> 1);
3310 if (vPoint.x < aRegions3D.at(nIndex)->vPosition.x)
3314 else if (vPoint.x > aRegions3D.at(nIndex)->vPosition.x)
3323 while ((i >= nLeft) && (vPoint.x == aRegions3D.at(i)->vPosition.x))
3325 if ((vPoint.y == aRegions3D.at(i)->vPosition.y) && (vPoint.z == aRegions3D.at(i)->vPosition.z))
3338 while ((i <= nRight) && (vPoint.x == aRegions3D.at(i)->vPosition.x))
3340 if ((vPoint.y == aRegions3D.at(i)->vPosition.y) && (vPoint.z == aRegions3D.at(i)->vPosition.z))
3354 if (nLeft <= nRight)
3356 if ((vPoint.x == aRegions3D.at(nLeft)->vPosition.x) && (vPoint.y == aRegions3D.at(nLeft)->vPosition.y) && (vPoint.z == aRegions3D.at(nLeft)->vPosition.z))
3360 else if ((vPoint.x == aRegions3D.at(nRight)->vPosition.x) && (vPoint.y == aRegions3D.at(nRight)->vPosition.y) && (vPoint.z == aRegions3D.at(nRight)->vPosition.z))
3373 inline void CHypothesisGeneration::SortVec3dsByX(std::vector<Vec3d>& aPoints)
3378 for (
int i = 1; i < (int)aPoints.size(); i++)
3380 Math3d::SetVec(vTemp, aPoints.at(i));
3383 while ((j > 0) && (aPoints.at(j - 1).x > vTemp.x))
3385 Math3d::SetVec(aPoints.at(j), aPoints.at(j - 1));
3389 Math3d::SetVec(aPoints.at(j), vTemp);
3395 inline bool CHypothesisGeneration::PointIsInList(
Vec3d vPoint, std::vector<Vec3d>& aPoints)
3399 int nRight = (int)aPoints.size() - 1;
3402 while (nRight > nLeft + 1)
3404 nIndex = nLeft + ((nRight - nLeft) >> 1);
3406 if (vPoint.x < aPoints.at(nIndex).x)
3410 else if (vPoint.x > aPoints.at(nIndex).x)
3414 else if ((vPoint.y == aPoints.at(nIndex).y) && (vPoint.z == aPoints.at(nIndex).z))
3424 if (nLeft <= nRight)
3426 if ((vPoint.x == aPoints.at(nLeft).x) && (vPoint.y == aPoints.at(nLeft).y) && (vPoint.z == aPoints.at(nLeft).z))
3430 else if ((vPoint.x == aPoints.at(nRight).x) && (vPoint.y == aPoints.at(nRight).y) && (vPoint.z == aPoints.at(nRight).z))
3441 void CHypothesisGeneration::CalculateSphere(
Vec3d vPoint1,
Vec3d vPoint2,
Vec3d vPoint3,
Vec3d vPoint4,
Vec3d& vCenter,
float& fRadius)
3485 float pSubmatrix[16];
3488 float fDetM11, fDetM12, fDetM13, fDetM14, fDetM15;
3579 Math3d::SetVec(pPoints[0], vPoint1);
3580 Math3d::SetVec(pPoints[1], vPoint2);
3581 Math3d::SetVec(pPoints[2], vPoint3);
3582 Math3d::SetVec(pPoints[3], vPoint4);
3585 for (
int i = 0; i < 4; i++)
3587 pSubmatrix[4 * i + 0] = pPoints[i].x;
3588 pSubmatrix[4 * i + 1] = pPoints[i].y;
3589 pSubmatrix[4 * i + 2] = pPoints[i].z;
3590 pSubmatrix[4 * i + 3] = 1;
3596 for (
int i = 0; i < 4; i++)
3598 pSubmatrix[4 * i + 0] = pPoints[i].x * pPoints[i].x + pPoints[i].y * pPoints[i].y + pPoints[i].z * pPoints[i].z;
3599 pSubmatrix[4 * i + 1] = pPoints[i].y;
3600 pSubmatrix[4 * i + 2] = pPoints[i].z;
3601 pSubmatrix[4 * i + 3] = 1;
3607 for (
int i = 0; i < 4; i++)
3609 pSubmatrix[4 * i + 0] = pPoints[i].x;
3610 pSubmatrix[4 * i + 1] = pPoints[i].x * pPoints[i].x + pPoints[i].y * pPoints[i].y + pPoints[i].z * pPoints[i].z;
3611 pSubmatrix[4 * i + 2] = pPoints[i].z;
3612 pSubmatrix[4 * i + 3] = 1;
3618 for (
int i = 0; i < 4; i++)
3620 pSubmatrix[4 * i + 0] = pPoints[i].x;
3621 pSubmatrix[4 * i + 1] = pPoints[i].y;
3622 pSubmatrix[4 * i + 2] = pPoints[i].x * pPoints[i].x + pPoints[i].y * pPoints[i].y + pPoints[i].z * pPoints[i].z;
3623 pSubmatrix[4 * i + 3] = 1;
3629 for (
int i = 0; i < 4; i++)
3631 pSubmatrix[4 * i + 0] = pPoints[i].x * pPoints[i].x + pPoints[i].y * pPoints[i].y + pPoints[i].z * pPoints[i].z;
3632 pSubmatrix[4 * i + 1] = pPoints[i].x;
3633 pSubmatrix[4 * i + 2] = pPoints[i].y;
3634 pSubmatrix[4 * i + 3] = pPoints[i].z;
3642 vCenter.x = 0.5f * fDetM12 / fDetM11;
3643 vCenter.y = -0.5f * fDetM13 / fDetM11;
3644 vCenter.z = 0.5f * fDetM14 / fDetM11;
3645 fRadius = sqrtf(vCenter.x * vCenter.x + vCenter.y * vCenter.y + vCenter.z * vCenter.z - fDetM15 / fDetM11);
3656 for (
int n = 0; n < 4; n++)
3659 for (
int i = 0; i < 3; i++)
3661 for (
int j = 0, l = 0; j < 4; j++)
3665 pSubMat[3 * i + l] = pMatrix[4 * (i + 1) + j];
3671 fDet = pSubMat[0] * pSubMat[4] * pSubMat[8] + pSubMat[1] * pSubMat[5] * pSubMat[6] + pSubMat[2] * pSubMat[3] * pSubMat[7]
3672 - pSubMat[2] * pSubMat[4] * pSubMat[6] - pSubMat[1] * pSubMat[3] * pSubMat[8] - pSubMat[0] * pSubMat[5] * pSubMat[7];
3674 if ((n == 0) || (n == 2))
3676 fRet += pMatrix[n] * fDet;
3680 fRet -= pMatrix[n] * fDet;
3690 bool CHypothesisGeneration::RANSACSphere(
const CVec3dArray& aPointCandidates,
const float fRANSACThreshold,
const float fMaxSphereRadius,
3691 const int nMaxIterations, CVec3dArray& aResultPoints,
Vec3d& vCenter,
float& fRadius)
3693 const int nPointCandidates = aPointCandidates.GetSize();
3695 aResultPoints.Clear();
3697 if (nPointCandidates < 4)
3699 ARMARX_WARNING_S <<
"At least 4 point candidates must be provided for RANSAC for sphere (" << nPointCandidates <<
" provided)";
3703 int nMaxSupport = 0;
3709 const int nIterations = (nTemp > nMaxIterations) ? nMaxIterations : nTemp;
3711 #pragma omp parallel
3713 #pragma omp for schedule(static, 40)
3714 for (
int i = 0; i < nIterations; i++)
3717 srand((rand() % 17)*i + i);
3719 const int nFirstIndex = rand() % nPointCandidates;
3723 nTempIndex = rand() % nPointCandidates;
3725 while (nTempIndex == nFirstIndex);
3727 const int nSecondIndex = nTempIndex;
3731 nTempIndex = rand() % nPointCandidates;
3733 while (nTempIndex == nFirstIndex || nTempIndex == nSecondIndex);
3735 const int nThirdIndex = nTempIndex;
3739 nTempIndex = rand() % nPointCandidates;
3741 while (nTempIndex == nFirstIndex || nTempIndex == nSecondIndex || nTempIndex == nThirdIndex);
3743 const Vec3d& p1 = aPointCandidates[nFirstIndex];
3744 const Vec3d& p2 = aPointCandidates[nSecondIndex];
3745 const Vec3d& p3 = aPointCandidates[nThirdIndex];
3746 const Vec3d& p4 = aPointCandidates[nTempIndex];
3765 CalculateSphere(p1, p2, p3, p4, vTempCenter, fTempRadius);
3768 if (fTempRadius == 0)
3774 if ((fTempRadius > 100) || (vTempCenter.z < 100))
3782 for (
int j = 0; j < nPointCandidates; j++)
3784 if (fabsf(Math3d::Distance(vTempCenter, aPointCandidates[j]) - fTempRadius) <= fRANSACThreshold)
3794 if (nSupport > nMaxSupport)
3796 #pragma omp critical
3797 if (nSupport > nMaxSupport)
3799 nMaxSupport = nSupport;
3800 Math3d::SetVec(vBestCenter, vTempCenter);
3801 fBestRadius = fTempRadius;
3808 if (nMaxSupport < 4)
3813 for (
int i = 0; i < nPointCandidates; i++)
3815 if (fabsf(Math3d::Distance(vBestCenter, aPointCandidates[i]) - fBestRadius) <= fRANSACThreshold)
3817 aResultPoints.AddElement(aPointCandidates[i]);
3821 Math3d::SetVec(vCenter, vBestCenter);
3822 fRadius = fBestRadius;