8 #ifndef META_OCEAN_TRACKING_VOCABULAR_TREE_H
9 #define META_OCEAN_TRACKING_VOCABULAR_TREE_H
28 class VocabularyStructure;
85 template <
typename TDistance>
143 template <
typename TDistance>
144 using Matches = std::vector<Match<TDistance>>;
221 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
244 static constexpr TDistance(*
distanceFunction)(
const TDescriptor&,
const TDescriptor&) = tDistanceFunction;
292 template <
typename TMultiDescriptor>
300 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor>
318 friend class VocabularyTree<TDescriptor, TDistance, tDistanceFunction>;
378 void determineBestLeafs(
const TDescriptor& descriptor, std::vector<const Indices32*>& leafs,
const TDistance distanceEpsilon = TDistance(0))
const;
389 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
402 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
417 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
434 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
447 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
448 void matchDescriptors(
const TDescriptor* candidateDescriptors,
const TDescriptor* queryDescriptors,
const size_t numberQueryDescriptors,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
462 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
463 void matchMultiDescriptors(
const TDescriptor* candidateDescriptors,
const TMultiDescriptor* queryMultiDescriptors,
const size_t numberQueryMultiDescriptors,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
479 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
480 void matchMultiDescriptorGroups(
const TDescriptor* candidateDescriptors,
const TMultiDescriptorGroup* queryMultiDescriptorGroups,
const size_t numberQueryMultiDescriptorGroups,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
525 template <
unsigned int tSize>
539 template <
unsigned int tSize>
564 VocabularyTree(
const unsigned int level,
const TDescriptor&
nodeDescriptor,
const Parameters& parameters,
const TDescriptor* treeDescriptors,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
const size_t numberDescriptorsIndices,
RandomGenerator& randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction& clustersMeanFunction,
Worker* worker);
591 void createChildNodes(
const unsigned int childNodeLevel,
const Parameters& parameters,
const TDescriptor* treeDescriptors,
const TDescriptor* clusterCenters,
const unsigned int* clusterSizes,
const size_t numberClusters,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
const size_t numberDescriptorsIndices,
RandomGenerator& randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction& clustersMeanFunction,
Worker* worker);
675 void createChildNodesSubset(
const unsigned int childNodeLevel,
const Parameters* parameters,
const TDescriptor* treeDescriptors,
const TDescriptor* clusterCenters,
const unsigned int* clusterSizes,
const size_t numberClusters,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
const size_t numberDescriptorsIndices,
RandomGenerator* randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction* clustersMeanFunction,
const unsigned int subsetFirstCluster,
const unsigned int subsetNumberClusters);
703 template <MatchingMode tMatchingMode>
704 void matchDescriptorsSubset(
const TDescriptor* candidateDescriptors,
const TDescriptor* queryDescriptors,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryDescriptor,
const unsigned int numberQueryDescriptors)
const;
719 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode>
720 void matchMultiDescriptorsSubset(
const TDescriptor* candidateDescriptors,
const TMultiDescriptor* queryMultiDescriptors,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryMultiDescriptor,
const unsigned int numberQueryMultiDescriptors)
const;
737 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode>
738 void matchMultiDescriptorGroupsSubset(
const TDescriptor* candidateDescriptors,
const TMultiDescriptorGroup* queryMultiDescriptorGroups,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryMultiDescriptorGroup,
const unsigned int numberQueryMultiDescriptorGroups)
const;
764 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
782 static constexpr TDistance(*
distanceFunction)(
const TDescriptor&,
const TDescriptor&) = tDistanceFunction;
820 template <
typename TMultiDescriptor>
828 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor>
873 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
887 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
902 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
919 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
933 template <MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
934 void matchDescriptors(
const TDescriptor* candidateDescriptors,
const TDescriptor* queryDescriptors,
const size_t numberQueryDescriptors,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
949 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
950 void matchMultiDescriptors(
const TDescriptor* candidateDescriptors,
const TMultiDescriptor* queryMultiDescriptors,
const size_t numberQueryMultiDescriptors,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
966 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode = MM_FIRST_BEST_LEAF>
967 void matchMultiDescriptorGroups(
const TDescriptor* candidateDescriptors,
const TMultiDescriptorGroup* queryMultiDescriptorGroups,
const size_t numberQueryMultiDescriptorGroups,
const TDistance maximalDistance,
Matches& matches,
Worker* worker =
nullptr)
const;
982 template <MatchingMode tMatchingMode>
983 void matchDescriptorsSubset(
const TDescriptor* candidateDescriptors,
const TDescriptor* queryDescriptors,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryDescriptor,
const unsigned int numberQueryDescriptors)
const;
998 template <
typename TMultiDescriptor, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode>
999 void matchMultiDescriptorsSubset(
const TDescriptor* candidateDescriptors,
const TMultiDescriptor* queryMultiDescriptors,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryMultiDescriptor,
const unsigned int numberQueryMultiDescriptors)
const;
1016 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, MultiDescriptorGroupFunction<TMultiDescriptorGroup, TMultiDescriptor> tMultiDescriptorGroupFunction, MultiDescriptorFunction<TMultiDescriptor> tMultiDescriptorFunction, MatchingMode tMatchingMode>
1017 void matchMultiDescriptorGroupsSubset(
const TDescriptor* candidateDescriptors,
const TMultiDescriptorGroup* queryMultiDescriptorGroups,
const TDistance maximalDistance,
Matches* matches,
Lock* lock,
const unsigned int firstQueryMultiDescriptorGroup,
const unsigned int numberQueryMultiDescriptorGroups)
const;
1030 template <
typename TDistance>
1032 candidateDescriptorIndex_(candidateDescriptorIndex),
1033 queryDescriptorIndex_(queryDescriptorIndex),
1039 template <
typename TDistance>
1042 return candidateDescriptorIndex_;
1045 template <
typename TDistance>
1048 return queryDescriptorIndex_;
1051 template <
typename TDistance>
1057 template <
typename TDistance>
1064 maximalNumberClustersPerLevel_(maximalNumberClustersPerLevel),
1065 maximalDescriptorsPerLeaf_(maximalDescriptorsPerLeaf),
1066 maximalLevels_(maximalLevels),
1067 initializationStrategy_(initializationStrategy)
1074 return maximalNumberClustersPerLevel_ >= 2u && maximalDescriptorsPerLeaf_ >= 1u && maximalLevels_ >= 1u && initializationStrategy_ !=
IS_INVALID;
1079 std::vector<uint8_t> lookup(256 * 8);
1081 for (
unsigned int n = 0u; n < 256u; ++n)
1083 uint8_t*
const lookupValues = lookup.data() + n * 8u;
1085 for (
unsigned int i = 0; i < 8u; ++i)
1089 lookupValues[i] = 1u;
1093 lookupValues[i] = 0u;
1101 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1104 static_assert(tDistanceFunction !=
nullptr,
"Invalid distance function!");
1109 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1112 static_assert(tDistanceFunction !=
nullptr,
"Invalid distance function!");
1114 ocean_assert(parameters.
isValid());
1116 ocean_assert(numberTreeDescriptors > 0);
1118 Indices32 reusableDescriptorIndicesInput = Ocean::createIndices<Index32>(numberTreeDescriptors, 0u);
1119 Indices32 reusableDescriptorIndicesOutput(numberTreeDescriptors);
1120 Indices32 reusableClusterIndicesForDescriptors(numberTreeDescriptors);
1124 memset(&nodeDescriptor_, 0,
sizeof(nodeDescriptor_));
1133 *
this =
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>(0u, nodeDescriptor_, parameters, treeDescriptors, reusableDescriptorIndicesInput.data(), reusableDescriptorIndicesOutput.data(), reusableDescriptorIndicesInput.size(), localRandomGenerator, reusableClusterIndicesForDescriptors.data(), clustersMeanFunction, worker);
1137 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1138 VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::VocabularyTree(
const unsigned int level,
const TDescriptor& nodeDescriptor,
const Parameters& parameters,
const TDescriptor* treeDescriptors,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
const size_t numberDescriptorIndices,
RandomGenerator& randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction& clustersMeanFunction,
Worker* worker) :
1140 nodeDescriptor_(nodeDescriptor)
1142 static_assert(tDistanceFunction !=
nullptr,
"Invalid distance function!");
1144 ocean_assert(parameters.
isValid());
1145 ocean_assert(reusableDescriptorIndicesInput !=
nullptr && reusableDescriptorIndicesOutput !=
nullptr);
1147 const unsigned int childLevel = level + 1u;
1153 const TDescriptors clusterCenters =
clusterDescriptors(parameters, treeDescriptors, reusableDescriptorIndicesInput, reusableDescriptorIndicesOutput, numberDescriptorIndices, randomGenerator, reusableClusterIndicesForDescriptors, clustersMeanFunction, &clusterSizes, worker);
1154 ocean_assert(clusterCenters.size() == clusterSizes.size());
1158 Index32*
const swappedReusableDescriptorIndicesInput = reusableDescriptorIndicesOutput;
1159 Index32*
const swappedReusableDescriptorIndicesOutput = reusableDescriptorIndicesInput;
1161 createChildNodes(childLevel, parameters, treeDescriptors, clusterCenters.data(), clusterSizes.data(), clusterCenters.size(), swappedReusableDescriptorIndicesInput, swappedReusableDescriptorIndicesOutput, numberDescriptorIndices, randomGenerator, reusableClusterIndicesForDescriptors, clustersMeanFunction, worker);
1164 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1167 nodeDescriptor_(nodeDescriptor)
1169 static_assert(tDistanceFunction !=
nullptr,
"Invalid distance function!");
1172 ocean_assert(numberDescriptorsIndices != 0);
1177 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1186 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1187 void VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::createChildNodes(
const unsigned int childNodeLevel,
const Parameters& parameters,
const TDescriptor* treeDescriptors,
const TDescriptor* clusterCenters,
const unsigned int* clusterSizes,
const size_t numberClusters,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
size_t numberDescriptorsIndices,
RandomGenerator& randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction& clustersMeanFunction,
Worker* worker)
1189 ocean_assert(clusterCenters !=
nullptr && clusterSizes !=
nullptr);
1190 ocean_assert(numberClusters >= 1);
1191 ocean_assert(reusableDescriptorIndicesInput !=
nullptr && reusableDescriptorIndicesOutput !=
nullptr);
1193 ocean_assert(childNodes_.empty());
1194 childNodes_.resize(numberClusters,
nullptr);
1198 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::createChildNodesSubset, childNodeLevel, ¶meters, treeDescriptors, clusterCenters, clusterSizes, numberClusters, reusableDescriptorIndicesInput, reusableDescriptorIndicesOutput, numberDescriptorsIndices, &randomGenerator, reusableClusterIndicesForDescriptors, &clustersMeanFunction, 0u, 0u), 0u, (
unsigned int)(numberClusters));
1202 createChildNodesSubset(childNodeLevel, ¶meters, treeDescriptors, clusterCenters, clusterSizes, numberClusters, reusableDescriptorIndicesInput, reusableDescriptorIndicesOutput, numberDescriptorsIndices, &randomGenerator, reusableClusterIndicesForDescriptors, &clustersMeanFunction, 0u, (
unsigned int)(numberClusters));
1206 for (
Node* childNode : childNodes_)
1208 ocean_assert(childNode !=
nullptr);
1213 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1216 const Node* bestChildNode;
1217 TDistance bestDistance;
1219 const Node* node =
this;
1223 ocean_assert(node !=
nullptr);
1225 bestChildNode =
nullptr;
1230 ocean_assert(childNode !=
nullptr);
1232 const TDistance distance = tDistanceFunction(descriptor, childNode->
nodeDescriptor_);
1234 if (distance < bestDistance)
1236 bestDistance = distance;
1237 bestChildNode = childNode;
1241 if (bestChildNode ==
nullptr)
1246 node = bestChildNode;
1250 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1253 ocean_assert(leafs.empty());
1255 TDistance bestDistance;
1258 bestNodes.reserve(16);
1263 nodes.emplace_back(
this);
1265 while (!nodes.empty())
1267 const Node* node = nodes.back();
1270 ocean_assert(node !=
nullptr);
1277 ocean_assert(childNode !=
nullptr);
1279 const TDistance distance = tDistanceFunction(descriptor, childNode->
nodeDescriptor_);
1281 if (distance < bestDistance)
1283 if (distance + distanceEpsilon < bestDistance)
1289 bestDistance = distance;
1290 bestNodes.emplace_back(childNode);
1292 else if (distance + distanceEpsilon <= bestDistance)
1294 bestNodes.emplace_back(childNode);
1298 if (bestNodes.empty())
1306 if (bestNodes.size() == 1)
1308 nodes.emplace_back(bestNodes.front());
1312 nodes.insert(nodes.cend(), bestNodes.cbegin(), bestNodes.cend());
1318 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1319 template <VocabularyStructure::MatchingMode tMatchingMode>
1322 ocean_assert(candidateDescriptors !=
nullptr);
1324 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
1327 if constexpr (tMatchingMode == MM_FIRST_BEST_LEAF)
1329 const Indices32& candidateIndices = determineBestLeaf(queryDescriptor);
1331 for (
const Index32& candidateIndex : candidateIndices)
1333 const TDistance candidateDistance = tDistanceFunction(candidateDescriptors[candidateIndex], queryDescriptor);
1335 if (candidateDistance < bestDistance)
1337 bestDistance = candidateDistance;
1338 bestCandidateDescriptorIndex = candidateIndex;
1344 ocean_assert(tMatchingMode == MM_ALL_BEST_LEAFS || tMatchingMode == MM_ALL_GOOD_LEAFS_1 || tMatchingMode == MM_ALL_GOOD_LEAFS_2);
1346 TDistance distanceEpsilon = TDistance(0);
1348 if constexpr (tMatchingMode == MM_ALL_GOOD_LEAFS_1)
1350 if (std::is_floating_point<TDistance>::value)
1352 distanceEpsilon = TDistance(0.25);
1356 distanceEpsilon = TDistance((
sizeof(TDescriptor) * 8 * 1 + 50) / 100);
1359 else if constexpr (tMatchingMode == MM_ALL_GOOD_LEAFS_2)
1361 if (std::is_floating_point<TDistance>::value)
1363 distanceEpsilon = TDistance(0.5);
1367 distanceEpsilon = TDistance((
sizeof(TDescriptor) * 8 * 2 + 50) / 100);
1373 determineBestLeafs(queryDescriptor, reusableData.
internalData_, distanceEpsilon);
1377 for (
const Index32& candidateIndex : *candidateLeaf)
1379 const TDistance candidateDistance = tDistanceFunction(candidateDescriptors[candidateIndex], queryDescriptor);
1381 if (candidateDistance < bestDistance)
1383 bestDistance = candidateDistance;
1384 bestCandidateDescriptorIndex = candidateIndex;
1390 if (distance !=
nullptr)
1392 *distance = bestDistance;
1395 return bestCandidateDescriptorIndex;
1398 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1399 template <VocabularyStructure::MatchingMode tMatchingMode>
1402 ocean_assert(candidateDescriptors !=
nullptr);
1403 ocean_assert(queryMultyDescriptor !=
nullptr && numberQuerySingleDescriptors >= 1);
1405 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
1408 for (
size_t nQuerySingle = 0; nQuerySingle < numberQuerySingleDescriptors; ++nQuerySingle)
1410 TDistance candidateDistance;
1411 const Index32 candidateIndex = matchDescriptor<tMatchingMode>(candidateDescriptors, queryMultyDescriptor[nQuerySingle], &candidateDistance, reusableData);
1413 if (candidateDistance < bestDistance)
1415 bestDistance = candidateDistance;
1416 bestCandidateDescriptorIndex = candidateIndex;
1420 if (distance !=
nullptr)
1422 *distance = bestDistance;
1425 return bestCandidateDescriptorIndex;
1428 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1429 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
1432 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
1434 ocean_assert(candidateDescriptors !=
nullptr);
1436 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
1439 size_t nQueryIndex = 0;
1441 while (
const TDescriptor* queryDescriptor = tMultiDescriptorFunction(queryMultiDescriptor, nQueryIndex++))
1443 ocean_assert(queryDescriptor !=
nullptr);
1445 TDistance candidateDistance;
1446 const Index32 candidateIndex = matchDescriptor<tMatchingMode>(candidateDescriptors, *queryDescriptor, &candidateDistance, reusableData);
1448 if (candidateDistance < bestDistance)
1450 bestDistance = candidateDistance;
1451 bestCandidateDescriptorIndex = candidateIndex;
1455 if (distance !=
nullptr)
1457 *distance = bestDistance;
1460 return bestCandidateDescriptorIndex;
1463 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1464 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
1467 static_assert(tMultiDescriptorGroupFunction !=
nullptr,
"Invalid function!");
1468 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
1470 ocean_assert(candidateDescriptors !=
nullptr);
1472 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
1475 size_t nQueryIndex = 0;
1477 while (
const TMultiDescriptor* queryMultiDescriptor = tMultiDescriptorGroupFunction(queryMultiDescriptorGroup, nQueryIndex++))
1479 ocean_assert(queryMultiDescriptor !=
nullptr);
1481 TDistance candidateDistance;
1482 const Index32 candidateIndex = matchMultiDescriptor<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, *queryMultiDescriptor, &candidateDistance, reusableData);
1484 if (candidateDistance < bestDistance)
1486 bestDistance = candidateDistance;
1487 bestCandidateDescriptorIndex = candidateIndex;
1491 if (distance !=
nullptr)
1493 *distance = bestDistance;
1496 return bestCandidateDescriptorIndex;
1499 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1500 template <VocabularyStructure::MatchingMode tMatchingMode>
1505 ocean_assert(candidateDescriptors !=
nullptr);
1506 if (numberQueryDescriptors == 0)
1511 ocean_assert(queryDescriptors !=
nullptr);
1513 if (worker && numberQueryDescriptors >= 50)
1516 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::matchDescriptorsSubset<tMatchingMode>, candidateDescriptors, queryDescriptors, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryDescriptors), 5u, 6u, 50u);
1520 matchDescriptorsSubset<tMatchingMode>(candidateDescriptors, queryDescriptors, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryDescriptors));
1524 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1525 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
1528 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
1532 ocean_assert(candidateDescriptors !=
nullptr);
1533 if (numberQueryMultiDescriptors == 0)
1538 ocean_assert(queryMultiDescriptors !=
nullptr);
1540 if (worker && numberQueryMultiDescriptors >= 50)
1543 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::matchMultiDescriptorsSubset<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>, candidateDescriptors, queryMultiDescriptors, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryMultiDescriptors), 5u, 6u, 50u);
1547 matchMultiDescriptorsSubset<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptors, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryMultiDescriptors));
1551 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1552 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
1555 static_assert(tMultiDescriptorGroupFunction !=
nullptr,
"Invalid function!");
1556 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
1560 ocean_assert(candidateDescriptors !=
nullptr);
1561 if (numberQueryMultiDescriptorGroups == 0)
1566 ocean_assert(queryMultiDescriptorGroups !=
nullptr);
1568 if (worker && numberQueryMultiDescriptorGroups >= 50)
1571 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::matchMultiDescriptorGroupsSubset<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>, candidateDescriptors, queryMultiDescriptorGroups, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryMultiDescriptorGroups), 5u, 6u, 50u);
1575 matchMultiDescriptorGroupsSubset<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptorGroups, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryMultiDescriptorGroups));
1579 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1582 return nodeDescriptor_;
1585 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1588 return descriptorIndices_;
1591 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1597 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1598 typename VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::TDescriptors VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::clusterDescriptors(
const Parameters& parameters,
const TDescriptor* treeDescriptors,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
size_t numberDescriptorsIndices,
RandomGenerator& randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction& clustersMeanFunction,
Indices32* clusterSizes,
Worker* worker)
1600 ocean_assert(parameters.
isValid());
1602 ocean_assert(reusableDescriptorIndicesInput !=
nullptr && reusableDescriptorIndicesOutput !=
nullptr);
1604 TDescriptors clusterCenters = initialClusters(parameters, treeDescriptors, reusableDescriptorIndicesInput, reusableDescriptorIndicesOutput, numberDescriptorsIndices, randomGenerator);
1605 const unsigned int numberClusters = (
unsigned int)(clusterCenters.size());
1613 if (!internalClusterSizes.empty())
1615 clusterCenters = clustersMeanFunction(numberClusters, treeDescriptors, reusableDescriptorIndicesInput, reusableClusterIndicesForDescriptors, numberDescriptorsIndices, worker);
1619 internalClusterSizes = assignDescriptorsToClusters(clusterCenters.data(), numberClusters, treeDescriptors, reusableDescriptorIndicesInput, reusableClusterIndicesForDescriptors, numberDescriptorsIndices, &sumDistances, worker);
1622 if (sumDistances >= previousSumDistances)
1628 previousSumDistances = sumDistances;
1631 ocean_assert(clusterCenters.size() >= 1);
1632 ocean_assert(internalClusterSizes.size() == clusterCenters.size());
1636 bool atLeastOneClusterEmpty = internalClusterSizes.front() == 0u;
1638 std::vector<Index32*> newDescriptorIndicesPerCluster;
1639 newDescriptorIndicesPerCluster.reserve(numberClusters);
1641 newDescriptorIndicesPerCluster.emplace_back(reusableDescriptorIndicesOutput);
1642 for (
unsigned int nCluster = 1u; nCluster < numberClusters; ++nCluster)
1644 newDescriptorIndicesPerCluster.emplace_back(newDescriptorIndicesPerCluster.back() + internalClusterSizes[nCluster - 1u]);
1646 if (internalClusterSizes[nCluster] == 0u)
1648 atLeastOneClusterEmpty =
true;
1652 for (
size_t nDescriptor = 0; nDescriptor < numberDescriptorsIndices; ++nDescriptor)
1654 const Index32& descriptorIndex = reusableDescriptorIndicesInput[nDescriptor];
1656 const Index32& clusterIndex = reusableClusterIndicesForDescriptors[descriptorIndex];
1658 *newDescriptorIndicesPerCluster[clusterIndex]++ = descriptorIndex;
1662 const Index32* debugNewDescriptorIndicesPerCluster = reusableDescriptorIndicesOutput;
1663 for (
unsigned int nCluster = 0u; nCluster < numberClusters; ++nCluster)
1665 debugNewDescriptorIndicesPerCluster += internalClusterSizes[nCluster];
1666 ocean_assert(newDescriptorIndicesPerCluster[nCluster] == debugNewDescriptorIndicesPerCluster);
1670 if (atLeastOneClusterEmpty)
1675 newClusterCenters.reserve(clusterCenters.size());
1678 newInternalClusterSizes.reserve(clusterCenters.size());
1680 for (
size_t n = 0; n < clusterCenters.size(); ++n)
1682 if (internalClusterSizes[n] != 0u)
1684 newClusterCenters.emplace_back(clusterCenters[n]);
1685 newInternalClusterSizes.emplace_back(internalClusterSizes[n]);
1689 clusterCenters = std::move(newClusterCenters);
1690 internalClusterSizes = std::move(newInternalClusterSizes);
1693 ocean_assert(internalClusterSizes.size() == clusterCenters.size());
1695 if (clusterSizes !=
nullptr)
1697 *clusterSizes = std::move(internalClusterSizes);
1700 return clusterCenters;
1703 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1706 ocean_assert(parameters.
isValid());
1708 ocean_assert(reusableDescriptorIndicesInput !=
nullptr);
1712 case IS_LARGEST_DISTANCE:
1713 return initialClustersLargestDistance(parameters, treeDescriptors, reusableDescriptorIndicesInput, reusableDescriptorIndicesOutput, numberDescriptorsIndices, randomGenerator);
1717 return initialClustersPureRandom(parameters, treeDescriptors, reusableDescriptorIndicesInput, numberDescriptorsIndices, randomGenerator);
1721 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1724 ocean_assert(parameters.
isValid());
1726 ocean_assert(treeDescriptors !=
nullptr && descriptorIndices !=
nullptr && reusableIndices !=
nullptr);
1727 ocean_assert(numberDescriptorsIndices >= 1);
1736 clusterCenters.reserve(maximalClusters);
1738 clusterCenters.emplace_back(treeDescriptors[descriptorIndices[
RandomI::random(randomGenerator, (
unsigned int)(numberDescriptorsIndices) - 1u)]]);
1740 for (
unsigned int nCluster = 1u; nCluster < maximalClusters; ++nCluster)
1743 unsigned int numberSameDistances = 0u;
1747 for (
size_t nDescriptor = 0; nDescriptor < numberDescriptorsIndices; ++nDescriptor)
1749 const Index32& descriptorIndex = descriptorIndices[nDescriptor];
1751 const TDescriptor& descriptor = treeDescriptors[descriptorIndex];
1755 for (
const TDescriptor& clusterCenter : clusterCenters)
1757 const TDistance distance = tDistanceFunction(descriptor, clusterCenter);
1759 if (distance < localBestDistance)
1761 localBestDistance = distance;
1765 if (localBestDistance > worstDistance)
1767 worstDistance = localBestDistance;
1769 reusableIndices[0u] = descriptorIndex;
1770 numberSameDistances = 1u;
1772 else if (localBestDistance == worstDistance)
1774 reusableIndices[numberSameDistances++] = descriptorIndex;
1778 if (worstDistance == TDistance(0))
1783 if (numberSameDistances == 0u)
1788 const unsigned int randomIndex =
RandomI::random(randomGenerator, numberSameDistances - 1u);
1790 const Index32& randomDescriptorIndex = reusableIndices[randomIndex];
1792 clusterCenters.emplace_back(treeDescriptors[randomDescriptorIndex]);
1795 return clusterCenters;
1798 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1801 ocean_assert(parameters.
isValid());
1803 ocean_assert(treeDescriptors !=
nullptr && descriptorIndices !=
nullptr);
1804 ocean_assert(numberDescriptorsIndices >= 1);
1811 initialCenterIndices.reserve(maximalClusters);
1813 while ((
unsigned int)(initialCenterIndices.size()) < maximalClusters)
1815 initialCenterIndices.emplace(
RandomI::random(randomGenerator, (
unsigned int)(numberDescriptorsIndices) - 1u));
1819 clusterCenters.reserve(maximalClusters);
1821 for (
const Index32& randomIndex : initialCenterIndices)
1823 const Index32& descriptorIndex = descriptorIndices[randomIndex];
1825 clusterCenters.emplace_back(treeDescriptors[descriptorIndex]);
1828 return clusterCenters;
1831 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1844 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1845 template <
unsigned int tSize>
1848 static_assert(tSize >= 1u && tSize % 8u == 0u,
"Invalid descriptor size!");
1850 #ifndef OCEAN_DONT_USE_LOOKUP_TABLE_IN_VOCABULARY_TREE
1851 static const std::vector<uint8_t> lookup(generateBitSeparationLookup8());
1854 constexpr
unsigned int tBytes = tSize / 8u;
1856 ocean_assert(numberClusters >= 1u);
1857 ocean_assert(treeDescriptors !=
nullptr && descriptorIndices !=
nullptr);
1858 ocean_assert(numberDescriptorIndices >= 1u);
1859 ocean_assert(clusterIndicesForDescriptors !=
nullptr);
1861 Indices32 meanDescriptorsSum(numberClusters * tSize, 0u);
1862 Indices32 numberDescriptorsInClusters(numberClusters, 0u);
1864 for (
size_t nDescriptor = 0; nDescriptor < numberDescriptorIndices; ++nDescriptor)
1866 const Index32& descriptorIndex = descriptorIndices[nDescriptor];
1868 ocean_assert(clusterIndicesForDescriptors[descriptorIndex] < numberClusters);
1870 ++numberDescriptorsInClusters[clusterIndicesForDescriptors[descriptorIndex]];
1871 Index32* meanDescriptor = meanDescriptorsSum.data() + clusterIndicesForDescriptors[descriptorIndex] * tSize;
1873 const uint8_t*
const descriptor = (
const uint8_t*)(treeDescriptors + descriptorIndex);
1875 for (
unsigned int nByte = 0u; nByte < tBytes; ++nByte)
1877 #ifdef OCEAN_DONT_USE_LOOKUP_TABLE_IN_VOCABULARY_TREE
1878 for (
unsigned int nBit = 0u; nBit < 8u; ++nBit)
1880 if (descriptor[nByte] & (1u << nBit))
1882 (*meanDescriptor)++;
1888 const uint8_t* lookupValues = lookup.data() + descriptor[nByte] * 8;
1890 for (
unsigned int nBit = 0u; nBit < 8u; ++nBit)
1892 *meanDescriptor++ += lookupValues[nBit];
1900 for (
unsigned int nCluster = 0u; nCluster < numberClusters; ++nCluster)
1902 const unsigned int* meanDescriptorSum = meanDescriptorsSum.data() + nCluster * tSize;
1904 uint8_t* meanDescriptor = (uint8_t*)(meanDescriptors.data() + nCluster);
1906 if (numberDescriptorsInClusters[nCluster] != 0u)
1908 for (
unsigned int nByte = 0u; nByte < tBytes; ++nByte)
1912 for (
unsigned int nBit = 0u; nBit < 8u; ++nBit)
1914 const unsigned int meanBit = (*meanDescriptorSum + numberDescriptorsInClusters[nCluster] / 2u) / numberDescriptorsInClusters[nCluster];
1915 ocean_assert(meanBit == 0u || meanBit == 1u);
1917 byte =
byte | uint8_t(meanBit << nBit);
1919 ++meanDescriptorSum;
1922 meanDescriptor[nByte] = byte;
1928 memset(meanDescriptor, 0, tBytes);
1932 return meanDescriptors;
1935 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
1936 template <
unsigned int tSize>
1939 static_assert(tSize >= 1u,
"Invalid descriptor size!");
1943 ocean_assert(numberClusters >= 1u);
1944 ocean_assert(treeDescriptors !=
nullptr && descriptorIndices !=
nullptr);
1945 ocean_assert(numberDescriptorIndices >= 1u);
1946 ocean_assert(clusterIndicesForDescriptors !=
nullptr);
1948 std::vector<float> meanDescriptorsSum(numberClusters * tSize, 0.0);
1949 Indices32 numberDescriptorsInClusters(numberClusters, 0u);
1951 for (
size_t nDescriptor = 0; nDescriptor < numberDescriptorIndices; ++nDescriptor)
1953 const Index32& descriptorIndex = descriptorIndices[nDescriptor];
1955 ocean_assert(clusterIndicesForDescriptors[descriptorIndex] < numberClusters);
1957 ++numberDescriptorsInClusters[clusterIndicesForDescriptors[descriptorIndex]];
1958 float* meanDescriptor = meanDescriptorsSum.data() + clusterIndicesForDescriptors[descriptorIndex] * tSize;
1960 const float*
const descriptor = (
const float*)(treeDescriptors + descriptorIndex);
1962 for (
unsigned int nElement = 0u; nElement < tSize; ++nElement)
1964 meanDescriptor[nElement] += descriptor[nElement];
1970 for (
unsigned int nCluster = 0u; nCluster < numberClusters; ++nCluster)
1972 const float* meanDescriptorSum = meanDescriptorsSum.data() + nCluster * tSize;
1974 float* meanDescriptor = (
float*)(meanDescriptors.data() + nCluster);
1976 if (numberDescriptorsInClusters[nCluster] != 0u)
1978 const float invDescriptorsInCluster = 1.0f / float(numberDescriptorsInClusters[nCluster]);
1980 for (
unsigned int nElement = 0u; nElement < tSize; ++nElement)
1982 meanDescriptor[nElement] = meanDescriptorSum[nElement] * invDescriptorsInCluster;
1987 memset(meanDescriptor, 0,
sizeof(
float) * tSize);
1990 for (
unsigned int nElement = 0u; nElement < tSize; ++nElement)
1992 ocean_assert(meanDescriptor[nElement] == 0.0f);
1998 return meanDescriptors;
2001 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2005 Indices32 clusterSizes(numberClusters, 0u);
2007 if (worker !=
nullptr && numberDescriptorIndices * numberClusters >= 50000)
2010 worker->
executeFunction(
Worker::Function::createStatic(&
VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::assignDescriptorsToClustersSubset, clusterCenters, numberClusters, treeDescriptors, descriptorIndices, clusterIndicesForDescriptors, clusterSizes.data(), &localSumDistances, &lock, 0u, 0u), 0u, (
unsigned int)(numberDescriptorIndices));
2014 assignDescriptorsToClustersSubset(clusterCenters, numberClusters, treeDescriptors, descriptorIndices, clusterIndicesForDescriptors, clusterSizes.data(), &localSumDistances,
nullptr, 0u, (
unsigned int)(numberDescriptorIndices));
2017 if (sumDistances !=
nullptr)
2019 *sumDistances = localSumDistances;
2022 return clusterSizes;
2025 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2026 void VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::createChildNodesSubset(
const unsigned int childNodeLevel,
const Parameters* parameters,
const TDescriptor* treeDescriptors,
const TDescriptor* clusterCenters,
const unsigned int* clusterSizes,
const size_t numberClusters,
Index32* reusableDescriptorIndicesInput,
Index32* reusableDescriptorIndicesOutput,
const size_t numberDescriptorsIndices,
RandomGenerator* randomGenerator,
Index32* reusableClusterIndicesForDescriptors,
const ClustersMeanFunction* clustersMeanFunction,
const unsigned int subsetFirstCluster,
const unsigned int subsetNumberClusters)
2028 ocean_assert(childNodeLevel >= 1u);
2029 ocean_assert(parameters !=
nullptr && parameters->
isValid());
2030 ocean_assert(clusterCenters !=
nullptr && clusterSizes !=
nullptr);
2031 ocean_assert(numberClusters >= 1u && subsetNumberClusters >= 1);
2032 ocean_assert(reusableDescriptorIndicesInput !=
nullptr && reusableDescriptorIndicesOutput !=
nullptr);
2034 unsigned int descriptorClusterOffset = 0u;
2036 for (
unsigned int nCluster = 0u; nCluster < subsetFirstCluster; ++nCluster)
2038 descriptorClusterOffset += clusterSizes[nCluster];
2041 for (
unsigned int nCluster = subsetFirstCluster; nCluster < subsetFirstCluster + subsetNumberClusters; ++nCluster)
2043 ocean_assert(nCluster < childNodes_.size());
2045 const size_t subsetNumberDescriptorIndices = clusterSizes[nCluster];
2047 if (subsetNumberDescriptorIndices > 0)
2049 const TDescriptor& nodeDescriptor = clusterCenters[nCluster];
2051 ocean_assert_and_suppress_unused(descriptorClusterOffset + subsetNumberDescriptorIndices <= numberDescriptorsIndices, numberDescriptorsIndices);
2053 Index32*
const subsetReusableDescriptorIndicesInput = reusableDescriptorIndicesInput + descriptorClusterOffset;
2054 Index32*
const subsetReusableDescriptorIndicesOutput = reusableDescriptorIndicesOutput + descriptorClusterOffset;
2056 Node* childNode =
nullptr;
2058 if (numberClusters == 1 || subsetNumberDescriptorIndices <= parameters->maximalDescriptorsPerLeaf_ || childNodeLevel + 1u >= parameters->
maximalLevels_)
2060 childNode =
new Node(childNodeLevel, nodeDescriptor, subsetReusableDescriptorIndicesInput, subsetNumberDescriptorIndices);
2064 constexpr
Worker* noWorker =
nullptr;
2066 childNode =
new Node(childNodeLevel, nodeDescriptor, *parameters, treeDescriptors, subsetReusableDescriptorIndicesInput, subsetReusableDescriptorIndicesOutput, subsetNumberDescriptorIndices, *randomGenerator, reusableClusterIndicesForDescriptors, *clustersMeanFunction, noWorker);
2069 ocean_assert(childNodes_[nCluster] ==
nullptr);
2070 childNodes_[nCluster] = childNode;
2072 descriptorClusterOffset += clusterSizes[nCluster];
2077 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2078 void VocabularyTree<TDescriptor, TDistance, tDistanceFunction>::assignDescriptorsToClustersSubset(
const TDescriptor* clusterCenters,
const unsigned int numberClusters,
const TDescriptor* treeDescriptors,
const Index32* descriptorIndices,
Index32* clusterIndicesForDescriptors,
Index32* clusterSizes,
TSumDistances* sumDistances,
Lock* lock,
const unsigned int firstDescriptorIndex,
const unsigned int numberDescriptorIndices)
2080 ocean_assert(clusterCenters !=
nullptr && numberClusters >= 1u);
2081 ocean_assert(treeDescriptors !=
nullptr && descriptorIndices !=
nullptr);
2082 ocean_assert(clusterIndicesForDescriptors !=
nullptr);
2083 ocean_assert(clusterSizes !=
nullptr);
2084 ocean_assert(numberDescriptorIndices >= 1u);
2086 Indices32 localClusterSizes(numberClusters, 0u);
2089 TDistance bestDistance;
2090 unsigned int bestCluster;
2092 for (
unsigned int nDescriptor = firstDescriptorIndex; nDescriptor < firstDescriptorIndex + numberDescriptorIndices; ++nDescriptor)
2094 const Index32& descriptorIndex = descriptorIndices[nDescriptor];
2095 const TDescriptor& descriptor = treeDescriptors[descriptorIndex];
2098 bestCluster = (
unsigned int)(-1);
2100 for (
unsigned int nCluster = 0u; nCluster < numberClusters; ++nCluster)
2102 const TDistance distance = tDistanceFunction(clusterCenters[nCluster], descriptor);
2104 if (distance < bestDistance)
2106 bestDistance = distance;
2107 bestCluster = nCluster;
2111 ocean_assert(bestCluster < numberClusters);
2113 clusterIndicesForDescriptors[descriptorIndex] = bestCluster;
2115 ++localClusterSizes[bestCluster];
2117 localSumDistances += bestDistance;
2122 for (
unsigned int n = 0u; n < numberClusters; ++n)
2124 clusterSizes[n] += localClusterSizes[n];
2129 *sumDistances += localSumDistances;
2133 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2134 template <VocabularyStructure::MatchingMode tMatchingMode>
2137 ocean_assert(candidateDescriptors !=
nullptr);
2138 ocean_assert(matches !=
nullptr);
2139 ocean_assert(numberQueryDescriptors >= 1u);
2144 localMatches.reserve(numberQueryDescriptors);
2146 for (
unsigned int nQuery = firstQueryDescriptor; nQuery < firstQueryDescriptor + numberQueryDescriptors; ++nQuery)
2149 const Index32 matchingCandidateIndex = matchDescriptor<tMatchingMode>(candidateDescriptors, queryDescriptors[nQuery], &distance, reusableData);
2151 if (distance <= maximalDistance)
2153 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2155 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2161 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
2164 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2165 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2168 ocean_assert(candidateDescriptors !=
nullptr);
2169 ocean_assert(matches !=
nullptr);
2170 ocean_assert(numberQueryMultiDescriptors >= 1u);
2175 localMatches.reserve(numberQueryMultiDescriptors);
2177 for (
unsigned int nQuery = firstQueryMultiDescriptor; nQuery < firstQueryMultiDescriptor + numberQueryMultiDescriptors; ++nQuery)
2180 const Index32 matchingCandidateIndex = matchMultiDescriptor<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptors[nQuery], &distance, reusableData);
2182 if (distance <= maximalDistance)
2184 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2186 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2192 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
2195 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2196 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2199 ocean_assert(candidateDescriptors !=
nullptr);
2200 ocean_assert(matches !=
nullptr);
2201 ocean_assert(numberQueryMultiDescriptorGroups >= 1u);
2206 localMatches.reserve(numberQueryMultiDescriptorGroups);
2208 for (
unsigned int nQuery = firstQueryMultiDescriptorGroup; nQuery < firstQueryMultiDescriptorGroup + numberQueryMultiDescriptorGroups; ++nQuery)
2211 const Index32 matchingCandidateIndex = matchMultiDescriptorGroup<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptorGroups[nQuery], &distance, reusableData);
2213 if (distance <= maximalDistance)
2215 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2217 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2223 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
2226 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2229 ocean_assert(numberTrees >= 1u);
2231 for (
size_t n = 0; n < numberTrees; ++n)
2233 vocabularyTrees_.emplace_back(treeDescriptors, numberDescriptors, clustersMeanFunction, parameters, worker, randomGenerator);
2237 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2238 template <VocabularyStructure::MatchingMode tMatchingMode>
2241 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
2246 TDistance candidateDistance;
2247 const Index32 candidateDescriptorIndex = vocabularyTree.template matchDescriptor<tMatchingMode>(candidateDescriptors, queryDescriptor, &candidateDistance, reusableData);
2249 if (candidateDistance < bestDistance)
2251 bestDistance = candidateDistance;
2252 bestCandidateDescriptorIndex = candidateDescriptorIndex;
2256 if (distance !=
nullptr)
2258 *distance = bestDistance;
2261 return bestCandidateDescriptorIndex;
2264 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2265 template <VocabularyStructure::MatchingMode tMatchingMode>
2268 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
2273 TDistance candidateDistance;
2274 const Index32 candidateDescriptorIndex = vocabularyTree.template matchMultiDescriptor<tMatchingMode>(candidateDescriptors, queryMultiDescriptor, numberQuerySingleDescriptors, &candidateDistance, reusableData);
2276 if (candidateDistance < bestDistance)
2278 bestDistance = candidateDistance;
2279 bestCandidateDescriptorIndex = candidateDescriptorIndex;
2283 if (distance !=
nullptr)
2285 *distance = bestDistance;
2288 return bestCandidateDescriptorIndex;
2291 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2292 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2295 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
2297 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
2302 TDistance candidateDistance;
2303 const Index32 candidateDescriptorIndex = vocabularyTree.template matchMultiDescriptor<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptor, &candidateDistance, reusableData);
2305 if (candidateDistance < bestDistance)
2307 bestDistance = candidateDistance;
2308 bestCandidateDescriptorIndex = candidateDescriptorIndex;
2312 if (distance !=
nullptr)
2314 *distance = bestDistance;
2317 return bestCandidateDescriptorIndex;
2320 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2321 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2324 static_assert(tMultiDescriptorGroupFunction !=
nullptr,
"Invalid function!");
2325 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
2327 Index32 bestCandidateDescriptorIndex = invalidMatchIndex();
2332 TDistance candidateDistance;
2333 const Index32 candidateDescriptorIndex = vocabularyTree.template matchMultiDescriptorGroup<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptorGroup, &candidateDistance, reusableData);
2335 if (candidateDistance < bestDistance)
2337 bestDistance = candidateDistance;
2338 bestCandidateDescriptorIndex = candidateDescriptorIndex;
2342 if (distance !=
nullptr)
2344 *distance = bestDistance;
2347 return bestCandidateDescriptorIndex;
2350 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2351 template <VocabularyStructure::MatchingMode tMatchingMode>
2356 ocean_assert(candidateDescriptors !=
nullptr);
2357 if (numberQueryDescriptors == 0)
2362 ocean_assert(queryDescriptors !=
nullptr);
2364 if (worker && numberQueryDescriptors >= 50)
2367 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyForest<TDescriptor, TDistance, tDistanceFunction>::matchDescriptorsSubset<tMatchingMode>, candidateDescriptors, queryDescriptors, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryDescriptors), 5u, 6u, 50u);
2371 matchDescriptorsSubset<tMatchingMode>(candidateDescriptors, queryDescriptors, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryDescriptors));
2375 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2376 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2379 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
2383 ocean_assert(candidateDescriptors !=
nullptr);
2384 if (numberQueryMultiDescriptors == 0)
2389 ocean_assert(queryMultiDescriptors !=
nullptr);
2391 if (worker && numberQueryMultiDescriptors >= 50)
2394 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyForest<TDescriptor, TDistance, tDistanceFunction>::matchMultiDescriptorsSubset<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>, candidateDescriptors, queryMultiDescriptors, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryMultiDescriptors), 5u, 6u, 50u);
2398 matchMultiDescriptorsSubset<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptors, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryMultiDescriptors));
2402 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2403 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2406 static_assert(tMultiDescriptorGroupFunction !=
nullptr,
"Invalid function!");
2407 static_assert(tMultiDescriptorFunction !=
nullptr,
"Invalid function!");
2411 ocean_assert(candidateDescriptors !=
nullptr);
2412 if (numberQueryMultiDescriptorGroups == 0)
2417 ocean_assert(queryMultiDescriptorGroups !=
nullptr);
2419 if (worker && numberQueryMultiDescriptorGroups >= 50)
2422 worker->
executeFunction(
Worker::Function::create(*
this, &
VocabularyForest<TDescriptor, TDistance, tDistanceFunction>::matchMultiDescriptorGroupsSubset<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>, candidateDescriptors, queryMultiDescriptorGroups, maximalDistance, &matches, &lock, 0u, 0u), 0u, (
unsigned int)(numberQueryMultiDescriptorGroups), 5u, 6u, 50u);
2426 matchMultiDescriptorGroupsSubset<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptorGroups, maximalDistance, &matches,
nullptr, 0u, (
unsigned int)(numberQueryMultiDescriptorGroups));
2430 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2431 template <VocabularyStructure::MatchingMode tMatchingMode>
2434 ocean_assert(candidateDescriptors !=
nullptr);
2435 ocean_assert(matches !=
nullptr);
2436 ocean_assert(numberQueryDescriptors >= 1u);
2441 localMatches.reserve(numberQueryDescriptors);
2443 for (
unsigned int nQuery = firstQueryDescriptor; nQuery < firstQueryDescriptor + numberQueryDescriptors; ++nQuery)
2446 const Index32 matchingCandidateIndex = matchDescriptor<tMatchingMode>(candidateDescriptors, queryDescriptors[nQuery], &distance, reusableData);
2448 if (distance <= maximalDistance)
2450 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2452 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2458 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
2461 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2462 template <
typename TMultiDescriptor, const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2465 ocean_assert(candidateDescriptors !=
nullptr);
2466 ocean_assert(matches !=
nullptr);
2467 ocean_assert(numberQueryMultiDescriptors >= 1u);
2472 localMatches.reserve(numberQueryMultiDescriptors);
2474 for (
unsigned int nQuery = firstQueryMultiDescriptor; nQuery < firstQueryMultiDescriptor + numberQueryMultiDescriptors; ++nQuery)
2477 const Index32 matchingCandidateIndex = matchMultiDescriptor<TMultiDescriptor, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptors[nQuery], &distance, reusableData);
2479 if (distance <= maximalDistance)
2481 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2483 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2489 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
2492 template <
typename TDescriptor,
typename TDistance, TDistance(*tDistanceFunction)(const TDescriptor&, const TDescriptor&)>
2493 template <
typename TMultiDescriptorGroup,
typename TMultiDescriptor, const TMultiDescriptor*(*tMultiDescriptorGroupFunction)(const TMultiDescriptorGroup&, const
size_t), const TDescriptor*(*tMultiDescriptorFunction)(const TMultiDescriptor&, const
size_t), VocabularyStructure::MatchingMode tMatchingMode>
2496 ocean_assert(candidateDescriptors !=
nullptr);
2497 ocean_assert(matches !=
nullptr);
2498 ocean_assert(numberQueryMultiDescriptorGroups >= 1u);
2503 localMatches.reserve(numberQueryMultiDescriptorGroups);
2505 for (
unsigned int nQuery = firstQueryMultiDescriptorGroup; nQuery < firstQueryMultiDescriptorGroup + numberQueryMultiDescriptorGroups; ++nQuery)
2508 const Index32 matchingCandidateIndex = matchMultiDescriptorGroup<TMultiDescriptorGroup, TMultiDescriptor, tMultiDescriptorGroupFunction, tMultiDescriptorFunction, tMatchingMode>(candidateDescriptors, queryMultiDescriptorGroups[nQuery], &distance, reusableData);
2510 if (distance <= maximalDistance)
2512 ocean_assert(matchingCandidateIndex != invalidMatchIndex());
2514 localMatches.emplace_back(matchingCandidateIndex, nQuery, distance);
2520 matches->insert(matches->cend(), localMatches.cbegin(), localMatches.cend());
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition: Caller.h:2876
static Caller< void > create(CT &object, typename MemberFunctionPointerMaker< CT, void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a member function with no function parameter.
Definition: Caller.h:3023
This class implements a recursive lock object.
Definition: Lock.h:31
T TypePerformance
Definition of the data type for the next larger data type regarding performance.
Definition: DataType.h:261
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static constexpr T minValue()
Returns the min scalar value.
Definition: Numeric.h:3250
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
This class implements an optional recursive scoped lock object locking the lock object only if it's d...
Definition: Lock.h:325
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
static unsigned int random(const unsigned int maxValue)
Returns one random integer value with specified maximum value.
This class implements a Vocabulary Forest holding several Vocabulary Trees.
Definition: VocabularyTree.h:766
Index32 matchMultiDescriptor(const TDescriptor *candidateDescriptors, const TMultiDescriptor &queryMultiDescriptor, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query multi-descriptor with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2293
VocabularyForest(const size_t numberTrees, const TDescriptor *treeDescriptors, const size_t numberTreeDescriptors, const ClustersMeanFunction &clustersMeanFunction, const Parameters ¶meters=Parameters(), Worker *worker=nullptr, RandomGenerator *randomGenerator=nullptr)
Creates a new forest with several trees for given descriptors.
Definition: VocabularyTree.h:2227
typename TVocabularyTree::ReusableData ReusableData
Re-definition of the ReusableData object.
Definition: VocabularyTree.h:834
const TDescriptor *(*)(const TMultiDescriptor &, const size_t) MultiDescriptorFunction
Definition of a function pointer to a function allowing to return individual descriptors from a multi...
Definition: VocabularyTree.h:821
std::vector< TVocabularyTree > TVocabularyTrees
Definition of a vector holding VocabularyTree objects.
Definition: VocabularyTree.h:841
TDescriptors(*)(const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, const Index32 *clusterIndicesForDescriptors, const size_t numberDescriptorIndices, Worker *worker) ClustersMeanFunction
Definition of a function pointer allowing to determine the mean descriptors for individual clusters.
Definition: VocabularyTree.h:813
TVocabularyTrees vocabularyTrees_
The trees of this forest.
Definition: VocabularyTree.h:1022
TDistance Distance
The distance data type of this forest.
Definition: VocabularyTree.h:777
Index32 matchMultiDescriptorGroup(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup &queryMultiDescriptorGroup, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query group of multi-descriptors with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2322
static constexpr TDistance(* distanceFunction)(const TDescriptor &, const TDescriptor &)
The pointer to the function determining the distance between two descriptors of this forest.
Definition: VocabularyTree.h:782
Index32 matchDescriptor(const TDescriptor *candidateDescriptors, const TDescriptor &queryDescriptor, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query descriptor with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2239
VocabularyForest()=default
Creates a new empty forest without trees.
void matchMultiDescriptorGroupsSubset(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup *queryMultiDescriptorGroups, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryMultiDescriptorGroup, const unsigned int numberQueryMultiDescriptorGroups) const
Matches a subset of several query groups of multi-descriptors with all candidate descriptors in this ...
Definition: VocabularyTree.h:2494
std::vector< TDistance > TDistances
Definition of a vector holding distances.
Definition: VocabularyTree.h:792
Match< TDistance > Match
Definition of a Match object using the distance data type of this tree.
Definition: VocabularyTree.h:802
void matchDescriptorsSubset(const TDescriptor *candidateDescriptors, const TDescriptor *queryDescriptors, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryDescriptor, const unsigned int numberQueryDescriptors) const
Matches a subset of several query descriptors with all forest candidate descriptors.
Definition: VocabularyTree.h:2432
Index32 matchMultiDescriptor(const TDescriptor *candidateDescriptors, const TDescriptor *queryMultiDescriptor, const size_t numberQuerySingleDescriptors, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query multi-descriptor with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2266
void matchMultiDescriptorGroups(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup *queryMultiDescriptorGroups, const size_t numberQueryMultiDescriptorGroups, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query groups of multi-descriptors with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2404
const TMultiDescriptor *(*)(const TMultiDescriptorGroup &, const size_t) MultiDescriptorGroupFunction
Definition of a function pointer to a function allowing to return individual multi-descriptors from a...
Definition: VocabularyTree.h:829
VocabularyTree< TDescriptor, TDistance, tDistanceFunction > TVocabularyTree
Definition of the Vocabulary Tree object.
Definition: VocabularyTree.h:797
void matchDescriptors(const TDescriptor *candidateDescriptors, const TDescriptor *queryDescriptors, const size_t numberQueryDescriptors, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query descriptors with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2352
std::vector< TDescriptor > TDescriptors
Definition of a vector holding descriptors.
Definition: VocabularyTree.h:787
TDescriptor Descriptor
The descriptor type of this forest.
Definition: VocabularyTree.h:772
void matchMultiDescriptors(const TDescriptor *candidateDescriptors, const TMultiDescriptor *queryMultiDescriptors, const size_t numberQueryMultiDescriptors, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query multi-descriptors with all candidate descriptors in this forest.
Definition: VocabularyTree.h:2377
void matchMultiDescriptorsSubset(const TDescriptor *candidateDescriptors, const TMultiDescriptor *queryMultiDescriptors, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryMultiDescriptor, const unsigned int numberQueryMultiDescriptors) const
Matches a subset of several query multi-descriptors with all forest candidate descriptors.
Definition: VocabularyTree.h:2463
This class implements a simple container holding the index pairs of matching descriptors and their di...
Definition: VocabularyTree.h:87
Index32 candidateDescriptorIndex_
The index of the candidate descriptor, with range [0, infinity).
Definition: VocabularyTree.h:130
Match()=default
Default constructor for an invalid match.
Index32 queryDescriptorIndex() const
Returns the index of the query descriptor.
Definition: VocabularyTree.h:1046
Index32 candidateDescriptorIndex() const
Returns the index of the candidate descriptor.
Definition: VocabularyTree.h:1040
Index32 queryDescriptorIndex_
The index of the query descriptor, with range [0, infinity).
Definition: VocabularyTree.h:133
bool isValid() const
Returns whether this match is valid.
Definition: VocabularyTree.h:1058
TDistance distance() const
Returns the distance between both descriptors.
Definition: VocabularyTree.h:1052
TDistance distance_
The distance between both descriptors, with range [0, infinity].
Definition: VocabularyTree.h:136
This class stores construction parameters for a VocabularyStructure.
Definition: VocabularyTree.h:150
unsigned int maximalDescriptorsPerLeaf_
The maximal number of descriptors each leaf can have, with range [1, infinity).
Definition: VocabularyTree.h:179
InitializationStrategy initializationStrategy_
The initialization strategy for initial clusters.
Definition: VocabularyTree.h:185
unsigned int maximalLevels_
The maximal number of tree levels, at tree will never have more level regardless what has been specif...
Definition: VocabularyTree.h:182
unsigned int maximalNumberClustersPerLevel_
The maximal number of clusters each tree level can have with range [2, infinity).
Definition: VocabularyTree.h:176
Parameters()=default
Default constructor.
bool isValid() const
Returns whether this object holds valid parameters.
Definition: VocabularyTree.h:1072
This class implements the base class for all Vocabulary objects.
Definition: VocabularyTree.h:42
InitializationStrategy
Definition of individual strategies to initialize the clustering of each tree node.
Definition: VocabularyTree.h:55
@ IS_INVALID
An invalid strategy.
Definition: VocabularyTree.h:57
@ IS_PURE_RANDOM
All initial clusters are chosen randomly.
Definition: VocabularyTree.h:59
@ IS_LARGEST_DISTANCE
The initial first cluster is chosen randomly, the remaining clusters are chosen with largest distance...
Definition: VocabularyTree.h:61
virtual ~VocabularyStructure()=default
Destructs this object.
std::vector< Match< TDistance > > Matches
Definition of a vector holding matches.
Definition: VocabularyTree.h:144
VocabularyStructure()=default
Default constructor.
MatchingMode
Definition of individual matching modes for descriptors.
Definition: VocabularyTree.h:68
@ MM_ALL_GOOD_LEAFS_1
All descriptors from all tree leafs are considered for matching which are within a 1% distance to the...
Definition: VocabularyTree.h:76
@ MM_ALL_GOOD_LEAFS_2
All descriptors from all tree leafs are considered for matching which are within a 2% distance to the...
Definition: VocabularyTree.h:78
@ MM_INVALID
An invalid matching mode.
Definition: VocabularyTree.h:70
@ MM_FIRST_BEST_LEAF
Only descriptor from the first best tree leaf are considered for matching (the second+ leaf with iden...
Definition: VocabularyTree.h:72
@ MM_ALL_BEST_LEAFS
All descriptors from all best tree leafs are considered for matching (all leafs with identical best d...
Definition: VocabularyTree.h:74
static constexpr Index32 invalidMatchIndex()
Returns an invalid matching index.
Definition: VocabularyTree.h:1025
static std::vector< uint8_t > generateBitSeparationLookup8()
Returns the lookup table which separates the bits of a byte into 8 individual bytes.
Definition: VocabularyTree.h:1077
Definition of a class which holds reusable data for internal use.
Definition: VocabularyTree.h:317
ReusableData()=default
Creates a new object.
std::vector< const Indices32 * > internalData_
The internal reusable data.
Definition: VocabularyTree.h:330
This class implements a Vocabulary Tree for feature descriptors.
Definition: VocabularyTree.h:223
void matchDescriptorsSubset(const TDescriptor *candidateDescriptors, const TDescriptor *queryDescriptors, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryDescriptor, const unsigned int numberQueryDescriptors) const
Matches a subset of several query descriptors with all tree candidate descriptors.
Definition: VocabularyTree.h:2135
const TDescriptor & nodeDescriptor() const
Returns the descriptor representing this tree/node.
Definition: VocabularyTree.h:1580
TDescriptors(*)(const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, const Index32 *clusterIndicesForDescriptors, const size_t numberDescriptorIndices, Worker *worker) ClustersMeanFunction
Definition of a function pointer allowing to determine the mean descriptors for individual clusters.
Definition: VocabularyTree.h:285
VocabularyTree & operator=(VocabularyTree &&vocabularyTree)
Move operator.
Definition: VocabularyTree.h:1832
void matchMultiDescriptorGroups(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup *queryMultiDescriptorGroups, const size_t numberQueryMultiDescriptorGroups, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query groups of multi-descriptors with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1553
VocabularyTree()=default
Creates an empty vocabulary tree.
Match< TDistance > Match
Definition of a Match object using the distance data type of this tree.
Definition: VocabularyTree.h:274
Indices32 descriptorIndices_
The indices of the descriptors which are part of this node.
Definition: VocabularyTree.h:749
TDistance Distance
The distance data type of this tree.
Definition: VocabularyTree.h:234
static TDescriptors determineClustersMeanForBinaryDescriptor(const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, const Index32 *clusterIndicesForDescriptors, const size_t numberDescriptorIndices, Worker *worker)
Determines a binary mean descriptor for each cluster.
Definition: VocabularyTree.h:1846
const Indices32 & determineBestLeaf(const TDescriptor &descriptor) const
Determines the leaf best matching with a given descriptor.
Definition: VocabularyTree.h:1214
const TMultiDescriptor *(*)(const TMultiDescriptorGroup &, const size_t) MultiDescriptorGroupFunction
Definition of a function pointer to a function allowing to return individual multi-descriptors from a...
Definition: VocabularyTree.h:301
VocabularyTree(const VocabularyTree &vocabularyTree)=delete
Disabled copy constructor.
void matchMultiDescriptorGroupsSubset(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup *queryMultiDescriptorGroups, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryMultiDescriptorGroup, const unsigned int numberQueryMultiDescriptorGroups) const
Matches a subset of several query groups of multi-descriptors with all candidate descriptors in this ...
Definition: VocabularyTree.h:2197
Nodes childNodes_
The child-nodes of this node.
Definition: VocabularyTree.h:752
~VocabularyTree()
Destructs the vocabulary tree.
Definition: VocabularyTree.h:1178
TDescriptors initialClustersPureRandom(const Parameters ¶meters, const TDescriptor *treeDescriptors, Index32 *descriptorIndices, const size_t numberDescriptorsIndices, RandomGenerator &randomGenerator) const
Determines the initial cluster based on a pure random choice.
Definition: VocabularyTree.h:1799
TDescriptor Descriptor
The descriptor type of this tree.
Definition: VocabularyTree.h:229
NextLargerTyper< TDistance >::TypePerformance TSumDistances
The data type of the sum of distances, uint64_t for uint32_t, and float for float.
Definition: VocabularyTree.h:239
void matchMultiDescriptorsSubset(const TDescriptor *candidateDescriptors, const TMultiDescriptor *queryMultiDescriptors, const TDistance maximalDistance, Matches *matches, Lock *lock, const unsigned int firstQueryMultiDescriptor, const unsigned int numberQueryMultiDescriptors) const
Matches a subset of several query multi-descriptors with all tree candidate descriptors.
Definition: VocabularyTree.h:2166
const Nodes & childNodes() const
Returns all child nodes of this node/tree.
Definition: VocabularyTree.h:1592
static constexpr TDistance(* distanceFunction)(const TDescriptor &, const TDescriptor &)
The pointer to the function determining the distance between two descriptors of this tree.
Definition: VocabularyTree.h:244
std::vector< TDistance > TDistances
Definition of a vector holding distances.
Definition: VocabularyTree.h:254
TDescriptor nodeDescriptor_
The node's descriptor.
Definition: VocabularyTree.h:746
VocabularyTree & operator=(const VocabularyTree &vocabularyTree)=delete
Disabled assign operator.
void determineBestLeafs(const TDescriptor &descriptor, std::vector< const Indices32 * > &leafs, const TDistance distanceEpsilon=TDistance(0)) const
Determines the leafs best matching with a given descriptor.
Definition: VocabularyTree.h:1251
VocabularyTree< TDescriptor, TDistance, tDistanceFunction > Node
Definition of a tree node which is just an alias for the tree (the root node).
Definition: VocabularyTree.h:259
Index32 matchMultiDescriptorGroup(const TDescriptor *candidateDescriptors, const TMultiDescriptorGroup &queryMultiDescriptorGroup, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query group of multi-descriptors with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1465
const Indices32 & descriptorIndices() const
Returns all indices of descriptors which belong to this tree/node.
Definition: VocabularyTree.h:1586
void createChildNodesSubset(const unsigned int childNodeLevel, const Parameters *parameters, const TDescriptor *treeDescriptors, const TDescriptor *clusterCenters, const unsigned int *clusterSizes, const size_t numberClusters, Index32 *reusableDescriptorIndicesInput, Index32 *reusableDescriptorIndicesOutput, const size_t numberDescriptorsIndices, RandomGenerator *randomGenerator, Index32 *reusableClusterIndicesForDescriptors, const ClustersMeanFunction *clustersMeanFunction, const unsigned int subsetFirstCluster, const unsigned int subsetNumberClusters)
Creates a subset of the new child nodes.
Definition: VocabularyTree.h:2026
Index32 matchDescriptor(const TDescriptor *candidateDescriptors, const TDescriptor &queryDescriptor, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query descriptor with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1320
void createChildNodes(const unsigned int childNodeLevel, const Parameters ¶meters, const TDescriptor *treeDescriptors, const TDescriptor *clusterCenters, const unsigned int *clusterSizes, const size_t numberClusters, Index32 *reusableDescriptorIndicesInput, Index32 *reusableDescriptorIndicesOutput, const size_t numberDescriptorsIndices, RandomGenerator &randomGenerator, Index32 *reusableClusterIndicesForDescriptors, const ClustersMeanFunction &clustersMeanFunction, Worker *worker)
Creates the new child nodes.
Definition: VocabularyTree.h:1187
const TDescriptor *(*)(const TMultiDescriptor &, const size_t) MultiDescriptorFunction
Definition of a function pointer to a function allowing to return individual descriptors from a multi...
Definition: VocabularyTree.h:293
TDescriptors initialClustersLargestDistance(const Parameters ¶meters, const TDescriptor *treeDescriptors, Index32 *descriptorIndices, Index32 *reusableIndices, const size_t numberDescriptorsIndices, RandomGenerator &randomGenerator) const
Determines the initial clusters based on the largest distance between each other.
Definition: VocabularyTree.h:1722
void matchMultiDescriptors(const TDescriptor *candidateDescriptors, const TMultiDescriptor *queryMultiDescriptors, const size_t numberQueryMultiDescriptors, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query multi-descriptors with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1526
static void assignDescriptorsToClustersSubset(const TDescriptor *clusterCenters, const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, Index32 *clusterIndicesForDescriptors, Index32 *clusterSizes, TSumDistances *sumDistances, Lock *lock, const unsigned int firstDescriptorIndex, const unsigned int numberDescriptorIndices)
Assigns a subset of descriptors to clusters.
Definition: VocabularyTree.h:2078
unsigned int level_
The node's level.
Definition: VocabularyTree.h:743
static Indices32 assignDescriptorsToClusters(const TDescriptor *clusterCenters, const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, Index32 *clusterIndicesForDescriptors, const size_t numberDescriptorIndices, TSumDistances *sumDistances=nullptr, Worker *worker=nullptr)
Assigns descriptors to clusters.
Definition: VocabularyTree.h:2002
std::vector< Node * > Nodes
Definition of a vector holding tree nodes.
Definition: VocabularyTree.h:264
TDescriptors initialClusters(const Parameters ¶meters, const TDescriptor *treeDescriptors, Index32 *reusableDescriptorIndicesInput, Index32 *reusableDescriptorIndicesOutput, size_t numberDescriptorsIndices, RandomGenerator &randomGenerator)
Determines the initial clusters based on specified initialization strategy.
Definition: VocabularyTree.h:1704
std::vector< const Node * > ConstNodes
Definition of a vector holding constant tree nodes.
Definition: VocabularyTree.h:269
void matchDescriptors(const TDescriptor *candidateDescriptors, const TDescriptor *queryDescriptors, const size_t numberQueryDescriptors, const TDistance maximalDistance, Matches &matches, Worker *worker=nullptr) const
Matches several query descriptors with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1501
static TDescriptors determineClustersMeanForFloatDescriptor(const unsigned int numberClusters, const TDescriptor *treeDescriptors, const Index32 *descriptorIndices, const Index32 *clusterIndicesForDescriptors, const size_t numberDescriptorIndices, Worker *worker)
Determines a float mean descriptor for each cluster.
Definition: VocabularyTree.h:1937
Index32 matchMultiDescriptor(const TDescriptor *candidateDescriptors, const TDescriptor *queryMultiDescriptor, const size_t numberQuerySingleDescriptors, TDistance *distance=nullptr, const ReusableData &reusableData=ReusableData()) const
Matches a query multi-descriptor with all candidate descriptors in this tree.
Definition: VocabularyTree.h:1400
TDescriptors clusterDescriptors(const Parameters ¶meters, const TDescriptor *treeDescriptors, Index32 *reusableDescriptorIndicesInput, Index32 *reusableDescriptorIndicesOutput, size_t numberDescriptorsIndices, RandomGenerator &randomGenerator, Index32 *clusterIndicesForDescriptors, const ClustersMeanFunction &clustersMeanFunction, Indices32 *clusterSizes=nullptr, Worker *worker=nullptr)
Distributes several descriptors into individual clusters.
Definition: VocabularyTree.h:1598
std::vector< TDescriptor > TDescriptors
Definition of a vector holding descriptors.
Definition: VocabularyTree.h:249
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition: Base.h:96
std::unordered_set< Index32 > UnorderedIndexSet32
Definition of an unordered_set holding 32 bit indices.
Definition: Base.h:126
uint32_t Index32
Definition of a 32 bit index value.
Definition: Base.h:84
std::shared_ptr< VocabularyStructure > SharedVocabularyStructure
Definition of a shared pointer holding a VocabularyStructure object.
Definition: VocabularyTree.h:35
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15