29 assert(hist1.size() == hist2.size());
31 double BhattachDist_aux = 0.0;
32 for (
unsigned i = 0; i < hist1.size(); i++)
33 BhattachDist_aux += sqrt(hist1[i] * hist2[i]);
35 BhattachDist = sqrt(1 - BhattachDist_aux);
40 SubgraphMatcher::SubgraphMatcher()
48 bool SubgraphMatcher::evalUnaryConstraints(
56 cout <<
"unary between " << plane1.
id <<
" " << plane2.
id <<
"\n";
101 configLocaliser.hue_threshold)
104 cout <<
"Hist_H false " 106 << configLocaliser.hue_threshold <<
"\n";
135 if (rel_areas < configLocaliser.area_full_threshold_inv ||
136 rel_areas > configLocaliser.area_full_threshold)
139 cout <<
"False: rel_areas full " << rel_areas << endl;
146 if (rel_elong < configLocaliser.elongation_threshold_inv ||
147 rel_elong > configLocaliser.elongation_threshold)
150 cout <<
"False: rel_elong full " << rel_elong << endl;
160 if (rel_areas < configLocaliser.area_full_threshold_inv ||
161 rel_areas > configLocaliser.area_threshold)
164 cout <<
"rel_areas RefFull " << rel_areas << endl;
171 if (rel_areas < configLocaliser.area_threshold_inv ||
172 rel_areas > configLocaliser.area_full_threshold)
175 cout <<
"rel_areas CheckFull " << rel_areas << endl;
181 rel_areas < configLocaliser.area_threshold_inv ||
182 rel_areas > configLocaliser.area_threshold)
185 cout <<
"rel_areas simple " << rel_areas << endl;
191 if (rel_elong < configLocaliser.elongation_threshold_inv ||
192 rel_elong > configLocaliser.elongation_threshold)
195 cout <<
"rel_elong simple " << rel_elong << endl;
204 cout <<
"UNARY TRUE" << endl;
210 bool SubgraphMatcher::evalUnaryConstraintsOdometry(
218 cout <<
"unaryOdometry between " << plane1.
id <<
" " << plane2.
id <<
"\n";
224 if (fabs(plane1.
d - plane2.
d) > configLocaliser.dist_d)
227 cout <<
"depthUnaryConstraint false " << fabs(plane1.
d - plane2.
d)
228 <<
" > " << configLocaliser.dist_d <<
"\n";
236 cout <<
"angleUnaryConstraint false " 238 << configLocaliser.angle <<
"\n";
284 configLocaliser.hue_threshold)
287 cout <<
"Hist_H false_ " 289 << configLocaliser.hue_threshold <<
"\n";
321 if (rel_areas < configLocaliser.area_full_threshold_inv ||
322 rel_areas > configLocaliser.area_full_threshold)
325 cout <<
"False: rel_areas full " << rel_areas << endl;
332 if (rel_elong < configLocaliser.elongation_threshold_inv ||
333 rel_elong > configLocaliser.elongation_threshold)
336 cout <<
"False: rel_elong full " << rel_elong << endl;
346 if (rel_areas < configLocaliser.area_full_threshold_inv ||
347 rel_areas > configLocaliser.area_threshold)
350 cout <<
"rel_areas RefFull " << rel_areas << endl;
357 if (rel_areas < configLocaliser.area_threshold_inv ||
358 rel_areas > configLocaliser.area_full_threshold)
361 cout <<
"rel_areas CheckFull " << rel_areas << endl;
367 rel_areas < configLocaliser.area_threshold_inv ||
368 rel_areas > configLocaliser.area_threshold)
371 cout <<
"rel_areas simple " << rel_areas << endl;
377 if (rel_elong < configLocaliser.elongation_threshold_inv ||
378 rel_elong > configLocaliser.elongation_threshold)
381 cout <<
"rel_elong simple " << rel_elong << endl;
390 cout <<
"UNARY TRUE" << endl;
396 bool SubgraphMatcher::evalUnaryConstraints2D(
404 cout <<
"unary2D between " << plane1.
id <<
" " << plane2.
id <<
"\n";
414 if (fabs(plane1.
d - plane2.
d) < 0.15)
463 configLocaliser.hue_threshold)
466 cout <<
"Hist_H false " 468 << configLocaliser.hue_threshold <<
"\n";
497 if (rel_areas < configLocaliser.area_full_threshold_inv ||
498 rel_areas > configLocaliser.area_full_threshold)
501 cout <<
"False: rel_areas full " << rel_areas << endl;
508 if (rel_elong < configLocaliser.elongation_threshold_inv ||
509 rel_elong > configLocaliser.elongation_threshold)
512 cout <<
"False: rel_elong full " << rel_elong << endl;
522 if (rel_areas < configLocaliser.area_full_threshold_inv ||
523 rel_areas > configLocaliser.area_threshold)
526 cout <<
"rel_areas RefFull " << rel_areas << endl;
533 if (rel_areas < configLocaliser.area_threshold_inv ||
534 rel_areas > configLocaliser.area_full_threshold)
537 cout <<
"rel_areas CheckFull " << rel_areas << endl;
543 rel_areas < configLocaliser.area_threshold_inv ||
544 rel_areas > configLocaliser.area_threshold)
547 cout <<
"rel_areas simple " << rel_areas << endl;
553 if (rel_elong < configLocaliser.elongation_threshold_inv ||
554 rel_elong > configLocaliser.elongation_threshold)
557 cout <<
"rel_elong simple " << rel_elong << endl;
566 cout <<
"UNARY TRUE" << endl;
572 bool SubgraphMatcher::evalUnaryConstraintsOdometry2D(
580 cout <<
"unaryOdometry2D between " << plane1.
id <<
" " << plane2.
id <<
"\n";
591 if (fabs(plane1.
d - plane2.
d) < 0.12)
598 cout <<
"pass 2D \n";
602 if (fabs(plane1.
d - plane2.
d) > configLocaliser.dist_d)
605 cout <<
"depthUnaryConstraint false " << fabs(plane1.
d - plane2.
d)
606 <<
" > " << configLocaliser.dist_d <<
"\n";
614 cout <<
"angleUnaryConstraint false " 616 << configLocaliser.angle <<
"\n";
662 configLocaliser.hue_threshold)
665 cout <<
"Hist_H false_ " 667 << configLocaliser.hue_threshold <<
"\n";
699 if (rel_areas < configLocaliser.area_full_threshold_inv ||
700 rel_areas > configLocaliser.area_full_threshold)
703 cout <<
"False: rel_areas full " << rel_areas << endl;
710 if (rel_elong < configLocaliser.elongation_threshold_inv ||
711 rel_elong > configLocaliser.elongation_threshold)
714 cout <<
"False: rel_elong full " << rel_elong << endl;
724 if (rel_areas < configLocaliser.area_full_threshold_inv ||
725 rel_areas > configLocaliser.area_threshold)
728 cout <<
"rel_areas RefFull " << rel_areas << endl;
735 if (rel_areas < configLocaliser.area_threshold_inv ||
736 rel_areas > configLocaliser.area_full_threshold)
739 cout <<
"rel_areas CheckFull " << rel_areas << endl;
745 rel_areas < configLocaliser.area_threshold_inv ||
746 rel_areas > configLocaliser.area_threshold)
749 cout <<
"rel_areas simple " << rel_areas << endl;
755 if (rel_elong < configLocaliser.elongation_threshold_inv ||
756 rel_elong > configLocaliser.elongation_threshold)
759 cout <<
"rel_elong simple " << rel_elong << endl;
768 cout <<
"UNARY TRUE" << endl;
778 bool SubgraphMatcher::evalBinaryConstraints(
793 double dif_height = fabs(
798 float threshold_dist_dependent =
799 configLocaliser.height_threshold *
801 float height_threshold = std::max(
802 configLocaliser.height_threshold, threshold_dist_dependent);
803 if (dif_height > height_threshold)
807 cout <<
"Binary false: Ref dif_height " << dif_height << endl;
815 double dif_height = fabs(
823 configLocaliser.height_threshold;
824 if (dif_height > height_threshold)
828 cout <<
"Binary false BIG Area: Ref dif_height " << dif_height
838 double dif_height2 = fabs(
843 float threshold_dist_dependent =
844 configLocaliser.height_threshold *
846 float height_threshold = std::max(
847 configLocaliser.height_threshold, threshold_dist_dependent);
848 if (dif_height2 > height_threshold)
852 cout <<
"Binary false: neigRef dif_height2 " << dif_height2 << endl;
860 double dif_height2 = fabs(
867 float height_threshold =
869 if (dif_height2 > height_threshold)
873 cout <<
"Binary false: neigRef dif_height2 " << dif_height2 << endl;
881 double dif_normal = fabs(
RAD2DEG(
885 if (dif_normal > std::max(
886 configLocaliser.angle_threshold,
890 cout <<
"Binary false: angle " << dif_normal <<
" with " << neigRef.
id 898 double rel_dist_centers = sqrt(
910 if (configLocaliser.use_completeness)
912 if (RefBothFull && CheckBothFull)
914 if (rel_dist_centers < configLocaliser.dist_threshold_inv ||
915 rel_dist_centers > configLocaliser.dist_threshold)
918 cout <<
"Binary false: dist_centers1 with " << neigRef.
id 925 else if (RefBothFull || CheckBothFull)
927 if (rel_dist_centers < configLocaliser.dist_threshold_inv ||
928 rel_dist_centers > configLocaliser.dist_threshold)
931 cout <<
"Binary false: dist_centers2 with " << neigRef.
id 941 if (rel_dist_centers < configLocaliser.dist_threshold_inv ||
942 rel_dist_centers > configLocaliser.dist_threshold)
945 cout <<
"Binary false: dist_centers3 with " << neigRef.
id 958 if (rel_dist_centers < configLocaliser.dist_threshold_inv ||
959 rel_dist_centers > configLocaliser.dist_threshold)
962 cout <<
"Binary false: dist_centers4 with " << neigRef.
id 974 cout <<
"BINARY TRUE\n" << endl;
981 map<unsigned, unsigned>& contained, map<unsigned, unsigned>& container)
983 if (contained.size() > container.size())
return false;
986 for (
auto it = contained.begin(); it != contained.end(); it++)
987 if (container.count(it->first) == 0)
989 else if (container[it->first] != it->second)
993 cout <<
"Repeated sequence. Comparing:\n";
994 for (map<unsigned, unsigned>::iterator it = contained.begin();
995 it != contained.end(); it++)
996 cout << it->first <<
" " << it->second << endl;
998 for (map<unsigned, unsigned>::iterator it = container.begin();
999 it != container.end(); it++)
1000 cout << it->first <<
" " << it->second << endl;
1013 void SubgraphMatcher::exploreSubgraphTreeR(
1014 set<unsigned>& sourcePlanes, set<unsigned>& targetPlanes,
1015 map<unsigned, unsigned>& matched)
1018 cout <<
"matched: " << matched.size() <<
"\n";
1019 for (map<unsigned, unsigned>::iterator it = matched.begin();
1020 it != matched.end(); it++)
1021 cout << it->first <<
" - " << it->second <<
" =" 1022 << subgraphTrg->pPBM->vPlanes[it->second].label << endl;
1023 cout <<
"sourcePlanes: " << sourcePlanes.size() <<
": ";
1024 for (set<unsigned>::iterator it1 = sourcePlanes.begin();
1025 it1 != sourcePlanes.end(); it1++)
1026 cout << *it1 <<
" ";
1027 cout <<
"\ntargetPlanes " << targetPlanes.size() <<
": ";
1028 for (set<unsigned>::iterator it2 = targetPlanes.begin();
1029 it2 != targetPlanes.end(); it2++)
1030 cout << *it2 <<
" ";
1040 unsigned requiredMatches =
1041 max(configLocaliser.min_planes_recognition,
1042 static_cast<unsigned>(winnerMatch.size()));
1063 while (!sourcePlanes.empty())
1065 auto it1 = sourcePlanes.begin();
1067 cout <<
"Compare " << *it1
1068 <<
" Compare Compare Compare Compare Compare " << endl;
1071 if ((matched.size() +
min(sourcePlanes.size(), targetPlanes.size())) <=
1075 cout <<
"End branch recursive search. Too short " << matched.size()
1076 <<
" prev winner " << winnerMatch.size() << endl;
1092 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end(); it2++)
1095 cout <<
" " << *it1 <<
" with " << *it2 << endl;
1129 if (hashUnaryConstraints[*it1][*it2] != 1)
1134 bool binaryFail =
false;
1135 for (
auto it_matched = matched.begin(); it_matched != matched.end();
1137 if (!evalBinaryConstraints(
1138 subgraphSrc->pPBM->vPlanes[*it1],
1139 subgraphSrc->pPBM->vPlanes[it_matched->first],
1140 subgraphTrg->pPBM->vPlanes[*it2],
1141 subgraphTrg->pPBM->vPlanes[it_matched->second]))
1146 if (binaryFail)
continue;
1151 set<unsigned> nextSrcPlanes = sourcePlanes;
1152 nextSrcPlanes.erase(*it1);
1153 set<unsigned> nextTrgPlanes = targetPlanes;
1154 nextTrgPlanes.erase(*it2);
1155 map<unsigned, unsigned> nextMatched = matched;
1156 nextMatched[*it1] = *it2;
1158 alreadyExplored.push_back(nextMatched);
1160 exploreSubgraphTreeR(nextSrcPlanes, nextTrgPlanes, nextMatched);
1166 sourcePlanes.erase(it1);
1169 if (matched.size() > winnerMatch.size())
1171 float areaMatched = calcAreaMatched(matched);
1174 cout <<
"End branch recursive search. matched " << matched.size()
1175 <<
" A " << areaMatched <<
" prev winner " << winnerMatch.size()
1176 <<
" A " << areaWinnerMatch << endl;
1178 areaWinnerMatch = areaMatched;
1179 winnerMatch = matched;
1183 void SubgraphMatcher::exploreSubgraphTreeR_Area(
1184 set<unsigned>& sourcePlanes, set<unsigned>& targetPlanes,
1185 map<unsigned, unsigned>& matched)
1188 cout <<
"matched: " << matched.size() <<
"\n";
1189 for (map<unsigned, unsigned>::iterator it = matched.begin();
1190 it != matched.end(); it++)
1191 cout << it->first <<
" - " << it->second <<
" =" 1192 << subgraphTrg->pPBM->vPlanes[it->second].label << endl;
1193 cout <<
"sourcePlanes: " << sourcePlanes.size() <<
": ";
1194 for (set<unsigned>::iterator it1 = sourcePlanes.begin();
1195 it1 != sourcePlanes.end(); it1++)
1196 cout << *it1 <<
" ";
1197 cout <<
"\ntargetPlanes " << targetPlanes.size() <<
": ";
1198 for (set<unsigned>::iterator it2 = targetPlanes.begin();
1199 it2 != targetPlanes.end(); it2++)
1200 cout << *it2 <<
" ";
1210 float matchedArea = calcAreaMatched(matched);
1212 float unmatchedArea = 0;
1213 for (
auto it1 = sourcePlanes.begin(); it1 != sourcePlanes.end(); it1++)
1214 unmatchedArea += subgraphSrc->pPBM->vPlanes[*it1].areaHull;
1219 while (!sourcePlanes.empty())
1221 auto it1 = sourcePlanes.begin();
1223 cout <<
"Compare " << *it1
1224 <<
" Compare Compare Compare Compare Compare " << endl;
1227 if ((matched.size() +
min(sourcePlanes.size(), targetPlanes.size())) <=
1228 configLocaliser.min_planes_recognition)
1229 if ((matchedArea + unmatchedArea) < areaWinnerMatch)
1232 cout <<
"End branch recursive search. Too short " 1233 << matched.size() <<
" prev winner " << winnerMatch.size()
1250 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end(); it2++)
1253 cout <<
" " << *it1 <<
" with " << *it2 << endl;
1287 if (hashUnaryConstraints[*it1][*it2] != 1)
1292 bool binaryFail =
false;
1293 for (
auto it_matched = matched.begin(); it_matched != matched.end();
1295 if (!evalBinaryConstraints(
1296 subgraphSrc->pPBM->vPlanes[*it1],
1297 subgraphSrc->pPBM->vPlanes[it_matched->first],
1298 subgraphTrg->pPBM->vPlanes[*it2],
1299 subgraphTrg->pPBM->vPlanes[it_matched->second]))
1304 if (binaryFail)
continue;
1309 set<unsigned> nextSrcPlanes = sourcePlanes;
1310 nextSrcPlanes.erase(*it1);
1311 set<unsigned> nextTrgPlanes = targetPlanes;
1312 nextTrgPlanes.erase(*it2);
1313 map<unsigned, unsigned> nextMatched = matched;
1314 nextMatched[*it1] = *it2;
1316 alreadyExplored.push_back(nextMatched);
1318 exploreSubgraphTreeR_Area(
1319 nextSrcPlanes, nextTrgPlanes, nextMatched);
1325 sourcePlanes.erase(it1);
1329 float areaMatched = calcAreaMatched(matched);
1330 if (areaMatched > areaWinnerMatch)
1333 cout <<
"End branch recursive search. matched " << matched.size()
1334 <<
" A " << areaMatched <<
" prev winner " << winnerMatch.size()
1335 <<
" A " << areaWinnerMatch << endl;
1337 areaWinnerMatch = areaMatched;
1338 winnerMatch = matched;
1342 float SubgraphMatcher::calcAreaMatched(
1343 std::map<unsigned, unsigned>& matched_planes)
1345 float areaMatched = 0;
1346 for (
auto it = matched_planes.begin(); it != matched_planes.end(); it++)
1347 areaMatched += subgraphSrc->pPBM->vPlanes[it->first].areaHull;
1352 float SubgraphMatcher::calcAreaUnmatched(std::set<unsigned>& unmatched_planes)
1354 float areaUnatched = 0;
1355 for (
auto it = unmatched_planes.begin(); it != unmatched_planes.end(); it++)
1356 areaUnatched += subgraphSrc->pPBM->vPlanes[*it].areaHull;
1358 return areaUnatched;
1396 std::map<unsigned, unsigned> SubgraphMatcher::compareSubgraphs(
1400 subgraphSrc = &subgraphSource;
1401 subgraphTrg = &subgraphTarget;
1402 map<unsigned, unsigned> matched;
1404 areaWinnerMatch = 0;
1405 winnerMatch.clear();
1406 alreadyExplored.clear();
1409 std::set<unsigned> targetPlanes = subgraphTrg->subgraphPlanesIdx;
1412 cout <<
"Source planes: ";
1413 for (set<unsigned>::iterator it2 = sourcePlanes.begin();
1414 it2 != sourcePlanes.end(); it2++)
1415 cout <<
" " << *it2;
1417 cout <<
"Target planes: ";
1418 for (set<unsigned>::iterator it2 = targetPlanes.begin();
1419 it2 != targetPlanes.end(); it2++)
1420 cout <<
" " << *it2;
1425 hashUnaryConstraints = std::vector<std::vector<int8_t>>(
1426 subgraphSrc->pPBM->vPlanes.size(),
1427 std::vector<int8_t>(subgraphTrg->pPBM->vPlanes.size()));
1429 for (
auto it1 = sourcePlanes.begin(); it1 != sourcePlanes.end(); it1++)
1430 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end();
1432 hashUnaryConstraints[*it1][*it2] =
1433 (evalUnaryConstraints(
1434 subgraphSrc->pPBM->vPlanes[*it1],
1435 subgraphTrg->pPBM->vPlanes[*it2], *subgraphTrg->pPBM,
1439 else if (option == 1)
1440 for (
auto it1 = sourcePlanes.begin(); it1 != sourcePlanes.end(); it1++)
1441 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end();
1443 hashUnaryConstraints[*it1][*it2] =
1444 (evalUnaryConstraintsOdometry(
1445 subgraphSrc->pPBM->vPlanes[*it1],
1446 subgraphTrg->pPBM->vPlanes[*it2], *subgraphTrg->pPBM,
1450 else if (option == 2)
1452 for (
auto it1 = sourcePlanes.begin(); it1 != sourcePlanes.end(); it1++)
1453 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end();
1455 hashUnaryConstraints[*it1][*it2] =
1456 (evalUnaryConstraints2D(
1457 subgraphSrc->pPBM->vPlanes[*it1],
1458 subgraphTrg->pPBM->vPlanes[*it2], *subgraphTrg->pPBM,
1462 else if (option == 3)
1464 for (
auto it1 = sourcePlanes.begin(); it1 != sourcePlanes.end(); it1++)
1465 for (
auto it2 = targetPlanes.begin(); it2 != targetPlanes.end();
1467 hashUnaryConstraints[*it1][*it2] =
1468 (evalUnaryConstraintsOdometry2D(
1469 subgraphSrc->pPBM->vPlanes[*it1],
1470 subgraphTrg->pPBM->vPlanes[*it2], *subgraphTrg->pPBM,
1475 exploreSubgraphTreeR(sourcePlanes, targetPlanes, matched);
1478 cout <<
"Area winnerMatch " << areaWinnerMatch << endl;
A class used to store a planar feature (Plane for short).
double BhattacharyyaDist_(std::vector< float > &hist1, std::vector< float > &hist2)
bool isSubgraphContained(map< unsigned, unsigned > &contained, map< unsigned, unsigned > &container)
unsigned id
! Parameters to allow the plane-based representation of the map by a graph
std::vector< float > hist_H
Eigen::Vector3f v3center
! Geometric description
std::set< unsigned > subgraphPlanesIdx
A class used to store a Plane-based Map (PbMap).
CONTAINER::Scalar norm(const CONTAINER &v)