MTF
StateSpaceModel.h
1 #ifndef MTF_STATE_SPACE_MODEL_H
2 #define MTF_STATE_SPACE_MODEL_H
3 
4 #include "mtf/Macros/common.h"
5 #include "mtf/Utilities/excpUtils.h"
6 #include "SSMEstimatorParams.h"
7 
8 #define ssm_func_not_implemeted(func_name) \
9  throw mtf::utils::FunctonNotImplemented(cv::format("%s :: %s :: Not implemented Yet", name.c_str(), #func_name))
10 
11 #define validate_ssm_state(state_vec)\
12  assert(state_vec.size() == state_size)
13 
14 #define validate_ssm_jacobian(dI_dp, dI_dw)\
15  assert(dI_dp.rows() == n_pts*n_channels && dI_dp.cols() == state_size);\
16  assert(dI_dw.rows() == n_pts*n_channels)
17 
18 #define validate_ssm_hessian(d2I_dp2, d2I_dw2, dI_dw)\
19  assert(d2I_dp2.rows() == state_size*state_size && d2I_dp2.cols() == n_pts*n_channels);\
20  assert(dI_dw.rows() == n_pts*n_channels && d2I_dw2.cols() == n_pts*n_channels)
21 
22 _MTF_BEGIN_NAMESPACE
23 
24 struct SSMStatus{
25  bool pts, grad_pts, hess_pts, sampler;
26  SSMStatus(){ clear(); }
27  void set(){
28  pts = grad_pts = hess_pts = sampler = true;
29  }
30  void clear(){
31  pts = grad_pts = hess_pts = sampler = false;
32  }
33 };
34 
35 struct SSMParams{
37  int resx, resy;
38  SSMParams(int _resx, int _resy) :
39  resx(_resx), resy(_resy){}
40  SSMParams(const SSMParams *ssm_params = nullptr) :
41  resx(MTF_RES), resy(MTF_RES){
42  if(ssm_params){
43  resx = ssm_params->resx;
44  resy = ssm_params->resy;
45  }
46  }
47 };
48 
50 
51 public:
52  string name;
53 
54  StateSpaceModel(const SSMParams *params) :
55  resx(getResX(params)), resy(getResY(params)), n_pts(resx*resy),
56  state_size(0), identity_jacobian(false), first_iter(false),
57  spi_mask(nullptr){
58  if(resx == 0 || resy == 0) {
59  throw utils::InvalidArgument("StateSpaceModel::Invalid sampling resolution provided");
60  }
61  init_pts.resize(Eigen::NoChange, n_pts);
62  curr_pts.resize(Eigen::NoChange, n_pts);
63  }
64  virtual ~StateSpaceModel(){}
65 
66  // --------------------------------------------------------------- //
67  // ---------------------------accessors--------------------------- //
68  // --------------------------------------------------------------- //
69 
70  virtual unsigned int getStateSize(){ return state_size; }
71  virtual unsigned int getResX(){ return resx; }
72  virtual unsigned int getResY(){ return resy; }
73  virtual unsigned int getNPts(){ return n_pts; }
74  virtual unsigned int getNChannels(){ return n_channels; }
75 
76  virtual const PtsT& getPts(){ return curr_pts; }
77  virtual const CornersT& getCorners(){ return curr_corners; }
78  virtual const VectorXd& getState(){ return curr_state; }
79 
80  virtual const GradPtsT& getGradPts(){ return grad_pts; }
81  virtual const HessPtsT& getHessPts(){ return hess_pts; }
82 
83  // overloaded accessors that copy the current corners to the provided OpenCV structure
84  // rather than returning it in Eigen format
85  virtual void getCorners(cv::Point2d *cv_corners){
86  corners_to_points(cv_corners, curr_corners);
87  }
88  virtual void getCorners(cv::Mat &cv_corners){
89  corners_to_cv(cv_corners, curr_corners);
90  }
91  // --------------------------------------------------------------- //
92  // ---------------------------modifiers--------------------------- //
93  // --------------------------------------------------------------- //
94 
95  virtual void setNChannels(int _n_channels){ n_channels = _n_channels; }
96 
97  virtual void setState(const VectorXd &ssm_state){
98  ssm_func_not_implemeted(setState);
99  }
100 
101  // update the internal state so that the object location is set to the specified corners
102  virtual void setCorners(const CornersT& eig_corners){
103  ssm_func_not_implemeted(setCorners);
104  }
105  // overloaded variant to accept corners in OpenCV Mat format
106  virtual void setCorners(const cv::Mat& cv_corners){
107  CornersT eig_corners;
108  corners_from_cv(eig_corners, cv_corners);
109  setCorners(eig_corners);
110  }
111  // initialize the internal state variables; an alias for setCorners;
112  virtual void initialize(const CornersT& eig_corners, int _n_channels = 1){
113  setNChannels(_n_channels);
114  setCorners(eig_corners);
115  is_initialized.pts = true;
116  }
117  // overloaded function to let the user initialize SSM with corners in OpenCV format
118  virtual void initialize(const cv::Mat& cv_corners, int _n_channels = 1){
119  setNChannels(_n_channels);
120  setCorners(cv_corners);
121  is_initialized.pts = true;
122  }
123 
124  virtual void initializeGradPts(double grad_eps){
125  if(!is_initialized.grad_pts){
126  grad_pts.resize(Eigen::NoChange, n_pts);
127  }
128  updateGradPts(grad_eps);
129  is_initialized.grad_pts = true;
130  }
131  virtual void initializeHessPts(double hess_eps){
132  if(!is_initialized.hess_pts){
133  hess_pts.resize(Eigen::NoChange, n_pts);
134  }
135  updateHessPts(hess_eps);
136  is_initialized.hess_pts = true;
137  }
138  // functions to update internal state variables
139  virtual void additiveUpdate(const VectorXd& state_update){
140  ssm_func_not_implemeted(additiveUpdate);
141  }
142  virtual void compositionalUpdate(const VectorXd& state_update){
143  ssm_func_not_implemeted(compositionalUpdate);
144  }
145  virtual void updateGradPts(double grad_eps){
146  ssm_func_not_implemeted(updateGradPts);
147  }
148  virtual void updateHessPts(double hess_eps){
149  ssm_func_not_implemeted(updateHessPts);
150  }
151  // compute the state corresponding to the compositional inverse of the transformation
152  // described by the given state, i.e. W(inv_state, W(state, pts)) = pts
153  virtual void invertState(VectorXd& inv_state, const VectorXd& state){
154  ssm_func_not_implemeted(invertState);
155  }
156  virtual VectorXd invertState(const VectorXd& state){
157  VectorXd inv_state(getStateSize());
158  invertState(inv_state, state);
159  return inv_state;
160  }
161 
162  // --------------------------------------------------------------------------- //
163  // ---------------------------interfacing functions--------------------------- //
164  // --------------------------------------------------------------------------- //
165 
170  virtual void cmptInitPixJacobian(MatrixXd &jacobian_prod, const PixGradT &pixel_grad) {
171  ssm_func_not_implemeted(cmptInitPixJacobian);
172  }
173  virtual void cmptPixJacobian(MatrixXd &jacobian_prod, const PixGradT &pixel_grad){
174  ssm_func_not_implemeted(cmptPixJacobian);
175  }
176  virtual void cmptWarpedPixJacobian(MatrixXd &jacobian_prod, const PixGradT &pixel_grad) {
177  ssm_func_not_implemeted(cmptWarpedPixJacobian);
178  }
179  virtual void cmptApproxPixJacobian(MatrixXd &jacobian_prod, const PixGradT &pixel_grad) {
180  ssm_func_not_implemeted(cmptApproxPixJacobian);
181  }
182  virtual void cmptInitPixHessian(MatrixXd &pix_hess_ssm, const PixHessT &pix_hess_coord,
183  const PixGradT &pix_grad) {
184  ssm_func_not_implemeted(cmptInitPixHessian);
185  }
186  virtual void cmptPixHessian(MatrixXd &pix_hess_ssm, const PixHessT &pix_hess_coord,
187  const PixGradT &pix_grad) {
188  ssm_func_not_implemeted(cmptPixHessian);
189  }
190  virtual void cmptWarpedPixHessian(MatrixXd &pix_hess_ssm, const PixHessT &pix_hess_coord,
191  const PixGradT &pix_grad){
192  ssm_func_not_implemeted(cmptWarpedPixHessian);
193  }
194  virtual void cmptApproxPixHessian(MatrixXd &pix_hess_ssm, const PixHessT &pix_hess_coord,
195  const PixGradT &pix_grad) {
196  ssm_func_not_implemeted(cmptApproxPixHessian);
197  }
198 
199  // computes the warped corners generated by applying the warp corresponding to the given state vector to the given corners
200  virtual void applyWarpToCorners(CornersT &out_corners, const CornersT &in_corners,
201  const VectorXd &ssm_state){
202  ssm_func_not_implemeted(applyWarpToCorners);
203  }
204  virtual CornersT applyWarpToCorners(const CornersT &in_corners, const VectorXd &ssm_state){
205  CornersT out_corners;
206  applyWarpToCorners(out_corners, in_corners, ssm_state);
207  return out_corners;
208  }
209  virtual void applyWarpToCorners(cv::Mat &out_corners_cv, const cv::Mat &in_corners_cv,
210  const VectorXd &ssm_state){
211  CornersT out_corners, in_corners;
212  corners_from_cv(in_corners, in_corners_cv);
213  corners_from_cv(out_corners, out_corners_cv);
214  applyWarpToCorners(out_corners, in_corners, ssm_state);
215  }
216  virtual cv::Mat applyWarpToCorners(const cv::Mat &in_corners, const VectorXd &ssm_state){
217  cv::Mat out_corners(2, 4, CV_64FC1);
218  applyWarpToCorners(out_corners, in_corners, ssm_state);
219  return out_corners;
220  }
221  // computes the warped points generated by applying the warp corresponding to the given state vector to the given points
222  virtual void applyWarpToPts(PtsT &out_pts, const PtsT &in_pts,
223  const VectorXd &ssm_state){
224  ssm_func_not_implemeted(applyWarpToPts);
225  }
226  virtual PtsT applyWarpToPts(const PtsT &in_pts, const VectorXd &ssm_state){
227  PtsT out_pts;
228  out_pts.resize(Eigen::NoChange, in_pts.cols());
229  applyWarpToPts(out_pts, in_pts, ssm_state);
230  return out_pts;
231  }
232  // return SSM state vector p corresponding to the identity warp, i.e. S(x, p)=x;
233  virtual void getIdentityWarp(VectorXd &p){
234  ssm_func_not_implemeted(applyWarpToPts);
235  }
236  // compute SSM state vector p12 that corresponds to the composition of p1 and p2,
237  // i.e. S(x, p12) = S(S(x, p1), p2);
238  virtual void composeWarps(VectorXd &p12, const VectorXd &p1,
239  const VectorXd &p2){
240  ssm_func_not_implemeted(applyWarpToPts);
241  }
242 
243 
244  // estimates the state vector whose corresponding transformation, when applied to in_corners
245  // produces out_corners; if such a transformation is not exactly possible due to constraints
246  // on the SSM state, the resultant corners must be optimal in the least squares sense, i.e. their
247  // Euclidean distance from out_corners should be as small as possible while obeying these constraints
248  virtual void estimateWarpFromCorners(VectorXd &state_update, const CornersT &in_corners,
249  const CornersT &out_corners){
250  ssm_func_not_implemeted(estimateWarpFromCorners);
251  }
252  virtual VectorXd estimateWarpFromCorners(const CornersT &in_corners,
253  const CornersT &out_corners){
254  VectorXd state_update(getStateSize());
255  estimateWarpFromCorners(state_update, in_corners, out_corners);
256  return state_update;
257  }
258  // overloaded variant that takes OpenCV Mat instead
259  virtual void estimateWarpFromCorners(VectorXd &state_update, const cv::Mat &in_corners_cv,
260  const cv::Mat &out_corners_cv){
261  CornersT in_corners, out_corners;
262  corners_from_cv(in_corners, in_corners_cv);
263  corners_from_cv(out_corners, out_corners_cv);
264  estimateWarpFromCorners(state_update, in_corners, out_corners);
265  }
266  virtual VectorXd estimateWarpFromCorners(const cv::Mat &in_corners,
267  const cv::Mat &out_corners){
268  VectorXd state_update(getStateSize());
269  estimateWarpFromCorners(state_update, in_corners, out_corners);
270  return state_update;
271  }
273 
274  // estimates the state vector whose corresponding transformation, when applied to in_pts
275  // produces points that are best fit to out_pts according to estimation_method;
276  virtual void estimateWarpFromPts(VectorXd &state_update, vector<uchar> &mask,
277  const vector<cv::Point2f> &in_pts, const vector<cv::Point2f> &out_pts,
278  const EstimatorParams &est_params){
279  ssm_func_not_implemeted(estimateWarpFromPts);
280  }
281 
282  // -------------------------------------------------------------------------- //
283  // --------------------------- Stochastic Sampler --------------------------- //
284  // -------------------------------------------------------------------------- //
285 
286  virtual void initializeSampler(const VectorXd &state_sigma,
287  const VectorXd &state_mean){
288  ssm_func_not_implemeted(initializeSampler(VectorXd, VectorXd));
289  }
290  virtual void setSampler(const VectorXd &state_sigma,
291  const VectorXd &state_mean){
292  ssm_func_not_implemeted(setSampler);
293  }
294  virtual void setSamplerMean(const VectorXd &mean){
295  ssm_func_not_implemeted(setSamplerMean(VectorXd));
296  }
297  virtual void setSamplerSigma(const VectorXd &std){
298  ssm_func_not_implemeted(setSamplerSigma(VectorXd));
299  }
300  virtual VectorXd getSamplerSigma(){ ssm_func_not_implemeted(getSamplerSigma); }
301  virtual VectorXd getSamplerMean(){ ssm_func_not_implemeted(getSamplerMean); }
302 
303 
304  // use Random Walk model to generate perturbed sample
305  virtual void compositionalRandomWalk(VectorXd &perturbed_state, const VectorXd &base_state){
306  ssm_func_not_implemeted(compositionalRandomWalk);
307  }
308  virtual void additiveRandomWalk(VectorXd &perturbed_state, const VectorXd &base_state){
309  ssm_func_not_implemeted(additiveRandomWalk);
310  }
311  // use first order Auto Regressive model to generate perturbed sample
312  virtual void compositionalAutoRegression1(VectorXd &perturbed_state, VectorXd &perturbed_ar,
313  const VectorXd &base_state, const VectorXd &base_ar, double a = 0.5){
314  ssm_func_not_implemeted(compositionalAutoRegression1);
315  }
316  // use first order Auto Regressive model to generate perturbed sample
317  virtual void additiveAutoRegression1(VectorXd &perturbed_state, VectorXd &perturbed_ar,
318  const VectorXd &base_state, const VectorXd &base_ar, double a = 0.5){
319  ssm_func_not_implemeted(additiveAutoRegression1);
320  }
321  virtual void generatePerturbation(VectorXd &perturbation){
322  ssm_func_not_implemeted(generatePerturbation);
323  }
324  virtual void generatePerturbedPts(VectorXd &perturbed_pts){
325  ssm_func_not_implemeted(generatePerturbedPts);
326  }
327  virtual void getPerturbedPts(VectorXd &perturbed_pts,
328  const VectorXd &state_update){
329  ssm_func_not_implemeted(getPerturbedPts);
330  }
331 
332  virtual void estimateMeanOfSamples(VectorXd &sample_mean,
333  const std::vector<VectorXd> &samples, int n_samples){
334  ssm_func_not_implemeted(estimateMeanOfSamples);
335  }
336  virtual void estimateStateSigma(VectorXd &state_sigma, double pix_sigma){
337  ssm_func_not_implemeted(estimateStateSigma);
338  }
339 
340  // --------------------------------------------------------------------------- //
341  // ---------------------- miscellaneous functionality ---------------------- //
342  // --------------------------------------------------------------------------- //
343 
344  // gradient of the SSM w.r.t. its parameters computed at the given point
345  // can be used for estimating the change in SSM parameters needed to produce
346  // a required change in point coordinates in image space
347  virtual void getInitPixGrad(PtsT &jacobian_prod, int pix_id){
348  ssm_func_not_implemeted(getInitPixGrad);
349  }
350  virtual void getCurrPixGrad(PtsT &jacobian_prod, int pix_id){
351  ssm_func_not_implemeted(getCurrPixGrad);
352  }
353 
354  virtual void setInitStatus(){ is_initialized.set(); }
355  virtual void clearInitStatus(){ is_initialized.clear(); }
356 
357  //should be called before performing the first iteration on a new frame to indicate that the image
358  // that will subsequently be passed to the update functions is a new one, i.e. different from
359  // the one passed the last time these were called
360  virtual void setFirstIter(){ first_iter = true; }
361  //should be called after the first iteration on a new frame is done
362  virtual void clearFirstIter(){ first_iter = false; }
363 
364  virtual void setSPIMask(const bool *_spi_mask){ spi_mask = _spi_mask; }
365  virtual void clearSPIMask(){ spi_mask = nullptr; }
366  virtual bool supportsSPI(){ return false; }// should be overridden by an implementing class once
367  // it implements SPI functionality for all functions where it makes logical sense
368 
369  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
370 
371 protected:
372  const unsigned int resx, resy;
373  const unsigned int n_pts;
374 
375  unsigned int state_size;
376  unsigned int n_channels;
377 
379  VectorXd curr_state;
380 
384  PtsT init_pts, curr_pts;
385  CornersT init_corners, curr_corners;
386  GradPtsT grad_pts;
387  HessPtsT hess_pts;
388  bool identity_jacobian;
399  const bool *spi_mask;
400 
401 private:
402  unsigned int getResX(const SSMParams *params){
403  return params ? static_cast<unsigned int>(params->resx) : MTF_RES;
404  }
405  unsigned int getResY(const SSMParams *params){
406  return params ? static_cast<unsigned int>(params->resy) : MTF_RES;
407  }
408 };
409 _MTF_END_NAMESPACE
410 
411 #endif
Definition: StateSpaceModel.h:35
VectorXd curr_state
parameters defining the SSM state
Definition: StateSpaceModel.h:379
Definition: StateSpaceModel.h:49
PtsT init_pts
grid points and corners that define the object&#39;s location in the frame
Definition: StateSpaceModel.h:384
bool first_iter
indicator variable that can be set by the search method to indicate when a new frame has been acquire...
Definition: StateSpaceModel.h:398
Definition: StateSpaceModel.h:24
Definition: SSMEstimatorParams.h:9
int resx
horizontal and vertical sampling resolutions
Definition: StateSpaceModel.h:37
virtual void cmptInitPixJacobian(MatrixXd &jacobian_prod, const PixGradT &pixel_grad)
right multiplies the initial or current ssm jacobian with the provided am jacobian; though this can b...
Definition: StateSpaceModel.h:170
SSMStatus is_initialized
keep track of what state variables have been initialized
Definition: StateSpaceModel.h:392