contrib/mul/msm/utils/msm_shape_mode_view.cxx
Go to the documentation of this file.
00001 
00002 //:
00003 // \file
00004 // \brief Generates shapes displaying modes of a shape model.
00005 // \author Tim Cootes
00006 
00007 #include "msm_shape_mode_view.h"
00008 #include <msm/msm_ref_shape_model.h>
00009 #include <vcl_cmath.h>
00010 #include <vsl/vsl_indent.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_algorithm.h>
00013 
00014 //=======================================================================
00015 // Dflt ctor
00016 //=======================================================================
00017 
00018 msm_shape_mode_view::msm_shape_mode_view():
00019   shape_model_(0),
00020   points_(3),
00021   n_per_mode_(3),
00022   mode_(0),
00023   sd_range_(3.0),
00024   rel_scale_(0.95),
00025   overlap_shapes_(false),
00026   display_win_(0,255,0,128)
00027 {}
00028 
00029 
00030 //: When true, overlap all the shapes to highlight changes
00031 void msm_shape_mode_view::set_overlap_shapes(bool b)
00032 {
00033   msm_shape_mode_view::overlap_shapes_=b;
00034 
00035   if (shape_model_!=0)
00036     compute_shapes();
00037 }
00038 
00039 //=======================================================================
00040 //: Define shape model
00041 //=======================================================================
00042 
00043 void msm_shape_mode_view::set_shape_model(const msm_ref_shape_model& sm)
00044 {
00045   shape_model_ = &sm;
00046   sm_inst_.set_shape_model(*shape_model_);
00047 
00048   b_sd_ = sm.mode_var();
00049   for (unsigned i=0;i<b_sd_.size();i++) b_sd_[i]=vcl_sqrt(b_sd_[i]);
00050 
00051   if (b_sd_.size()>0)
00052     set_mode(1);
00053   else
00054     set_mode(0);
00055 
00056   compute_shapes();
00057 }
00058 
00059 //: Define width of display region for a single shape
00060 //  Height estimated from aspect ratio of mean shape
00061 //  Width of display window is then a multiple of this,
00062 //  depending on the number of shapes along the row.
00063 void msm_shape_mode_view::set_display_width(double width)
00064 {
00065   // Estimate aspect ratio
00066   vgl_box_2d<double> bounds = shape_model().mean_points().bounds();
00067   double asp=bounds.height()/(1e-3+bounds.width());
00068 
00069   int win_width;
00070   if (overlap_shapes_)
00071     win_width=int(width);
00072   else
00073     win_width=int(width*n_per_mode_);
00074 
00075   int win_height=int(asp*width);
00076   set_display_window(vgl_box_2d<int>(0,win_width, 0,win_height));
00077 }
00078 
00079 
00080 //: Current shape model
00081 const msm_ref_shape_model& msm_shape_mode_view::shape_model() const
00082 {
00083   assert(shape_model_!=0);
00084   return *shape_model_;
00085 }
00086 
00087 //: Compute the shapes so they fit into current window
00088 void msm_shape_mode_view::compute_shapes()
00089 {
00090   compute_shapes(n_per_mode_,sd_range_,false);
00091 }
00092 
00093 //: Compute the shapes so they fit into current window
00094 void msm_shape_mode_view::compute_shapes(unsigned n_shapes,
00095                                          double range, bool vary_one)
00096 {
00097   if (mode_<=0) return;
00098   if (mode_>b_sd_.size()) return;
00099 
00100   double min_b,db;
00101 
00102   if (n_shapes>1)
00103   {
00104     min_b = -1.0 * range * b_sd_(mode_-1);
00105     db = -2.0 * min_b/(n_shapes-1);
00106   }
00107   else
00108   {
00109     if (vary_one)
00110     {
00111       min_b = 1.0 * range * b_sd_(mode_-1);
00112       db = 0;
00113     }
00114     else
00115     {
00116       min_b = 0.0;
00117       db    = 0.0;
00118     }
00119   }
00120   points_.resize(n_shapes);
00121 
00122   // First compute model shapes and largest bounding box
00123   vgl_box_2d<double> bbox;
00124   for (unsigned i=0;i<n_shapes;++i)
00125   {
00126     b_(mode_-1) = min_b + db*i;
00127     sm_inst_.set_params(b_);
00128     points_[i]=sm_inst_.points();
00129     if (i==0)
00130       bbox=points_[i].bounds();
00131     else
00132     {
00133       bbox.add(points_[i].bounds());
00134     }
00135   }
00136 
00137   double w_width;
00138   if (overlap_shapes_)
00139     w_width = display_win_.width();
00140   else
00141     w_width = display_win_.width()/n_per_mode_;
00142   double w_height = display_win_.height();
00143 
00144   // Estimate scaling required to fit into window
00145 
00146   // Assumes shapes have origin at CoG
00147 //  double sw = 0.5*w_width/vcl_max(-bbox.min_x(),bbox.max_x());
00148 //  double sh = 0.5*w_height/vcl_max(-bbox.min_y(),bbox.max_y());
00149   double sw = w_width/(bbox.max_x()-bbox.min_x());
00150   double sh = w_height/(bbox.max_y()-bbox.min_y());
00151   double s = vcl_min(sw,sh)*rel_scale_;
00152 
00153   // Scale each example
00154   for (unsigned i=0;i<n_shapes;++i)
00155     points_[i].scale_by(s);
00156 
00157   // Centre of scaled bounding box
00158   vgl_point_2d<double > bbox_c(bbox.centroid().x()*s,
00159                                bbox.centroid().y()*s);
00160 
00161   // Find translation to centre the box
00162   vgl_point_2d<double> view_centre(0.5*w_width,0.5*w_height);
00163   vgl_vector_2d<double> t=view_centre-bbox_c;
00164 
00165   // Translate each example
00166   // Assume each model centred on origin
00167   for (unsigned i=0;i<n_shapes;++i)
00168   {
00169     if (overlap_shapes_)
00170     {
00171       // Centre every example at field centre
00172       points_[i].translate_by(t.x(),t.y());
00173     }
00174     else
00175     {
00176       // Centre each example along a row
00177       points_[i].translate_by(t.x()+i*w_width,t.y());
00178     }
00179   }
00180 }
00181 
00182   //: Define current display window size
00183 void msm_shape_mode_view::set_display_window(const vgl_box_2d<int> & win)
00184 {
00185   display_win_ = win;
00186 
00187   if (shape_model_!=0)
00188     compute_shapes();
00189 }
00190 
00191     //: Define current mode to use
00192 void msm_shape_mode_view::set_mode(unsigned m)
00193 {
00194   if (shape_model_==0) return;
00195 
00196   if (m>=shape_model().n_modes()) m = shape_model().n_modes();
00197   mode_ = m;
00198 
00199   if (b_.size()!=mode_)
00200   {
00201     b_.set_size(mode_);
00202     for (unsigned i=0; i<mode_; ++i) b_(i) = 0.0;
00203   }
00204 
00205   compute_shapes();
00206 }
00207 
00208   //: Define number of shapes per mode
00209 void msm_shape_mode_view::set_n_per_mode(unsigned n)
00210 {
00211   if (n_per_mode_ == n) return;
00212   if (n<1) return;
00213 
00214   n_per_mode_ = n;
00215 
00216   compute_shapes();
00217 }
00218 
00219 //: Maximum number of shape modes available
00220 unsigned msm_shape_mode_view::max_modes() const
00221 {
00222   if (shape_model_==0)
00223     return 0;
00224   else
00225     return shape_model_->n_modes();
00226 }
00227 
00228 //: Set range (in units of SD)
00229 void  msm_shape_mode_view::set_range(double r)
00230 {
00231   sd_range_ = r;
00232   compute_shapes();
00233 }