1 #include "rgrl_trans_homo2d_proj_rad.h"
2 //:
3 // \file
4 #include <cassert>
5 #ifdef _MSC_VER
6 #  include "vcl_msvc_warnings.h"
7 #endif
8 
9 #include "vnl/vnl_vector_fixed.h"
10 #include "vnl/vnl_transpose.h"
11 #include "vnl/vnl_double_2.h"
12 #include "vnl/vnl_double_2x2.h"
13 #include <rgrl/rgrl_util.h>
14 
15 rgrl_trans_homo2d_proj_rad::
rgrl_trans_homo2d_proj_rad()16 rgrl_trans_homo2d_proj_rad()
17   : rgrl_est_proj_rad_func<2,2>( 0, true )
18   , H_( 0.0 )
19   , rad_k_(0)
20 {
21   const vnl_vector_fixed<double, 2> zeroc( 0, 0 );
22   this->set_centres( zeroc, zeroc, zeroc );
23 }
24 
25 
26 rgrl_trans_homo2d_proj_rad::
rgrl_trans_homo2d_proj_rad(vnl_matrix_fixed<double,3,3> const & H,std::vector<double> const & k,vnl_vector_fixed<double,2> const & image_centre)27 rgrl_trans_homo2d_proj_rad( vnl_matrix_fixed<double, 3, 3> const& H,
28                             std::vector<double>             const& k,
29                             vnl_vector_fixed< double, 2 >  const& image_centre)
30   : rgrl_est_proj_rad_func<2,2>( k.size(), true ),
31     H_(H),
32     rad_k_(k)
33 {
34   const vnl_vector_fixed<double, 2> zeroc( 0, 0 );
35   this->set_centres( zeroc, zeroc, image_centre );
36   set_up_rad_k(k);
37 }
38 
39 rgrl_trans_homo2d_proj_rad::
rgrl_trans_homo2d_proj_rad(vnl_matrix_fixed<double,3,3> const & H,std::vector<double> const & k,vnl_vector_fixed<double,2> const & image_centre,vnl_matrix<double> const & covar,vnl_vector<double> const & from_centre,vnl_vector<double> const & to_centre)40 rgrl_trans_homo2d_proj_rad( vnl_matrix_fixed<double, 3, 3> const& H,
41                             std::vector<double>             const& k,
42                             vnl_vector_fixed< double, 2 >  const& image_centre,
43                             vnl_matrix<double> const& covar,
44                             vnl_vector<double> const& from_centre,
45                             vnl_vector<double> const& to_centre )
46   : rgrl_transformation( covar ),
47     rgrl_est_proj_rad_func<2,2>( k.size(), true ),
48     H_(H),
49     rad_k_(k)
50 {
51   this->set_centres( from_centre, to_centre, image_centre );
52   set_up_rad_k( k );
53 }
54 
55 rgrl_trans_homo2d_proj_rad::
rgrl_trans_homo2d_proj_rad(std::vector<double> const & norm_k,vnl_matrix_fixed<double,3,3> const & H,vnl_vector_fixed<double,2> const & image_centre)56 rgrl_trans_homo2d_proj_rad( std::vector<double>             const& norm_k,
57                             vnl_matrix_fixed<double, 3, 3> const& H,
58                             vnl_vector_fixed< double, 2 >  const& image_centre )
59   : rgrl_est_proj_rad_func<2,2>( norm_k.size(), true ),
60     H_(H),
61     rad_k_(norm_k)
62 {
63   const vnl_vector_fixed<double, 2> zeroc( 0, 0 );
64   this->set_centres( zeroc, zeroc, image_centre );
65 }
66 
67 rgrl_trans_homo2d_proj_rad::
rgrl_trans_homo2d_proj_rad(std::vector<double> const & norm_k,vnl_matrix_fixed<double,3,3> const & H,vnl_vector_fixed<double,2> const & image_centre,vnl_matrix<double> const & covar,vnl_vector<double> const & from_centre,vnl_vector<double> const & to_centre)68 rgrl_trans_homo2d_proj_rad( std::vector<double>             const& norm_k,
69                             vnl_matrix_fixed<double, 3, 3> const& H,
70                             vnl_vector_fixed< double, 2 >  const& image_centre,
71                             vnl_matrix<double> const& covar,
72                             vnl_vector<double> const& from_centre,
73                             vnl_vector<double> const& to_centre )
74   : rgrl_transformation( covar ),
75     rgrl_est_proj_rad_func<2,2>( norm_k.size(), true ),
76     H_(H),
77     rad_k_(norm_k)
78 {
79   this->set_centres( from_centre, to_centre, image_centre );
80 }
81 
82 void
83 rgrl_trans_homo2d_proj_rad::
set_up_rad_k(std::vector<double> const & rad_k)84 set_up_rad_k(std::vector<double> const & rad_k)
85 {
86   rad_k_.resize(rad_k.size());
87   const double centre_mag_norm = centre_mag_norm_const();
88 
89   double base = 1;
90   for ( unsigned i=0; i<rad_k.size(); ++i ) {
91     base *= centre_mag_norm;
92     rad_k_[i] = rad_k[i] * base;
93   }
94 }
95 
96 void
97 rgrl_trans_homo2d_proj_rad::
map_loc(vnl_vector<double> const & from,vnl_vector<double> & to) const98 map_loc( vnl_vector<double> const& from,
99          vnl_vector<double>      & to  ) const
100 {
101   // use vnl_double_2 to reduce memory allocation
102   vnl_double_2 pt = from;
103   vnl_double_2 mapped;
104   rgrl_est_proj_rad_func<2,2>::map_loc( mapped, H_, rad_k_, pt );
105   to = mapped.as_ref();
106 }
107 
108 void
109 rgrl_trans_homo2d_proj_rad::
map_dir(vnl_vector<double> const & from_loc,vnl_vector<double> const & from_dir,vnl_vector<double> & to_dir) const110 map_dir( vnl_vector<double> const& from_loc,
111          vnl_vector<double> const& from_dir,
112          vnl_vector<double>      & to_dir  ) const
113 {
114   assert ( from_loc.size() == 2 );
115   assert ( from_dir.size() == 2 );
116 
117   const vnl_double_2 from_begin( from_loc );
118   vnl_double_2 from_end( from_loc );
119   from_end += from_dir;
120 
121   vnl_double_2 to_loc_begin, to_loc_end;
122   rgrl_est_proj_rad_func<2,2>::map_loc( to_loc_begin, H_, rad_k_, from_begin );
123   rgrl_est_proj_rad_func<2,2>::map_loc( to_loc_end,   H_, rad_k_, from_end );
124 
125   to_dir = (to_loc_end - to_loc_begin).as_ref();
126   to_dir.normalize();
127 }
128 
129 rgrl_transformation_sptr
130 rgrl_trans_homo2d_proj_rad::
scale_by(double scale) const131 scale_by( double scale ) const
132 {
133   vnl_matrix_fixed<double,3,3> new_H( H_ );
134 
135   // scale
136   new_H(0,2) *= scale;
137   new_H(1,2) *= scale;
138 
139   // move the scale on the fixed coordinate,
140   // and divide the 3rd row by this scale
141   new_H(2,0) /= scale;
142   new_H(2,1) /= scale;
143 
144   // normalize
145   new_H /= new_H.fro_norm();
146 
147   // centers
148   const vnl_vector_fixed<double,2> from = from_centre_ * scale;
149   const vnl_vector_fixed<double,2> to = to_centre_ * scale;
150   const vnl_vector_fixed<double,2> ic = image_centre_ * scale;
151 
152   // radial terms
153   std::vector<double> radk = radial_params();
154   const double sq_scale = scale*scale;
155 
156   double base = 1;
157   for (double & i : radk) {
158     base *= sq_scale;
159     i /= base;
160   }
161 
162   rgrl_transformation_sptr xform
163     =  new rgrl_trans_homo2d_proj_rad( new_H,
164                                        radk,
165                                        ic,
166                                        vnl_matrix<double>(),
167                                        from.as_ref(), to.as_ref() );
168   xform->set_scaling_factors( this->scaling_factors() );
169   return xform;
170 }
171 
172 
173 vnl_matrix_fixed<double, 3, 3>
174 rgrl_trans_homo2d_proj_rad::
H() const175 H( ) const
176 {
177   return uncentre_proj( H_ );
178 }
179 
180 vnl_matrix<double>
181 rgrl_trans_homo2d_proj_rad::
transfer_error_covar(vnl_vector<double> const & p) const182 transfer_error_covar( vnl_vector<double> const& p ) const
183 {
184   assert ( p.size() == 2 );
185   vnl_matrix<double> jac;
186   full_proj_rad_jacobian( jac, H_, rad_k_, p );
187   return jac*covar_*vnl_transpose(jac);
188 }
189 
190 //: Return the jacobian of the transform.
191 void
192 rgrl_trans_homo2d_proj_rad::
jacobian_wrt_loc(vnl_matrix<double> & jacobian,vnl_vector<double> const & from_loc) const193 jacobian_wrt_loc( vnl_matrix<double>& jacobian, vnl_vector<double> const& from_loc ) const
194 {
195   vnl_double_2x2 jac_loc;
196   proj_jac_wrt_loc( jac_loc, H_, rad_k_, from_loc );
197   jacobian = jac_loc.as_ref();
198 }
199 
200 // for output CENTERED transformation
201 void
202 rgrl_trans_homo2d_proj_rad::
write(std::ostream & os) const203 write(std::ostream& os ) const
204 {
205   // tag
206   os << "HOMOGRAPHY2D+RADIAL\n"
207   // parameters
208      << H_ << std::endl;
209 
210   // radial terms
211   os << rad_k_.size() << "  ";
212   for (double i : rad_k_)
213     os << i << ' ';
214 
215   os << '\n' << from_centre_ << "   " << to_centre_
216      << '\n' << image_centre_ << "   " << centre_mag_norm_const_
217      << std::endl;
218 
219   // parent
220   rgrl_transformation::write( os );
221 }
222 
223 // for input
224 bool
225 rgrl_trans_homo2d_proj_rad::
read(std::istream & is)226 read(std::istream& is )
227 {
228   // skip empty lines
229   rgrl_util_skip_empty_lines( is );
230 
231   std::string str;
232   std::getline( is, str );
233 
234   // The token should appear at the beginning of line
235   if ( str.find( "HOMOGRAPHY2D+RADIAL" ) != 0 ) {
236    return false;
237   }
238 
239   // input global xform
240   is >> H_;
241 
242   // input radial terms
243   {
244     int size = -1;
245     is >> size;
246     if ( size < 0 || !is.good() )
247       return false;
248 
249     rad_k_.resize( size );
250     for ( int i=0; i<size; ++i )
251       is >> rad_k_[i];
252 
253     // set H_dof_
254     camera_dof_ = size;
255   }
256 
257   is >> from_centre_ >> to_centre_;
258   is >> image_centre_;
259   is >> centre_mag_norm_const_;
260 
261   // parent
262   return is.good() && rgrl_transformation::read( is );
263 }
264 
265 //: make a clone copy
266 rgrl_transformation_sptr
267 rgrl_trans_homo2d_proj_rad::
clone() const268 clone() const
269 {
270   return new rgrl_trans_homo2d_proj_rad( *this );
271 }
272 
273 //: return radial parameters
274 std::vector<double>
275 rgrl_trans_homo2d_proj_rad::
radial_params() const276 radial_params() const
277 {
278   std::vector<double> ori_radk( rad_k_ );
279 
280   const double centre_mag_norm = centre_mag_norm_const();
281 
282   double base = 1;
283   for (double & i : ori_radk) {
284     base *= centre_mag_norm;
285     i /= base;
286   }
287   return ori_radk;
288 }
289