1 #include "rgrl_convergence_tester.h"
2 #include <rgrl/rgrl_view.h>
3 #include <rgrl/rgrl_converge_status.h>
4 
5 rgrl_convergence_tester::
6 ~rgrl_convergence_tester() = default;
7 
8 rgrl_converge_status_sptr
9 rgrl_convergence_tester::
compute_status(const rgrl_converge_status_sptr & prev_status,rgrl_view const & prev_view,rgrl_view const & current_view,const rgrl_match_set_sptr & current_match_set,const rgrl_scale_sptr & current_scale,bool penalize_scaling) const10 compute_status( const rgrl_converge_status_sptr&               prev_status,
11                 rgrl_view                        const& prev_view,
12                 rgrl_view                        const& current_view,
13                 const rgrl_match_set_sptr&                     current_match_set,
14                 const rgrl_scale_sptr&                         current_scale,
15                 bool                                    penalize_scaling )const
16 {
17   rgrl_set_of<rgrl_match_set_sptr> match_sets;
18   match_sets.push_back( current_match_set );
19   rgrl_set_of<rgrl_scale_sptr> scales;
20   scales.push_back( current_scale );
21   return compute_status( prev_status, prev_view, current_view,
22                          match_sets, scales, penalize_scaling );
23 }
24 
25 rgrl_converge_status_sptr
26 rgrl_convergence_tester::
compute_status(const rgrl_converge_status_sptr & prev_status,const rgrl_transformation_sptr & xform_estimate,const rgrl_estimator_sptr & xform_estimator,rgrl_set_of<rgrl_match_set_sptr> const & current_match_sets,rgrl_set_of<rgrl_scale_sptr> const & current_scales,bool penalize_scaling) const27 compute_status( const rgrl_converge_status_sptr&               prev_status,
28                 const rgrl_transformation_sptr&                xform_estimate,
29                 const rgrl_estimator_sptr&                     xform_estimator,
30                 rgrl_set_of<rgrl_match_set_sptr> const& current_match_sets,
31                 rgrl_set_of<rgrl_scale_sptr>     const& current_scales,
32                 bool                                    penalize_scaling )const
33 {
34   rgrl_mask_box   dummy_image_region(0);
35   rgrl_mask_sptr  dummy_roi = new rgrl_mask_box( 0 );
36   rgrl_view view( dummy_roi, dummy_roi,
37                   dummy_image_region, dummy_image_region,
38                   xform_estimator, xform_estimate, 0);
39   return compute_status( prev_status, view, view,
40                          current_match_sets, current_scales, penalize_scaling );
41 }
42 
43 rgrl_converge_status_sptr
44 rgrl_convergence_tester::
compute_status(const rgrl_converge_status_sptr & prev_status,const rgrl_transformation_sptr & xform_estimate,const rgrl_estimator_sptr & xform_estimator,const rgrl_match_set_sptr & current_match_set,const rgrl_scale_sptr & current_scale,bool penalize_scaling) const45 compute_status( const rgrl_converge_status_sptr&               prev_status,
46                 const rgrl_transformation_sptr&                xform_estimate,
47                 const rgrl_estimator_sptr&                     xform_estimator,
48                 const rgrl_match_set_sptr&                     current_match_set,
49                 const rgrl_scale_sptr&                         current_scale,
50                 bool                                    penalize_scaling )const
51 {
52   rgrl_set_of<rgrl_match_set_sptr> match_sets;
53   match_sets.push_back( current_match_set );
54   rgrl_set_of<rgrl_scale_sptr> scales;
55   scales.push_back( current_scale );
56   return compute_status( prev_status, xform_estimate, xform_estimator,
57                          match_sets, scales, penalize_scaling );
58 }
59 
60 
61 rgrl_converge_status_sptr
62 rgrl_convergence_tester::
verify(rgrl_view const & view,rgrl_match_set_sptr const & current_match_set,rgrl_scale_sptr const & current_scale) const63 verify( rgrl_view                   const& view,
64         rgrl_match_set_sptr         const& current_match_set,
65         rgrl_scale_sptr             const& current_scale )const
66 {
67   rgrl_set_of<rgrl_match_set_sptr> match_sets;
68   match_sets.push_back( current_match_set );
69   rgrl_set_of<rgrl_scale_sptr> scales;
70   scales.push_back( current_scale );
71   return this->verify( view, match_sets, scales );
72 }
73 
74 rgrl_converge_status_sptr
75 rgrl_convergence_tester::
verify(rgrl_view const &,rgrl_set_of<rgrl_match_set_sptr> const &,rgrl_set_of<rgrl_scale_sptr> const &) const76 verify( rgrl_view                        const& /*view*/,
77         rgrl_set_of<rgrl_match_set_sptr> const& /*current_match_sets*/,
78         rgrl_set_of<rgrl_scale_sptr>     const& /*current_scales*/ )const
79 {
80   std::cerr << "WARNING: should never call rgrl_convergence_tester::verify()\n";
81   return new rgrl_converge_status( rgrl_converge_status::converged, rgrl_converge_status::good_and_terminate,
82                                    -1.0, 0, -1.0 );
83 }
84 
85 rgrl_converge_status_sptr
86 rgrl_convergence_tester::
initialize_status(const rgrl_transformation_sptr & xform_estimate,const rgrl_estimator_sptr & xform_estimator,rgrl_scale_sptr const & prior_scale,bool penalize_scaling) const87 initialize_status( const rgrl_transformation_sptr&                xform_estimate,
88                    const rgrl_estimator_sptr&                     xform_estimator,
89                    rgrl_scale_sptr                  const& prior_scale,
90                    bool                                    penalize_scaling )const
91 {
92   rgrl_mask_box   dummy_image_region(0);
93   rgrl_mask_sptr  dummy_roi = new rgrl_mask_box( 0 );
94   rgrl_view view( dummy_roi, dummy_roi,
95                   dummy_image_region, dummy_image_region,
96                   xform_estimator, xform_estimate, 0);
97   return this->init_status( view, prior_scale, penalize_scaling );
98 }
99 
100 rgrl_converge_status_sptr
101 rgrl_convergence_tester::
initialize_status(rgrl_view const & init_view,rgrl_scale_sptr const & prior_scale,bool penalize_scaling) const102 initialize_status( rgrl_view       const& init_view,
103                    rgrl_scale_sptr const& prior_scale,
104                    bool                   penalize_scaling ) const
105 {
106   // call the real virtual function
107   return this->init_status( init_view, prior_scale, penalize_scaling );
108 }
109 
110 rgrl_converge_status_sptr
111 rgrl_convergence_tester::
init_status(rgrl_view const &,rgrl_scale_sptr const &,bool) const112 init_status( rgrl_view       const& /*init_view*/,
113              rgrl_scale_sptr const& /*prior_scale*/,
114              bool                   /*penalize_scaling*/ ) const
115 {
116   // nothing to initialize
117   return nullptr;
118 }
119 
120 rgrl_converge_status_sptr
121 rgrl_convergence_tester::
compute_status_helper(double new_error,bool good_enough,rgrl_converge_status_sptr prev_status,rgrl_view const & prev_view,rgrl_view const & current_view) const122 compute_status_helper( double new_error,
123                        bool good_enough,
124                 rgrl_converge_status_sptr               prev_status,
125                 rgrl_view                        const& prev_view,
126                 rgrl_view                        const& current_view ) const
127 {
128   // Step3: First check if the regions in the view have converged. If yes,
129   //        check the convergence of the transform estimate by comparing to
130   //        the previous status. The oscillation count is incremented if the
131   //        error_diff changes the sign.
132   //
133   bool converged;
134   bool stagnated = false;
135   unsigned int oscillation_count = 0;
136   double error_diff = 0.0;
137   if (new_error == 0.0 )
138     converged = true;
139   else if ( prev_status &&  current_view.regions_converged_to(prev_view) ) {
140     double old_error = prev_status->error();
141     error_diff = new_error-old_error;
142     double diff = (new_error-old_error) / new_error ;
143     converged = std::abs( diff ) < rel_tol_thres_;
144 
145     if ( !converged ) {
146       // look for oscillation
147       // There are two kinds of oscillation:
148       // 1. the error increases and decreases in turn
149       // 2. Once it is good enough, the error increases slightly
150       //
151 
152       // first situation
153       if ( !good_enough ) {
154         if ( error_diff * prev_status->error_diff() < 0.0 ) {
155           oscillation_count = prev_status->oscillation_count() + 1;
156           DebugMacro_abv(1, "Oscillation. Count="<<oscillation_count<<'\n' );
157 
158         } else {
159           if ( prev_status->oscillation_count() > 0 )
160             oscillation_count = prev_status->oscillation_count() - 1;
161         }
162         if ( oscillation_count > 10 ) {
163           stagnated = true;
164         }
165       } else {
166 
167         // second situation
168         if ( error_diff > 0 )  { // error increases again
169           oscillation_count = prev_status->oscillation_count() + 1;
170           DebugMacro_abv(1, "Good Oscillation. Count="<<oscillation_count<<'\n' );
171         }
172 
173         // check for oscillation, call convergence
174         if ( oscillation_count > 3 )
175           converged = true;
176       }
177     }
178 
179   } else {
180     converged = false;
181   }
182 
183   return new rgrl_converge_status( converged, stagnated, good_enough, false, new_error, oscillation_count, error_diff );
184 }
185