KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
psi_likelihood.h
Go to the documentation of this file.
1 /* $Id: psi_likelihood.h 18278 2014-11-25 01:42:10Z ksimek $ */
2 /* {{{=========================================================================== *
3  |
4  | Copyright (c) 1994-2011 by Kobus Barnard (author)
5  |
6  | Personal and educational use of this code is granted, provided that this
7  | header is kept intact, and that the authorship is not misrepresented, that
8  | its use is acknowledged in publications, and relevant papers are cited.
9  |
10  | For other use contact the author (kobus AT cs DOT arizona DOT edu).
11  |
12  | Please note that the code in this file has not necessarily been adequately
13  | tested. Naturally, there is no guarantee of performance, support, or fitness
14  | for any particular task. Nonetheless, I am interested in hearing about
15  | problems that you encounter.
16  |
17  | Author: Kyle Simek
18  * =========================================================================== }}}*/
19 
20 // vim: tabstop=4 shiftwidth=4 foldmethod=marker
21 
22 #ifndef PSI_LIKELIHOOD
23 #define PSI_LIKELIHOOD
24 
25 
26 #include <m_cpp/m_matrix.h>
29 #include <prob_cpp/prob_pdf.h>
30 
32 #include <psi_cpp/psi_model.h>
33 #include <psi_cpp/psi_bbox.h>
34 #include <psi_cpp/psi_util.h>
35 
36 #ifdef KJB_HAVE_UA_CARTWHEEL
37 #include <Control/CapsuleState.h>
38 #include <Control/SimulationInterface.h>
39 #include <Control/ExtendedAction.h>
40 #include <Control/WrapperAction.h>
41 #include <Control/StartState.h>
42 #endif
43 
44 #include <boost/function.hpp>
45 
46 #include <vector>
47 #include <cmath>
48 
49 namespace kjb
50 {
51 namespace psi
52 {
53 
55 {
56 public:
58  double xy_sigma,
59  double width_sigma,
60  double height_sigma) :
61  xy_prob_(0.0, xy_sigma),
62  width_prob_(0.0, width_sigma),
63  height_prob_(0.0, height_sigma)
64  { }
65 
66  double operator()(const Bbox& data, const Bbox& model) const;
67 
68 private:
69  kjb::Normal_distribution xy_prob_;
70  kjb::Normal_distribution width_prob_;
71  kjb::Normal_distribution height_prob_;
72 };
73 
75 {
76 public:
78  double x_min,
79  double x_max,
80  double y_min,
81  double y_max,
82  double width_lambda,
83  double height_lambda) :
84  x_prob_(x_min, x_max),
85  y_prob_(y_min, y_max),
86  width_prob_(width_lambda),
87  height_prob_(height_lambda)
88  { }
89 
90 
91  double operator()(const Bbox& data) const;
92 private:
93 
96 
98  kjb::Exponential_distribution height_prob_;
99 };
100 
102 {
103 public:
105  size_t width,
106  size_t height,
107  const boost::function2<double, const Bbox&, const Bbox&>& pairwise_box_likelihood,
108  const boost::function1<double, const Bbox&>& noise_box_likelihood,
109  double p_noise
110  ) :
111  P_MISSING_SWITCH_POINT(0.3), // hard-coded; may need tweaking or fitting
112  P_MISSING_BASE_PROB(0.1), // hard-coded; may need tweaking
113  P_MISSING_SMOOTHNESS(0.1), // hard-coded; may need tweaking
114  p_noise_(p_noise),
115  pair_likelihood_(pairwise_box_likelihood),
116  noise_likelihood_(noise_box_likelihood),
117  frame_bounds_(kjb::Vector(0.0, 0.0), (double) width, (double) height),
118  marginalize_out_noise_(true)
119  {}
120 
129  double operator()(const std::vector<Bbox>& data_boxes, const std::vector<Bbox>& model_boxes) const
130  {
131  // TODO Somehow cache this and only update values that change with each iteration
132  const std::vector<double> m_p_missing = get_p_missing(model_boxes);
133 
134  kjb::Matrix affinities = get_affinity(data_boxes, model_boxes, m_p_missing);
135 
136 
137  std::vector<size_t> correspondences = get_correspondence_greedily(affinities);
138  return this->operator()(data_boxes, model_boxes, affinities, correspondences, m_p_missing);
139  }
140 
154  double compute_visibility(const std::vector<Bbox>& all_boxes, size_t box_i) const;
155 
157  double p_missing(double visibility) const
158  {
159  if(visibility < 0 || visibility > 1.0)
160  {
161  KJB_THROW_2(kjb::Illegal_argument, "Visibility must be in [0,1].");
162  }
163 
164  using kjb::cdf;
165 
166  // this is all hacked, and hand-tuned. Maybe we can fit a function from data at some point?
167 
168  // using normal cdf as a soft step function. sigma doesn't have any real meaning here, except the smoothness of the plot "looked okay" compared to the data. Need to investigate this more...
169 
170  const double mean = P_MISSING_SWITCH_POINT;
171  const double sigma = P_MISSING_SMOOTHNESS;
172 
173  const kjb::Normal_distribution normal_dist(mean, sigma);
174 
175  const double min = P_MISSING_BASE_PROB; // when no occlusion, miss detection 1% of the time, due to detector failure, or random occlusion from unmodelled objects
176 
177  const double obscured = 1-visibility;
178 
179  double result = log(min + (1-min) * cdf(normal_dist, obscured));
180 
181  return result;
182  }
183 
187  double p_correspondence(size_t num_data, size_t num_noise) const;
188 
192  std::vector<double> get_p_missing( const std::vector<Bbox>& model) const;
193 
195  const std::vector<Bbox>& data,
196  const std::vector<Bbox>& model) const
197  {
198  return get_affinity(data, model, get_p_missing(model));
199  }
200 
201  std::vector<size_t> get_correspondence_greedily( const kjb::Matrix& affinities) const;
202 
210  {
211  marginalize_out_noise_ = false;
212 
213  return *this;
214  }
215 
216 protected:
217  double operator()(
218  const std::vector<Bbox>& data_boxes,
219  const std::vector<Bbox>& models,
220  const kjb::Matrix& affinities,
221  const std::vector<size_t>& correspondences,
222  const std::vector<double>& m_p_missing) const;
223 
225  const std::vector<Bbox>& data,
226  const std::vector<Bbox>& model,
227  const std::vector<double>& m_p_missing
228  ) const;
229 
230 private:
231  // p_missing_center parameter, base parameter
232  const double P_MISSING_SWITCH_POINT; // this says how occluded a box can be before the detector misses it 50% of the time
233  const double P_MISSING_BASE_PROB; // probability of a miss when fully visible
234  const double P_MISSING_SMOOTHNESS; // how quickly the transition from zero to 1 occurs. setting this to zero gives a step function
235 
236  // p_noise bernoilli parameter
237  double p_noise_;
238 
239  // pair likelihood
240  boost::function2<double, const Bbox&, const Bbox&> pair_likelihood_;
241  // noise likelihood
242  boost::function1<double, const Bbox&> noise_likelihood_;
243 
244  Bbox frame_bounds_;
245 
246  // this describes how the transition between pairwise matches
247  // an noise models occurs. If true, the transition is smooth,
248  // because the noise model is "rolled into" the pairwise probability.
249  // If false, the correspondence can switch from being pairwise to being
250  // noise, which makes the likelihood demo more interesting, but offers
251  // little other benefit.
252  bool marginalize_out_noise_;
253 
254 };
255 
257 {
258 public:
259  virtual double operator()(const Model& m) const = 0;
260 };
261 
262 #ifdef KJB_HAVE_UA_CARTWHEEL
263 class Cartwheel_likelihood : public kjb::psi::Model_evaluator
264 {
265 public:
274  Cartwheel_likelihood(
275  const std::vector<std::vector<Bbox> >& data,
276  const kjb::Perspective_camera& cam,
277  const Frame_likelihood& frame_likelihood,
278  InterfacePtr interface,
279 // size_t width,
280 // size_t height,
281 // const boost::function2<double, const Bbox&, const Bbox&>& pairwise_box_likelihood,
282 // const boost::function1<double, const Bbox&>& noise_box_likelihood,
283 // double p_noise, // bernoulli noise process
284  double p_frame_count
285  ) :
286  data_(data),
287  cam_(cam),
288  interface_(interface),
289  frame_likelihood_(frame_likelihood),
290  frame_count_penalty_(p_frame_count)
291 // P_MISSING_SWITCH_POINT(0.6), // hard-coded; may need tweaking or fitting
292 // P_MISSING_BASE_PROB(0.01), // hard-coded; may need tweaking
293 // p_noise_(p_noise),
294 // noise_prob_(data_.size(), p_noise),
295 // pair_likelihood_(pairwise_box_likelihood),
296 // noise_likelihood_(noise_box_likelihood),
297 // frame_bounds_(kjb::Vector(0.0, 0.0), (double) width, (double) height)
298 //
299  { }
300 
301  virtual double operator()(const Model& m) const;
302 
303  std::vector<std::pair<double, Bbox> > blocks_to_boxes(const std::vector<CartWheel::BoxStatePtr>& box_state) const;
304 
305  std::vector<std::pair<double, Bbox> > capsules_to_boxes(const CartWheel::CapsuleState& capsule_state) const;
306 
307  std::vector<std::pair<double, Bbox> > capsules_to_boxes(const std::vector<std::vector<CartWheel::Math::Capsule*> >& actors_capsules) const;
308 
322 // double compute_visibility(const std::vector<Bbox>& all_boxes, size_t box_i) const;
323 
324 
325 private:
326  const std::vector<std::vector<Bbox> >& data_;
328  mutable InterfacePtr interface_;
329 
330  Frame_likelihood frame_likelihood_;
331 
332  // penalty for requesting too many or too few frames
333  kjb::Geometric_distribution frame_count_penalty_;
334 };
335 #endif
336 
338 {
339 public:
349  boost::shared_ptr<std::vector<std::vector<std::vector<Bbox> > > > data,
350  const kjb::Perspective_camera& cam,
351  const Frame_likelihood& frame_likelihood,
352  const Simple_simulator& sim,
353  double p_frame_count
354  ) :
355  data_(data),
356  cam_(cam),
357  simulator_(sim),
358  frame_likelihood_(frame_likelihood),
359  frame_count_penalty_(p_frame_count),
360  num_frames_(0)
361  {
362 
363  for(size_t i = 0; i < data_->size(); i++)
364  {
365  if((*data_)[i].size() == 0) continue;
366 
367  if(num_frames_ == 0)
368  num_frames_ = (*data_).size();
369  else
370  {
371  if(num_frames_ != (*data_).size())
372  KJB_THROW_2(Illegal_argument, "Number of data frames must be equal for all object types.");
373  }
374  }
375 
376  assert(num_frames_ > 0);
377  }
378 
379  virtual double operator()(const Model& m) const;
380 
382  std::vector<std::pair<double, Bbox> > blocks_to_boxes(const std::vector<Cuboid>& blocks) const;
383 
385  std::vector<std::pair<double, Bbox> > entities_to_boxes(const std::vector<std::vector<Entity_state> >& entities) const;
386 
387 private:
388  boost::shared_ptr<std::vector<std::vector<std::vector<Bbox> > > > data_;
390  mutable Simple_simulator simulator_;
391 
392  Frame_likelihood frame_likelihood_;
393 
394  // penalty for requesting too many or too few frames
395  kjb::Geometric_distribution frame_count_penalty_;
396  size_t num_frames_;
397 };
398 
399 
400 inline std::vector<Bbox> sort_by_depth(std::vector<std::pair<double, Bbox> >& boxes);
401 
402 } // namespace psi
403 } // namespace kjb
404 #endif
Definition: psi_likelihood.h:101
double operator()(const std::vector< Bbox > &data_boxes, const std::vector< Bbox > &model_boxes) const
Definition: psi_likelihood.h:129
Bbox_noise_likelihood(double x_min, double x_max, double y_min, double y_max, double width_lambda, double height_lambda)
Definition: psi_likelihood.h:77
double operator()(const Bbox &data, const Bbox &model) const
Definition: psi_likelihood.cpp:126
Definition for the Matrix class, a thin wrapper on the KJB Matrix struct and its related functionalit...
Class that represents an axis-aligned 2D rectangle. It is defined in terms of its (2D) center...
Definition: gr_2D_bounding_box.h:51
Definition of various standard probability distributions.
kjb::Matrix get_affinity(const std::vector< Bbox > &data, const std::vector< Bbox > &model) const
Definition: psi_likelihood.h:194
std::vector< Bbox > sort_by_depth(std::vector< std::pair< double, Bbox > > &boxes)
Definition: psi_likelihood.cpp:109
std::vector< std::pair< double, Bbox > > blocks_to_boxes(const std::vector< Cuboid > &blocks) const
convert 3d blocks into 2d bounding boxes, with depths from camera
Definition: psi_likelihood.h:337
Frame_likelihood(size_t width, size_t height, const boost::function2< double, const Bbox &, const Bbox & > &pairwise_box_likelihood, const boost::function1< double, const Bbox & > &noise_box_likelihood, double p_noise)
Definition: psi_likelihood.h:104
Cylinder_world_likelihood(boost::shared_ptr< std::vector< std::vector< std::vector< Bbox > > > > data, const kjb::Perspective_camera &cam, const Frame_likelihood &frame_likelihood, const Simple_simulator &sim, double p_frame_count)
Definition: psi_likelihood.h:348
height
Definition: APPgetLargeConnectedEdges.m:33
double p_correspondence(size_t num_data, size_t num_noise) const
Definition: psi_likelihood.cpp:536
This class implements vectors, in the linear-algebra sense, with real-valued elements.
Definition: m_vector.h:87
Value_type mean(Iterator begin, Iterator end, const Value_type &)
Definition: prob_stat.h:56
Definition: psi_likelihood.h:54
St_perspective_camera for modeling a perspective camera using the classic Forsyth and Ponce parametri...
double p_missing(double visibility) const
Definition: psi_likelihood.h:157
boost::math::exponential Exponential_distribution
Definition: prob_distribution.h:64
PDFs and CDFs for the different distributions defined in "prob_distribution.h".
Definition: perspective_camera.h:93
Definition: psi_cylinder_world.h:133
Definition: prob_distribution.h:79
Frame_likelihood & dont_marginalize_noise()
Definition: psi_likelihood.h:209
Definition: psi_likelihood.h:256
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
double compute_visibility(const std::vector< Bbox > &all_boxes, size_t box_i) const
Definition: psi_likelihood.cpp:364
Int_matrix::Value_type min(const Int_matrix &mat)
Return the minimum value in this matrix.
Definition: l_int_matrix.h:1385
boost::math::normal Normal_distribution
Definition: prob_distribution.h:68
double cdf(const Log_normal_distribution &dist, double x)
Computes the cdf of a log-normal distribution at x.
Definition: prob_pdf.h:151
Object thrown when an argument to a function is not acceptable.
Definition: l_exception.h:377
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
virtual double operator()(const Model &m) const
Definition: psi_likelihood.cpp:693
This class implements matrices, in the linear-algebra sense, with real-valued elements.
Definition: m_matrix.h:94
boost::math::uniform Uniform_distribution
Definition: prob_distribution.h:70
for m
Definition: APPgetLargeConnectedEdges.m:64
virtual double operator()(const Model &m) const =0
std::vector< size_t > get_correspondence_greedily(const kjb::Matrix &affinities) const
Definition: psi_likelihood.cpp:621
double operator()(const Bbox &data) const
Definition: psi_likelihood.cpp:178
std::vector< std::pair< double, Bbox > > entities_to_boxes(const std::vector< std::vector< Entity_state > > &entities) const
convert 3d entities into 2d bounding boxes, with depths from camera
Definition: psi_likelihood.cpp:782
Bbox_pairwise_likelihood(double xy_sigma, double width_sigma, double height_sigma)
Definition: psi_likelihood.h:57
Definition: psi_likelihood.h:74
Definition: psi_model.h:62
std::vector< double > get_p_missing(const std::vector< Bbox > &model) const
Definition: psi_likelihood.cpp:553