MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
cascade_hashing.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016, Andre Schulz
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <algorithm>
11#include <cstdint>
12#include <vector>
13
14#include "sfm/cascade_hashing.h"
15
17
18void
19CascadeHashing::GlobalData::generate_proj_matrices (Options const& opts)
20{
21 generate_proj_matrices(
22 &this->sift.prim_proj_mat,
23 &this->sift.sec_proj_mats,
24 opts);
25 generate_proj_matrices(
26 &this->surf.prim_proj_mat,
27 &this->surf.sec_proj_mats,
28 opts);
29}
30
31/* ---------------------------------------------------------------- */
32
33void
34CascadeHashing::init (bundler::ViewportList* viewports)
35{
36 ExhaustiveMatching::init(viewports);
37
38 util::WallTimer timer;
39 this->local_data_sift.clear();
40 this->local_data_sift.resize(viewports->size());
41 this->local_data_surf.clear();
42 this->local_data_surf.resize(viewports->size());
43
44 this->global_data.generate_proj_matrices(this->cashash_opts);
45
46 /* Convert feature descriptors to zero mean. */
47 math::Vec128f sift_avg;
48 math::Vec64f surf_avg;
49 compute_avg_descriptors(this->processed_feature_sets, &sift_avg, &surf_avg);
50
51#pragma omp parallel for schedule(dynamic)
52 for (std::size_t i = 0; i < viewports->size(); i++)
53 {
54 LocalData* ld_sift = &this->local_data_sift[i];
55 LocalData* ld_surf = &this->local_data_surf[i];
56
57 ProcessedFeatureSet const& pfs = this->processed_feature_sets[i];
58 std::vector<math::Vec128f> sift_zero_mean_descs;
59 std::vector<math::Vec64f> surf_zero_mean_descs;
60 this->compute_zero_mean_descs(&sift_zero_mean_descs,
61 &surf_zero_mean_descs, pfs.sift_descr, pfs.surf_descr, sift_avg,
62 surf_avg);
63
64 this->compute(ld_sift, ld_surf, sift_zero_mean_descs,
65 surf_zero_mean_descs, this->global_data, this->cashash_opts);
66 }
67 std::cout << "Computing cascade hashes took " << timer.get_elapsed()
68 << " ms" << std::endl;
69}
70
71void
72CascadeHashing::pairwise_match (int view_1_id, int view_2_id,
73 Matching::Result* result) const
74{
75 /* SIFT matching. */
76 ProcessedFeatureSet const& pfs_1 = this->processed_feature_sets[view_1_id];
77 ProcessedFeatureSet const& pfs_2 = this->processed_feature_sets[view_2_id];
78 LocalData const& ld_sift_1 = this->local_data_sift[view_1_id];
79 LocalData const& ld_sift_2 = this->local_data_sift[view_2_id];
80 Matching::Result sift_result;
81 if (pfs_1.sift_descr.size() > 0)
82 {
83 this->twoway_match(this->opts.sift_matching_opts,
84 ld_sift_1, ld_sift_2,
85 pfs_1.sift_descr, pfs_2.sift_descr,
86 &sift_result, this->cashash_opts);
87 Matching::remove_inconsistent_matches(&sift_result);
88 }
89
90 /* SURF matching. */
91 LocalData const& ld_surf_1 = this->local_data_surf[view_1_id];
92 LocalData const& ld_surf_2 = this->local_data_surf[view_2_id];
93 Matching::Result surf_result;
94 if (pfs_1.surf_descr.size() > 0)
95 {
96 this->twoway_match(this->opts.surf_matching_opts,
97 ld_surf_1, ld_surf_2,
98 pfs_1.surf_descr, pfs_2.surf_descr,
99 &surf_result, this->cashash_opts);
100 Matching::remove_inconsistent_matches(&surf_result);
101 }
102
103 Matching::combine_results(sift_result, surf_result, result);
104}
105
106void
107CascadeHashing::compute(
108 LocalData* ld_sift, LocalData* ld_surf,
109 std::vector<math::Vec128f> const& sift_zero_mean_descs,
110 std::vector<math::Vec64f> const& surf_zero_mean_descs,
111 GlobalData const& cashash_global_data,
112 Options const& cashash_opts)
113{
114 /* Compute cascade hashes of zero mean SIFT/SURF descriptors. */
115 compute_cascade_hashes(
116 sift_zero_mean_descs,
117 &ld_sift->comp_hash_data,
118 &ld_sift->bucket_grps_bucket_ids,
119 cashash_global_data.sift.prim_proj_mat,
120 cashash_global_data.sift.sec_proj_mats,
121 cashash_opts);
122 compute_cascade_hashes(
123 surf_zero_mean_descs,
124 &ld_surf->comp_hash_data,
125 &ld_surf->bucket_grps_bucket_ids,
126 cashash_global_data.surf.prim_proj_mat,
127 cashash_global_data.surf.sec_proj_mats,
128 cashash_opts);
129
130 /* Build buckets. */
131 build_buckets(
132 &ld_sift->bucket_grps_feature_ids,
133 ld_sift->bucket_grps_bucket_ids,
134 sift_zero_mean_descs.size(),
135 cashash_opts);
136 build_buckets(
137 &ld_surf->bucket_grps_feature_ids,
138 ld_surf->bucket_grps_bucket_ids,
139 surf_zero_mean_descs.size(),
140 cashash_opts);
141}
142
143/* ---------------------------------------------------------------- */
144
145void
146CascadeHashing::compute_avg_descriptors (ProcessedFeatureSets const& pfs,
147 math::Vec128f* sift_avg, math::Vec64f* surf_avg)
148{
149 math::Vec128f sift_vec_sum(0.0f);
150 math::Vec64f surf_vec_sum(0.0f);
151 std::size_t num_sift_descs_total = 0;
152 std::size_t num_surf_descs_total = 0;
153
154 /* Compute sum of all SIFT/SURF descriptors. */
155 for (std::size_t i = 0; i < pfs.size(); i++)
156 {
157 SiftDescriptors const& sift_descr = pfs[i].sift_descr;
158 SurfDescriptors const& surf_descr = pfs[i].surf_descr;
159
160 std::size_t num_sift_descriptors = sift_descr.size();
161 std::size_t num_surf_descriptors = surf_descr.size();
162 num_sift_descs_total += num_sift_descriptors;
163 num_surf_descs_total += num_surf_descriptors;
164
165 for (std::size_t j = 0; j < num_sift_descriptors; j++)
166 for (int k = 0; k < 128; k++)
167 sift_vec_sum[k] += sift_descr[j][k] / 255.0f;
168
169 for (std::size_t j = 0; j < num_surf_descriptors; j++)
170 for (int k = 0; k < 64; k++)
171 surf_vec_sum[k] += surf_descr[j][k] / 127.0f;
172 }
173
174 /* Compute average vectors for SIFT/SURF. */
175 *sift_avg = sift_vec_sum / num_sift_descs_total;
176 *surf_avg = surf_vec_sum / num_surf_descs_total;
177}
178
179void
180CascadeHashing::compute_zero_mean_descs(
181 std::vector<math::Vec128f>* sift_zero_mean_descs,
182 std::vector<math::Vec64f>* surf_zero_mean_descs,
183 SiftDescriptors const& sift_descs, SurfDescriptors const& surf_descs,
184 math::Vec128f const& sift_avg, math::Vec64f const& surf_avg)
185{
186 /* Compute zero mean descriptors. */
187 sift_zero_mean_descs->resize(sift_descs.size());
188 for (std::size_t i = 0; i < sift_descs.size(); i++)
189 for (int j = 0; j < 128; j++)
190 (*sift_zero_mean_descs)[i][j] = sift_descs[i][j] / 255.0f - sift_avg[j];
191
192 surf_zero_mean_descs->resize(surf_descs.size());
193 for (std::size_t i = 0; i < surf_descs.size(); i++)
194 for (int j = 0; j < 64; j++)
195 (*surf_zero_mean_descs)[i][j] = surf_descs[i][j] / 127.0f - surf_avg[j];
196}
197
198/* ---------------------------------------------------------------- */
199
200void
201CascadeHashing::build_buckets(
202 BucketGroupsFeatures *bucket_grps_feature_ids,
203 BucketGroupsBuckets const& bucket_grps_bucket_ids,
204 size_t num_descs,
205 Options const& opts)
206{
207 uint8_t const num_bucket_grps = opts.num_bucket_groups;
208 uint8_t const num_bucket_bits = opts.num_bucket_bits;
209 uint32_t const num_buckets_per_group = 1 << num_bucket_bits;
210
211 bucket_grps_feature_ids->resize(num_bucket_grps);
212
213 for (uint8_t grp_idx = 0; grp_idx < num_bucket_grps; grp_idx++)
214 {
215 BucketGroupFeatures &bucket_grp_features = (*bucket_grps_feature_ids)[grp_idx];
216 bucket_grp_features.resize(num_buckets_per_group);
217 for (size_t i = 0; i < num_descs; i++)
218 {
219 uint16_t bucket_id = bucket_grps_bucket_ids[grp_idx][i];
220 bucket_grp_features[bucket_id].emplace_back(i);
221 }
222 }
223}
224
Cross-platform high-resolution real-time timer.
Definition timer.h:30
std::size_t get_elapsed(void) const
Returns the milli seconds since last reset.
Definition timer.h:94
std::vector< Viewport > ViewportList
The list of all viewports considered for bundling.
#define SFM_NAMESPACE_END
Definition defines.h:14
#define SFM_NAMESPACE_BEGIN
Definition defines.h:13
Feature matching result reported as two lists, each with indices in the other set.
Definition matching.h:57