Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef SKELETON_CLOUD_MEASURE_H
00017 #define SKELETON_CLOUD_MEASURE_H
00018
00019 #include "skeleton_state.h"
00020 #include "auxil.h"
00021 #include "options.h"
00022 #include "math_types.h"
00023 #include "kinect_cloud.h"
00024 #include "point_cloud.h"
00025 #include "triclops_cloud.h"
00026
00027 inline
00028 bool nearest_bone_point (const vector3 &p, const_bone_iter iter,
00029 vector3 &result, const vector3 &root)
00030 {
00031 bool is_end_point = true;
00032 const vector3 a = iter->absolute ().T () + root;
00033 const vector3 b = iter->parent ()->absolute ().T () + root;
00034
00035 const double len2 = iter->get_length2 ();
00036 const vector3 bma = (b - a);
00037 const double t = -((a - p) * bma) / len2;
00038
00039 if (t < 0)
00040 {
00041 result = a;
00042 }
00043 else if (t > 1)
00044 {
00045 result = b;
00046 }
00047 else
00048 {
00049 result = a + t * bma;
00050 is_end_point = false;
00051 }
00052
00053 return is_end_point;
00054 }
00055
00056 inline
00057 double point_bone_distance2 (const vector3 &p, const_bone_iter iter, const vector3 &root)
00058 {
00059 vector3 nearest;
00060 nearest_bone_point (p, iter, nearest, root);
00061 const double retval = norm2 (nearest - p);
00062
00063 return retval;
00064 }
00065
00082 template <class state_type, class observation_type>
00083 class measure
00084 {
00085 public:
00093 measure (const options &opts, const calibration &_calib)
00094 : threshold2 (square (opts.measure_threshold ())),
00095 variance (opts.measure_variance ()),
00096 calib (_calib),
00097 cam (calib.camera_centre ())
00098 {
00099 };
00100
00101
00102 #define POINT_HALF_CAPSULE_DISTANCE
00103
00104
00105
00118 double log_measure (state_type &state, const observation_type &observation) const
00119 {
00120
00121 state.compute_pose ();
00122 const vector3 root = state.get_root ();
00123
00124 double mean = 0;
00125 const size_t num_points = observation.size ();
00126 for (size_t idx = 0; idx < num_points; idx++)
00127 {
00128 #ifdef ELLIPSOIDAL_DISTANCE_2
00129 double sum = 0;
00130 #else
00131 double min = threshold2;
00132 #endif // ELLIPSOIDAL_DISTANCE_2
00133
00134 const vector3 p = observation [idx];
00135 for (const_bone_iter iter = state.bone_begin (); iter != state.bone_end (); iter++)
00136 {
00137 if (!iter->is_root ())
00138 {
00139 #ifdef POINT_CAPSULE_DISTANCE
00140
00141 const double d2 = point_bone_distance2 (p, iter, root);
00142 const double r = iter->get_width ();
00143 const double dist = square (sqrt (d2) - r);
00144
00145 if (dist < min) min = dist;
00146 #endif // POINT_CAPSULE_DISTANCE
00147
00148
00149 #ifdef POINT_HALF_CAPSULE_DISTANCE
00150 const double dist = point_half_cylinder_distance2 (p, iter, root, min);
00151 if (dist < min) min = dist;
00152 #endif // POINT_HALF_CAPSULE_DISTANCE
00153
00154
00155 #ifdef ELLIPSOIDAL_DISTANCE_1
00156 ellipsoid E;
00157 double dist = threshold2;
00158 if (state.bone_to_ellipsoid (iter, E))
00159 {
00160 vector3 on_ellipsoid;
00161 E.project_point (p, on_ellipsoid);
00162 dist = std::min (E.euc_mahalanobis2 (p, on_ellipsoid), threshold2);
00163 }
00164
00165 if (dist < min) min = dist;
00166 #endif // ELLIPSOIDAL_DISTANCE_1
00167
00168
00169 #ifdef ELLIPSOIDAL_DISTANCE_2
00170 ellipsoid E;
00171 if (state.bone_to_ellipsoid (iter, E))
00172 {
00173 vector3 on_ellipsoid;
00174 E.project_point (p, on_ellipsoid);
00175 const double dist2 = std::min (E.euc_mahalanobis2 (p, on_ellipsoid), threshold2);
00176
00177 sum += exp (-dist2);
00178 }
00179 #endif // ELLIPSOIDAL_DISTANCE_2
00180 }
00181 }
00182
00183 #ifdef ELLIPSOIDAL_DISTANCE_2
00184 mean += log (sum);
00185 #else
00186 mean += min;
00187 #endif // ELLIPSOIDAL_DISTANCE_2
00188 }
00189
00190 mean /= (double)num_points;
00191
00192 #ifdef ELLIPSOIDAL_DISTANCE_2
00193 const double retval = mean / variance;
00194 #else
00195 const double retval = -0.5 * mean / variance;
00196 #endif // ELLIPSOIDAL_DISTANCE_2
00197
00198
00199 return (retval);
00200 }
00201
00202 private:
00203 double point_half_cylinder_distance2 (const vector3 &p, const_bone_iter iter,
00204 const vector3 &root, const double thresh) const
00205 {
00206 vector3 on_bone;
00207 const bool is_end_point = nearest_bone_point (p, iter, on_bone, root);
00208
00209
00210
00211 const double r = iter->get_width ();
00212 const double d = sqrt (norm2 (p - on_bone));
00213 double retval = square (d - r);
00214
00215
00216
00217 if (!is_end_point && retval < thresh )
00218 {
00219 const vector3 v1 = unit (cam - on_bone);
00220 const vector3 v2 = unit (p - on_bone);
00221 const double dot = (v1 * v2);
00222
00223
00224 if (dot < 0)
00225 {
00226
00227
00228
00229 const vector3 a = iter->absolute ().T () + root;
00230 const vector3 b = iter->parent ()->absolute ().T () + root;
00231
00232 const vector3 bone = unit (b - a);
00233 const vector3 v3 = r * unit (v1 % bone);
00234 const vector3 p1 = on_bone + v3;
00235 const vector3 p2 = on_bone - v3;
00236 const double dp1 = norm2 (p - p1);
00237 const double dp2 = norm2 (p - p2);
00238 retval = std::min (dp1, dp2);
00239 }
00240 }
00241 return retval;
00242 }
00243
00244 protected:
00245 const double threshold2;
00246 const double variance;
00247 const calibration &calib;
00248 const vector3 cam;
00249 };
00250
00251 #endif // SKELETON_CLOUD_MEASURE_H
00252