Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #include "msm_translation_aligner.h"
00007 #include <vnl/vnl_vector.h>
00008 #include <vsl/vsl_binary_loader.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_cstddef.h>
00011
00012
00013
00014
00015 vnl_vector<double> msm_translation_aligner::inverse(const vnl_vector<double>& t) const
00016 {
00017 return -t;
00018 }
00019
00020
00021 void msm_translation_aligner::apply_transform(const msm_points& points,
00022 const vnl_vector<double>& trans,
00023 msm_points& new_points) const
00024 {
00025 new_points=points;
00026 new_points.translate_by(trans[0],trans[1]);
00027 }
00028
00029
00030
00031 double msm_translation_aligner::scale(const vnl_vector<double>& trans) const
00032 {
00033 return 1.0;
00034 }
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 void msm_translation_aligner::calc_transform_from_ref(const msm_points& ref_pts,
00049 const msm_points& pts2,
00050 vnl_vector<double>& trans) const
00051 {
00052 vgl_point_2d<double> cog2 = pts2.cog();
00053 trans.set_size(2);
00054 trans[0]=cog2.x();
00055 trans[1]=cog2.y();
00056 }
00057
00058
00059
00060 void msm_translation_aligner::calc_transform(const msm_points& pts1,
00061 const msm_points& pts2,
00062 vnl_vector<double>& trans) const
00063 {
00064 vgl_point_2d<double> cog1 = pts1.cog();
00065 vgl_point_2d<double> cog2 = pts2.cog();
00066
00067 trans.set_size(2);
00068 trans[0]=cog2.x()-cog1.x();
00069 trans[1]=cog2.y()-cog1.y();
00070 }
00071
00072
00073 inline vgl_point_2d<double> msm_wtd_cog(const msm_points& pts,
00074 const vnl_vector<double>& wts)
00075 {
00076 const double* v=pts.vector().data_block();
00077 const double* w=wts.data_block();
00078 unsigned n=pts.size();
00079 const double* end_v=v+2*n;
00080 double cx=0.0,cy=0.0,w_sum=0.0;
00081 for (;v!=end_v;v+=2,++w)
00082 { cx+=w[0]*v[0]; cy+=w[0]*v[1]; w_sum+=w[0]; }
00083
00084 if (w_sum>0) { cx/=w_sum; cy/=w_sum; }
00085 return vgl_point_2d<double>(cx,cy);
00086 }
00087
00088
00089
00090
00091 void msm_translation_aligner::calc_transform_wt(const msm_points& pts1,
00092 const msm_points& pts2,
00093 const vnl_vector<double>& wts,
00094 vnl_vector<double>& trans) const
00095 {
00096 vgl_point_2d<double> cog1 = msm_wtd_cog(pts1,wts);
00097 vgl_point_2d<double> cog2 = msm_wtd_cog(pts2,wts);
00098
00099 trans.set_size(2);
00100 trans[0]=cog2.x()-cog1.x();
00101 trans[1]=cog2.y()-cog1.y();
00102 }
00103
00104
00105
00106
00107 void msm_translation_aligner::calc_transform_wt_mat(const msm_points& pts1,
00108 const msm_points& pts2,
00109 const vcl_vector<msm_wt_mat_2d>& wt_mat,
00110 vnl_vector<double>& trans) const
00111 {
00112 assert(pts2.size()==pts1.size());
00113 assert(wt_mat.size()==pts1.size());
00114
00115 msm_wt_mat_2d w_sum(0,0,0);
00116 double x1=0.0,y1=0.0;
00117 double x2=0.0,y2=0.0;
00118 const double* p1 = pts1.vector().begin();
00119 const double* p2 = pts2.vector().begin();
00120 const double* p1_end = pts1.vector().end();
00121 vcl_vector<msm_wt_mat_2d>::const_iterator w=wt_mat.begin();
00122 for (;p1!=p1_end;p1+=2,p2+=2,++w)
00123 {
00124 double wa=w->m11(), wb=w->m12(), wc=w->m22();
00125 w_sum += (*w);
00126 x1 += wa*p1[0]+wb*p1[1];
00127 y1 += wb*p1[0]+wc*p1[1];
00128 x2 += wa*p2[0]+wb*p2[1];
00129 y2 += wb*p2[0]+wc*p2[1];
00130 }
00131 msm_wt_mat_2d w_inv = w_sum.inverse();
00132 double v11=w_inv.m11(), v12=w_inv.m12(), v22=w_inv.m22();
00133 vgl_point_2d<double> cog1(v11*x1+v12*y1,v12*x1+v22*y1);
00134 vgl_point_2d<double> cog2(v11*x2+v12*y2,v12*x2+v22*y2);
00135
00136 trans.set_size(2);
00137 trans[0]=cog2.x()-cog1.x();
00138 trans[1]=cog2.y()-cog1.y();
00139 }
00140
00141
00142 void msm_translation_aligner::transform_wt_mat(const vcl_vector<msm_wt_mat_2d>& wt_mat,
00143 const vnl_vector<double>& trans,
00144 vcl_vector<msm_wt_mat_2d>& new_wt_mat) const
00145 {
00146 new_wt_mat = wt_mat;
00147 }
00148
00149
00150 vnl_vector<double> msm_translation_aligner::compose(
00151 const vnl_vector<double>& pose1,
00152 const vnl_vector<double>& pose2) const
00153 {
00154 return pose1+pose2;
00155 }
00156
00157
00158
00159
00160 void msm_translation_aligner::normalise_shape(msm_points& points) const
00161 {
00162 vgl_point_2d<double> cog = points.cog();
00163 points.translate_by(-cog.x(),-cog.y());
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 void msm_translation_aligner::align_set(const vcl_vector<msm_points>& points,
00174 msm_points& ref_mean_shape,
00175 vcl_vector<vnl_vector<double> >& pose_to_ref,
00176 vnl_vector<double>& average_pose) const
00177 {
00178 vcl_size_t n_shapes = points.size();
00179 assert(n_shapes>0);
00180 pose_to_ref.resize(n_shapes);
00181
00182
00183 ref_mean_shape = points[0];
00184 normalise_shape(ref_mean_shape);
00185
00186 vnl_vector<double> pose_from_ref;
00187
00188 average_pose.set_size(2);
00189 average_pose.fill(0);
00190
00191 for (unsigned i=0;i<n_shapes;++i)
00192 {
00193 calc_transform_from_ref(ref_mean_shape,points[i],pose_from_ref);
00194 pose_to_ref[i]=inverse(pose_from_ref);
00195 average_pose+=pose_from_ref;
00196 }
00197
00198 mean_of_transformed(points,pose_to_ref,ref_mean_shape);
00199 average_pose/=n_shapes;
00200 }
00201
00202
00203
00204 vcl_string msm_translation_aligner::is_a() const
00205 {
00206 return vcl_string("msm_translation_aligner");
00207 }
00208
00209
00210 msm_aligner* msm_translation_aligner::clone() const
00211 {
00212 return new msm_translation_aligner(*this);
00213 }
00214
00215