opensfm/bow.py (50 lines of code) (raw):

import os.path import cv2 import numpy as np from opensfm import context class BagOfWords: def __init__(self, words, frequencies): self.words = words self.frequencies = frequencies self.weights = np.log(frequencies.sum() / frequencies) FLANN_INDEX_KDTREE = 1 flann_params = {"algorithm": FLANN_INDEX_KDTREE, "trees": 8, "checks": 300} self.index = context.flann_Index(words, flann_params) def map_to_words(self, descriptors, k, matcher_type="FLANN"): if matcher_type == "FLANN": params = {"checks": 200} idx, dist = self.index.knnSearch(descriptors, k, params=params) else: matcher = cv2.DescriptorMatcher_create(matcher_type) matches = matcher.knnMatch(descriptors, self.words, k=k) idx = [[int(n.trainIdx) for n in m] for m in matches] idx = np.array(idx).astype(np.int32) return idx def histogram(self, words): h = np.bincount(words, minlength=len(self.words)) * self.weights return h / h.sum() def bow_distance(self, w1, w2, h1=None, h2=None): if h1 is None: h1 = self.histogram(w1) if h2 is None: h2 = self.histogram(w2) return np.fabs(h1 - h2).sum() def load_bow_words_and_frequencies(config): if config["bow_file"] == "bow_hahog_root_uchar_10000.npz": assert config["feature_type"] == "HAHOG" assert config["feature_root"] assert config["hahog_normalize_to_uchar"] bow_file = os.path.join(context.BOW_PATH, config["bow_file"]) bow = np.load(bow_file) return bow["words"], bow["frequencies"] def load_vlad_words_and_frequencies(config): if config["vlad_file"] == "bow_hahog_root_uchar_64.npz": assert config["feature_type"] == "HAHOG" assert config["feature_root"] assert config["hahog_normalize_to_uchar"] vlad_file = os.path.join(context.BOW_PATH, config["vlad_file"]) vlad = np.load(vlad_file) return vlad["words"], vlad["frequencies"] def load_bows(config) -> BagOfWords: words, frequencies = load_bow_words_and_frequencies(config) return BagOfWords(words, frequencies)