@@ -351,8 +351,8 @@ py::tuple BAHelpers::BundleLocal(
351351bool BAHelpers::TriangulateGCP (
352352 const map::GroundControlPoint& point,
353353 const std::unordered_map<map::ShotId, map::Shot>& shots,
354+ float reproj_threshold,
354355 Vec3d& coordinates) {
355- constexpr auto reproj_threshold{1.0 };
356356 constexpr auto min_ray_angle = 0.1 * M_PI / 180.0 ;
357357 constexpr auto min_depth = 1e-3 ; // Assume GCPs 1mm+ away from the camera
358358 MatX3d os, bs;
@@ -390,52 +390,58 @@ size_t BAHelpers::AddGCPToBundle(
390390 const auto & reference = map.GetTopocentricConverter ();
391391 const auto & shots = map.GetShots ();
392392
393- const auto dominant_terms = ba.GetRigInstances ().size () +
394- ba.GetProjectionsCount () +
395- ba.GetRelativeMotionsCount ();
396393
397- size_t total_terms = 0 ;
398- for (const auto & point : gcp) {
399- Vec3d coordinates;
400- if (TriangulateGCP (point, shots, coordinates) || !point.lla_ .empty ()) {
401- ++total_terms;
402- }
403- for (const auto & obs : point.observations_ ) {
404- total_terms += (shots.count (obs.shot_id_ ) > 0 );
405- }
406- }
407-
408- double global_weight = config[" gcp_global_weight" ].cast <double >() *
409- dominant_terms / std::max<size_t >(1 , total_terms);
394+ const float reproj_threshold =
395+ config[" gcp_reprojection_error_threshold" ].cast <float >();
410396
411397 size_t added_gcp_observations = 0 ;
412398 for (const auto & point : gcp) {
413399 const auto point_id = " gcp-" + point.id_ ;
414400 Vec3d coordinates;
415- if (!TriangulateGCP (point, shots, coordinates)) {
401+ if (!TriangulateGCP (point, shots, reproj_threshold, coordinates)) {
416402 if (!point.lla_ .empty ()) {
417403 coordinates = reference.ToTopocentric (point.GetLlaVec3d ());
418404 } else {
419405 continue ;
420406 }
421407 }
408+
409+ double avg_observations = 0 .;
410+ int valid_shots = 0 ;
411+ for (const auto & obs : point.observations_ ) {
412+ const auto shot_it = shots.find (obs.shot_id_ );
413+ if (shot_it != shots.end ()) {
414+ const auto & shot = (shot_it->second );
415+ avg_observations += shot.GetLandmarkObservations ().size ();
416+ ++valid_shots;
417+ }
418+ }
419+
420+ if (!valid_shots) {
421+ continue ;
422+ }
423+ avg_observations /= valid_shots;
424+
425+
426+ const double prior_weight = config[" gcp_global_weight" ].cast <double >() * avg_observations;
422427 constexpr auto point_constant{false };
423428 ba.AddPoint (point_id, coordinates, point_constant);
424429 if (!point.lla_ .empty ()) {
425430 const auto point_std = Vec3d (config[" gcp_horizontal_sd" ].cast <double >(),
426431 config[" gcp_horizontal_sd" ].cast <double >(),
427432 config[" gcp_vertical_sd" ].cast <double >());
428433 ba.AddPointPrior (point_id, reference.ToTopocentric (point.GetLlaVec3d ()),
429- point_std / global_weight , point.has_altitude_ );
434+ point_std / prior_weight , point.has_altitude_ );
430435 }
431436
432437 // Now iterate through the observations
438+ const double obs_weight = config[" gcp_global_weight" ].cast <double >() * avg_observations;
433439 for (const auto & obs : point.observations_ ) {
434440 const auto & shot_id = obs.shot_id_ ;
435441 if (shots.count (shot_id) > 0 ) {
436442 constexpr double scale{0.001 };
437443 ba.AddPointProjectionObservation (shot_id, point_id, obs.projection_ ,
438- scale / global_weight );
444+ scale / obs_weight );
439445 ++added_gcp_observations;
440446 }
441447 }
@@ -829,7 +835,7 @@ py::dict BAHelpers::Bundle(
829835 AddGCPToBundle (ba, map, gcp, config);
830836 }
831837
832- if (config[" bundle_compensate_gps_bias" ].cast <bool >()) {
838+ if (config[" bundle_compensate_gps_bias" ].cast <bool >() && !gcp. empty () ) {
833839 const auto & biases = map.GetBiases ();
834840 for (const auto & camera : map.GetCameras ()) {
835841 ba.SetCameraBias (camera.first , biases.at (camera.first ));
@@ -989,7 +995,7 @@ void BAHelpers::AlignmentConstraints(
989995 continue ;
990996 }
991997 Vec3d coordinates;
992- if (TriangulateGCP (point, shots, coordinates)) {
998+ if (TriangulateGCP (point, shots, config[ " gcp_reprojection_error_threshold " ]. cast < float >(), coordinates)) {
993999 Xp.row (idx) = topocentricConverter.ToTopocentric (point.GetLlaVec3d ());
9941000 X.row (idx) = coordinates;
9951001 ++idx;
0 commit comments