| 247 | } // namespace |
| 248 | |
| 249 | FeatureMatcherController::FeatureMatcherController( |
| 250 | const FeatureMatchingOptions& matching_options, |
| 251 | const TwoViewGeometryOptions& geometry_options, |
| 252 | std::shared_ptr<FeatureMatcherCache> cache) |
| 253 | : matching_options_(matching_options), |
| 254 | geometry_options_(geometry_options), |
| 255 | cache_(std::move(cache)), |
| 256 | is_setup_(false) { |
| 257 | THROW_CHECK(matching_options_.Check()); |
| 258 | THROW_CHECK(geometry_options_.Check()); |
| 259 | THROW_CHECK_EQ(geometry_options_.ransac_options.num_threads, 1) |
| 260 | << "Parallel RANSAC is not supported inside multi-threaded matching"; |
| 261 | |
| 262 | const int num_threads = GetEffectiveNumThreads(matching_options_.num_threads); |
| 263 | THROW_CHECK_GT(num_threads, 0); |
| 264 | |
| 265 | std::vector<int> gpu_indices = CSVToVector<int>(matching_options_.gpu_index); |
| 266 | THROW_CHECK_GT(gpu_indices.size(), 0); |
| 267 | |
| 268 | #if defined(COLMAP_CUDA_ENABLED) |
| 269 | if (matching_options_.use_gpu && gpu_indices.size() == 1 && |
| 270 | gpu_indices[0] == -1) { |
| 271 | const int num_cuda_devices = GetNumCudaDevices(); |
| 272 | THROW_CHECK_GT(num_cuda_devices, 0); |
| 273 | gpu_indices.resize(num_cuda_devices); |
| 274 | std::iota(gpu_indices.begin(), gpu_indices.end(), 0); |
| 275 | } |
| 276 | #endif // COLMAP_CUDA_ENABLED |
| 277 | |
| 278 | // If skip_geometric_verification, match directly to output_queue_. |
| 279 | const bool skip_geometric_verification = |
| 280 | matching_options_.skip_geometric_verification && |
| 281 | !matching_options_.guided_matching; |
| 282 | JobQueue<FeatureMatcherData>* matcher_output_queue = |
| 283 | skip_geometric_verification ? &output_queue_ : &verifier_queue_; |
| 284 | |
| 285 | if (matching_options_.use_gpu) { |
| 286 | auto worker_matching_options = matching_options_; |
| 287 | // The first matching is always without guided matching. |
| 288 | worker_matching_options.guided_matching = false; |
| 289 | matchers_.reserve(gpu_indices.size()); |
| 290 | for (const auto& gpu_index : gpu_indices) { |
| 291 | worker_matching_options.gpu_index = std::to_string(gpu_index); |
| 292 | matchers_.emplace_back( |
| 293 | std::make_unique<FeatureMatcherWorker>(worker_matching_options, |
| 294 | geometry_options_, |
| 295 | cache_, |
| 296 | &matcher_queue_, |
| 297 | matcher_output_queue)); |
| 298 | } |
| 299 | } else { |
| 300 | auto worker_matching_options = matching_options_; |
| 301 | // Prevent nested threading. |
| 302 | worker_matching_options.num_threads = 1; |
| 303 | // The first matching is always without guided matching. |
| 304 | worker_matching_options.guided_matching = false; |
| 305 | matchers_.reserve(num_threads); |
| 306 | for (int i = 0; i < num_threads; ++i) { |
nothing calls this directly
no test coverage detected