9 #include <aliceVision/config.hpp>
10 #include "distance.hpp"
11 #include "DefaultAllocator.hpp"
13 #include <aliceVision/feature/imageDescriberCommon.hpp>
14 #include <aliceVision/feature/regionsFactory.hpp>
16 #include <aliceVision/types.hpp>
17 #include <aliceVision/system/Logger.hpp>
35 typedef std::vector<Word> Document;
36 typedef std::map<Word, std::vector<IndexT>> SparseHistogram;
37 typedef std::map<DocId, SparseHistogram> SparseHistogramPerImage;
39 std::ostream& operator<<(std::ostream& os,
const Document& doc);
48 inline void computeSparseHistogram(
const std::vector<Word>& document, SparseHistogram& v)
51 for (std::size_t i = 0; i < document.size(); ++i)
56 Word word = document[i];
67 virtual void save(
const std::string& file)
const = 0;
69 virtual void load(
const std::string& file) = 0;
76 virtual SparseHistogram
quantizeToSparse(
const void* blindDescriptors)
const = 0;
79 virtual uint32_t
levels()
const = 0;
81 virtual uint32_t
splits()
const = 0;
83 virtual uint32_t
words()
const = 0;
86 virtual void clear() = 0;
89 inline IVocabularyTree::~IVocabularyTree() {}
101 template<
class Feature,
template<
typename,
typename>
class Distance = L2>
114 template<
class DescriptorT>
115 Word
quantize(
const DescriptorT& feature)
const;
118 template<
class DescriptorT>
119 std::vector<Word>
quantize(
const std::vector<DescriptorT>& features)
const;
122 template<
class DescriptorT>
123 SparseHistogram
quantizeToSparse(
const std::vector<DescriptorT>& features)
const;
127 const std::vector<Feature>* descriptors =
static_cast<const std::vector<Feature>*
>(blindDescriptors);
132 uint32_t
levels()
const override;
134 uint32_t
splits()
const override;
136 uint32_t
words()
const override;
139 void clear()
override;
142 void save(
const std::string& file)
const override;
144 void load(
const std::string& file)
override;
148 return (centers_ == other.centers_) && (valid_centers_ == other.valid_centers_) && (
k_ == other.
k_) && (levels_ == other.levels_) &&
149 (num_words_ == other.num_words_) && (word_start_ == other.word_start_);
153 std::vector<Feature> centers_;
154 std::vector<uint8_t> valid_centers_;
159 uint32_t word_start_;
161 bool initialized()
const {
return num_words_ != 0; }
163 void setNodeCounts();
166 template<
class Feature,
template<
typename,
typename>
class Distance>
167 VocabularyTree<Feature, Distance>::VocabularyTree()
174 template<
class Feature,
template<
typename,
typename>
class Distance>
184 template<
class Feature,
template<
typename,
typename>
class Distance>
185 template<
class DescriptorT>
188 typedef typename Distance<Feature, DescriptorT>::result_type distance_type;
191 assert(initialized());
194 for (
unsigned level = 0; level < levels_; ++level)
197 int32_t first_child = (index + 1) * splits();
199 int32_t best_child = first_child;
200 distance_type best_distance = std::numeric_limits<distance_type>::max();
201 for (int32_t child = first_child; child < first_child + (int32_t)splits(); ++child)
203 if (!valid_centers_[child])
205 distance_type child_distance = Distance<DescriptorT, Feature>()(feature, centers_[child]);
206 if (child_distance < best_distance)
209 best_distance = child_distance;
215 return index - word_start_;
218 template<
class Feature,
template<
typename,
typename>
class Distance>
219 template<
class DescriptorT>
223 std::vector<Word> imgVisualWords(features.size(), 0);
226 #pragma omp parallel for
227 for (ptrdiff_t j = 0; j < static_cast<ptrdiff_t>(features.size()); ++j)
230 imgVisualWords[j] = quantize<DescriptorT>(features[j]);
234 return imgVisualWords;
237 template<
class Feature,
template<
typename,
typename>
class Distance>
238 template<
class DescriptorT>
241 SparseHistogram histo;
242 std::vector<Word> doc = quantize(features);
243 computeSparseHistogram(doc, histo);
247 template<
class Feature,
template<
typename,
typename>
class Distance>
253 template<
class Feature,
template<
typename,
typename>
class Distance>
259 template<
class Feature,
template<
typename,
typename>
class Distance>
265 template<
class Feature,
template<
typename,
typename>
class Distance>
269 valid_centers_.clear();
270 k_ = levels_ = num_words_ = word_start_ = 0;
273 template<
class Feature,
template<
typename,
typename>
class Distance>
278 assert(initialized());
280 std::ofstream out(file, std::ios_base::binary);
281 out.write((
char*)(&k_),
sizeof(uint32_t));
282 out.write((
char*)(&levels_),
sizeof(uint32_t));
283 uint32_t size = centers_.size();
284 out.write((
char*)(&size),
sizeof(uint32_t));
285 out.write((
char*)(¢ers_[0]), centers_.size() *
sizeof(Feature));
286 out.write((
char*)(&valid_centers_[0]), valid_centers_.size());
289 template<
class Feature,
template<
typename,
typename>
class Distance>
295 in.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
300 in.open(file, std::ios_base::binary);
301 in.read((
char*)(&k_),
sizeof(uint32_t));
302 in.read((
char*)(&levels_),
sizeof(uint32_t));
303 in.read((
char*)(&size),
sizeof(uint32_t));
304 centers_.resize(size);
305 valid_centers_.resize(size);
306 in.read((
char*)(¢ers_[0]), centers_.size() *
sizeof(Feature));
307 in.read((
char*)(&valid_centers_[0]), valid_centers_.size());
309 catch (std::ifstream::failure& e)
311 throw std::runtime_error(
"Failed to load vocabulary tree file" + file);
315 assert(size == num_words_ + word_start_);
318 template<
class Feature,
template<
typename,
typename>
class Distance>
323 for (uint32_t i = 0; i < levels_ - 1; ++i)
325 word_start_ += num_words_;
339 float sparseDistance(
const SparseHistogram& v1,
340 const SparseHistogram& v2,
341 const std::string& distanceMethod =
"classic",
342 const std::vector<float>& word_weights = std::vector<float>());
344 inline std::unique_ptr<IVocabularyTree> createVoctreeForDescriberType(feature::EImageDescriberType imageDescriberType)
346 using namespace aliceVision::feature;
347 std::unique_ptr<IVocabularyTree> res;
349 switch (imageDescriberType)
351 case EImageDescriberType::SIFT:
352 res.reset(
new VocabularyTree<SIFT_Regions::DescriptorT>);
354 case EImageDescriberType::SIFT_FLOAT:
355 res.reset(
new VocabularyTree<SIFT_Float_Regions::DescriptorT>);
357 case EImageDescriberType::AKAZE:
358 res.reset(
new VocabularyTree<AKAZE_Float_Regions::DescriptorT>);
360 case EImageDescriberType::AKAZE_MLDB:
361 res.reset(
new VocabularyTree<AKAZE_BinaryRegions::DescriptorT>);
364 #if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_CCTAG)
365 case EImageDescriberType::CCTAG3:
366 case EImageDescriberType::CCTAG4:
367 res.reset(
new VocabularyTree<CCTAG_Regions::DescriptorT>);
369 #endif // ALICEVISION_HAVE_CCTAG
371 #if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_OPENCV)
372 #if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_OCVSIFT)
373 case EImageDescriberType::SIFT_OCV:
374 res.reset(
new VocabularyTree<SIFT_Regions::DescriptorT>);
376 #endif // ALICEVISION_HAVE_OCVSIFT
377 case EImageDescriberType::AKAZE_OCV:
378 res.reset(
new VocabularyTree<AKAZE_Float_Regions::DescriptorT>);
380 #endif // ALICEVISION_HAVE_OPENCV
383 throw std::out_of_range(
"Invalid imageDescriber enum");
389 inline void load(std::unique_ptr<IVocabularyTree>& out_voctree, feature::EImageDescriberType& out_descType,
const std::string& filepath)
391 std::size_t lastDot = filepath.find_last_of(
".");
392 if (lastDot == std::string::npos)
393 throw std::invalid_argument(
"Unrecognized Vocabulary tree filename (no extension): " + filepath);
394 std::size_t secondLastDot = filepath.find_last_of(
".", lastDot - 1);
395 if (secondLastDot == std::string::npos)
396 throw std::invalid_argument(
"Unrecognized Vocabulary tree filename (no descType in extension): " + filepath);
398 const std::string descTypeStr = filepath.substr((secondLastDot + 1), lastDot - (secondLastDot + 1));
400 out_descType = feature::EImageDescriberType_stringToEnum(descTypeStr);
401 out_voctree = createVoctreeForDescriberType(out_descType);
402 out_voctree->load(filepath);