00001
00063 #ifndef __IMPL_CLUSTER_CLASSIFIER_HPP__
00064 #define __IMPL_CLUSTER_CLASSIFIER_HPP__
00065
00066 #include "cob_3d_segmentation/cluster_classifier.h"
00067 #include <cob_3d_features/organized_normal_estimation.h>
00068
00069 #include <pcl/common/eigen.h>
00070
00071 #include <boost/tuple/tuple.hpp>
00072
00073 template <typename ClusterHandlerT, typename PointT, typename NormalT, typename LabelT> void
00074 cob_3d_segmentation::ClusterClassifier<ClusterHandlerT,PointT,NormalT,LabelT>::classifyOld()
00075 {
00076 ClusterPtr c_it, c_end;
00077 for ( boost::tie(c_it,c_end) = clusters_->getClusters(); c_it != c_end; ++c_it)
00078 {
00079 if ( c_it->size() < 5 ) continue;
00080 if ( c_it->type == I_EDGE || c_it->type == I_NAN || c_it->type == I_BORDER) continue;
00081
00082 clusters_->computeClusterComponents(c_it);
00083
00084 if (!c_it->is_planar_)
00085 {
00086
00087 recomputeClusterNormals(c_it);
00088 clusters_->computeCurvature(c_it);
00089 if (c_it->max_curvature < 0.02)
00090 c_it->type = I_PLANE;
00091 else if (c_it->max_curvature < 9.0 * c_it->min_curvature)
00092 c_it->type = I_SPHERE;
00093 else
00094 c_it->type = I_CYL;
00095
00096
00097 }
00098 else c_it->type = I_PLANE;
00099 }
00100 }
00101
00102 template <typename ClusterHandlerT, typename PointT, typename NormalT, typename LabelT> void
00103 cob_3d_segmentation::ClusterClassifier<ClusterHandlerT,PointT,NormalT,LabelT>::classify()
00104 {
00105 ClusterPtr c_it, c_end;
00106 float pc_min, pc_max;
00107 test.clear();
00108 test_plane.clear();
00109 test_cyl.clear();
00110 test_sph.clear();
00111 for ( boost::tie(c_it,c_end) = clusters_->getClusters(); c_it != c_end; ++c_it)
00112 {
00113 if ( c_it->size() < 5 ) continue;
00114 if ( c_it->type == I_EDGE || c_it->type == I_NAN || c_it->type == I_BORDER) continue;
00115
00116 clusters_->computeClusterComponents(c_it);
00117
00118 if (!c_it->is_planar_)
00119 {
00120 int w_size = std::min( std::floor(std::sqrt(c_it->size() / 16.0f)) + 5, 30.0f );
00121 int steps = std::floor(w_size / 5);
00122 int w_size_n = std::min( std::floor(std::sqrt(c_it->size() / 16.0f)) + 8, 30.0f );
00123 int steps_n = std::floor(w_size / 5);
00124 recomputeClusterNormals(c_it, w_size_n, steps_n);
00125 std::vector<int> geometry(NUM_LABELS, 0);
00126 int valid_points = 0;
00127 for (typename ClusterType::iterator idx=c_it->begin(); idx != c_it->end(); ++idx)
00128 {
00129 Eigen::Vector3f min_direction;
00130 if (!computeClusterPointCurvature(*idx, w_size, steps, pc_min, pc_max, min_direction))
00131 {
00132 test.push_back(*idx);
00133 continue;
00134 }
00135 ++valid_points;
00136
00137 if (pc_max < 0.01) { ++geometry[I_PLANE]; test_plane.push_back(*idx); }
00138 else if(pc_max > 9.0 * pc_min)
00139 {
00140 ++geometry[I_CYL];
00141 test_cyl.push_back(*idx);
00142 c_it->pca_inter_comp1 += min_direction;
00143 }
00144 else { ++geometry[I_SPHERE]; test_sph.push_back(*idx); }
00145 }
00146 c_it->pca_inter_comp1 = c_it->pca_inter_comp1.normalized();
00147 c_it->pca_inter_values(2) = 1.0;
00148
00149 int max = 0; size_t max_idx = 0;
00150 for (size_t i=0; i<geometry.size(); ++i)
00151 if ( (max=std::max(max,geometry[i])) == geometry[i] ) max_idx=i;
00152
00153 if (max == 0) { c_it->type = I_EDGE; }
00154 else
00155 {
00156 c_it->type = max_idx;
00157 c_it->type_probability = static_cast<float>(max) / static_cast<float>(valid_points);
00158
00159
00160 if(c_it->type_probability < 0.60) { c_it->type = I_SPHERE; }
00161
00162
00163
00164
00165
00166
00167
00168
00169 }
00170 }
00171 else c_it->type = I_PLANE;
00172 }
00173 }
00174
00175 template <typename ClusterHandlerT, typename PointT, typename NormalT, typename LabelT> void
00176 cob_3d_segmentation::ClusterClassifier<ClusterHandlerT,PointT,NormalT,LabelT>::recomputeClusterNormals(ClusterPtr c)
00177 {
00178 int w_size = std::min( std::floor(std::sqrt(c->size() / 16.0f)) + 5, 30.0f);
00179 int steps = std::floor(w_size / 5);
00180 recomputeClusterNormals(c, w_size, steps);
00181 }
00182
00183 template <typename ClusterHandlerT, typename PointT, typename NormalT, typename LabelT> void
00184 cob_3d_segmentation::ClusterClassifier<ClusterHandlerT,PointT,NormalT,LabelT>::recomputeClusterNormals(
00185 ClusterPtr c,
00186 int w_size,
00187 int steps)
00188 {
00189 clusters_->clearOrientation(c);
00190 for (typename ClusterType::iterator idx = c->begin(); idx != c->end(); ++ idx)
00191 {
00192 Eigen::Vector3f new_normal;
00193 cob_3d_features::OrganizedNormalEstimationHelper::computeSegmentNormal<PointT,LabelT>(
00194 new_normal, *idx, surface_, labels_, w_size, steps);
00195 normals_->points[*idx].getNormalVector3fMap() = new_normal;
00196 clusters_->updateNormal(c, new_normal);
00197 }
00198 }
00199
00200 template <typename ClusterHandlerT, typename PointT, typename NormalT, typename LabelT> bool
00201 cob_3d_segmentation::ClusterClassifier<ClusterHandlerT,PointT,NormalT,LabelT>::computeClusterPointCurvature(
00202 int index, int r, int steps, float& pc_min, float& pc_max, Eigen::Vector3f& pc_min_direction)
00203 {
00204 const int w = surface_->width, s = surface_->height * surface_->width;
00205 const int l_idx = labels_->points[index].label;
00206
00207
00208 const int w_rem = index%w;
00209 const int x_max = std::min(2*r, r + w - w_rem - 1);
00210 const int y_min = std::max(index - r*w - r, w_rem - r);
00211 const int y_max = std::min(index + r*w - r, s - (w - w_rem) - r);
00212
00213 const Eigen::Vector3f n_idx(normals_->points[index].normal);
00214 const Eigen::Matrix3f M = Eigen::Matrix3f::Identity() - n_idx * n_idx.transpose();
00215
00216 std::vector<Eigen::Vector3f> normals_projected;
00217 Eigen::Vector3f centroid = Eigen::Vector3f::Zero();
00218
00219 for (int y = y_min; y <= y_max; y += steps*w)
00220 {
00221 for (int idx = y; idx < y + x_max; idx+=steps)
00222 {
00223 if ( labels_->points[idx].label != l_idx ) { continue; }
00224 NormalT const* n_i = &(normals_->points[idx]);
00225 if ( pcl_isnan(n_i->normal[2]) ) continue;
00226 normals_projected.push_back( M * n_i->getNormalVector3fMap() );
00227 centroid += normals_projected.back();
00228 }
00229 }
00230 if (normals_projected.size() < 0.5 * pow(ceil(static_cast<float>(2*r+1)/static_cast<float>(steps)), 2)) { return false; }
00231 float num_p_inv = 1.0f / normals_projected.size();
00232 centroid *= num_p_inv;
00233 Eigen::Matrix3f cov = Eigen::Matrix3f::Zero();
00234 for (std::vector<Eigen::Vector3f>::iterator n_it = normals_projected.begin(); n_it != normals_projected.end(); ++n_it)
00235 {
00236 Eigen::Vector3f demean = *n_it - centroid;
00237 cov += demean * demean.transpose();
00238 }
00239 Eigen::Vector3f eigenvalues;
00240 Eigen::Matrix3f eigenvectors;
00241 pcl::eigen33(cov, eigenvectors, eigenvalues);
00242 pc_max = eigenvalues(2) * num_p_inv;
00243 pc_min = eigenvalues(1) * num_p_inv;
00244 pc_min_direction = eigenvectors.col(1);
00245 return true;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 #endif