Go to the documentation of this file.00001
00063 #ifndef __COB_3D_SEGMENTATION_CLUSTER_HANDLER_H__
00064 #define __COB_3D_SEGMENTATION_CLUSTER_HANDLER_H__
00065
00066 #include <cob_3d_mapping_common/point_types.h>
00067 #include <cob_3d_mapping_common/label_defines.h>
00068 #include "cob_3d_segmentation/cluster_types.h"
00069
00070 #include <list>
00071 #include <iomanip>
00072
00073 #include <pcl/point_cloud.h>
00074 #include <pcl/point_types.h>
00075 #include <pcl/common/eigen.h>
00076
00077
00078 namespace cob_3d_segmentation
00079 {
00080 template<typename ClusterT>
00081 class ClusterHandlerBase
00082 {
00083 public:
00084 typedef ClusterT ClusterType;
00085 typedef typename std::list<ClusterT>::iterator ClusterPtr;
00086 typedef typename std::list<ClusterT>::reverse_iterator reverse_iterator;
00087 typedef typename std::list<ClusterT>::size_type size_type;
00088
00089 public:
00090 ClusterHandlerBase() : clusters_()
00091 , id_to_cluster_()
00092 , max_cid_(0)
00093 , color_tab_()
00094 {
00095 const float rand_max_inv = 1.0f/ RAND_MAX;
00096
00097 for (size_t i=0; i<2048; ++i)
00098 {
00099 int r = (float)rand() * rand_max_inv * 255;
00100 int g = (float)rand() * rand_max_inv * 255;
00101 int b = (float)rand() * rand_max_inv * 255;
00102 color_tab_.push_back( r << 16 | g << 8 | b );
00103 }
00104 }
00105 virtual ~ClusterHandlerBase() { };
00106
00107 inline ClusterPtr begin() { return clusters_.begin(); }
00108 inline ClusterPtr end() { return clusters_.end(); }
00109 inline reverse_iterator rbegin() { return clusters_.rbegin(); }
00110 inline reverse_iterator rend() { return clusters_.rend(); }
00111 inline std::pair<ClusterPtr,ClusterPtr> getClusters()
00112 { return std::make_pair(clusters_.begin(),clusters_.end()); }
00113 inline std::pair<reverse_iterator, reverse_iterator> getClustersReverse()
00114 { return std::make_pair(clusters_.rbegin(), clusters_.rend()); }
00115
00116 inline size_type numClusters() const { return clusters_.size(); }
00117 inline void sortBySize() { clusters_.sort(); }
00118 virtual void clear() { clusters_.clear(); id_to_cluster_.clear(); max_cid_ = 0; }
00119 virtual void erase(ClusterPtr c) { clusters_.erase(c); }
00120
00121 inline ClusterPtr getCluster(const int id)
00122 {
00123 return ( (id_to_cluster_.find(id) == id_to_cluster_.end())
00124 ? clusters_.end()
00125 : id_to_cluster_.find(id)->second );
00126 }
00127
00128 inline ClusterPtr createCluster(int id = 0)
00129 {
00130 clusters_.push_back(ClusterType( (id<=max_cid_ ? ++max_cid_ : max_cid_ = id) ));
00131 return (id_to_cluster_[max_cid_] = --clusters_.end());
00132 }
00133
00134 std::string colorHumanReadable(int id)
00135 {
00136 std::stringstream ss;
00137 ss << "0x" << std::setfill('0') << std::setw(6) << std::right
00138 << std::hex << id << std::dec;
00139 return ss.str();
00140 }
00141
00142 void mapClusterColor(pcl::PointCloud<PointXYZRGB>::Ptr color_cloud)
00143 {
00144 uint32_t rgb; int t = 0;
00145 for(reverse_iterator c = clusters_.rbegin(); c != clusters_.rend(); ++c, ++t)
00146 {
00147 if (c->id() == I_NAN) { rgb = LabelColorMap::m.at(I_NAN); }
00148 else if (c->id() == I_BORDER) { rgb = LabelColorMap::m.at(I_BORDER); }
00149 else { rgb = color_tab_[t]; }
00150 for(typename ClusterType::iterator it = c->begin(); it != c->end(); ++it)
00151 { color_cloud->points[*it].rgb = *reinterpret_cast<float*>(&rgb); }
00152 c->label_color = rgb;
00153 }
00154 }
00155
00156 void mapTypeColor(pcl::PointCloud<PointXYZRGB>::Ptr color_cloud)
00157 {
00158 uint32_t rgb;
00159 for(ClusterPtr c = clusters_.begin(); c != clusters_.end(); ++c)
00160 {
00161 rgb = LabelColorMap::m.at(c->type);
00162 for (typename ClusterType::iterator it = c->begin(); it != c->end(); ++it)
00163 color_cloud->points[*it].rgb = *reinterpret_cast<float*>(&rgb);
00164 }
00165 }
00166
00167 virtual void addPoint(ClusterPtr c, int idx) = 0;
00168 virtual void merge(ClusterPtr source, ClusterPtr target) = 0;
00169
00170 protected:
00171 std::list<ClusterType> clusters_;
00172 std::map<int,ClusterPtr> id_to_cluster_;
00173 int max_cid_;
00174 std::vector<int> color_tab_;
00175 };
00176
00177
00178 template<typename LabelT, typename PointT, typename PointNT>
00179 class DepthClusterHandler : public ClusterHandlerBase<DepthCluster>
00180 {
00181 public:
00182 typedef boost::shared_ptr<DepthClusterHandler<LabelT,PointT,PointNT> > Ptr;
00183
00184 typedef pcl::PointCloud<LabelT> LabelCloud;
00185 typedef typename LabelCloud::Ptr LabelCloudPtr;
00186 typedef pcl::PointCloud<PointT> PointCloud;
00187 typedef typename PointCloud::ConstPtr PointCloudConstPtr;
00188 typedef pcl::PointCloud<PointNT> NormalCloud;
00189 typedef typename NormalCloud::ConstPtr NormalCloudConstPtr;
00190
00191 public:
00192 DepthClusterHandler()
00193 { };
00194 ~DepthClusterHandler() { };
00195
00196 void addPoint(ClusterPtr c, int idx)
00197 {
00198 c->addIndex(idx);
00199 c->sum_points_ += surface_->points[idx].getVector3fMap();
00200 c->sum_orientations_ += normals_->points[idx].getNormalVector3fMap();
00201 c->sum_rgb_(0) += surface_->points[idx].r;
00202 c->sum_rgb_(1) += surface_->points[idx].g;
00203 c->sum_rgb_(2) += surface_->points[idx].b;
00204 c->color_.addColor(surface_->points[idx].r,
00205 surface_->points[idx].g,
00206 surface_->points[idx].b);
00207 }
00208
00209 inline void updateNormal(ClusterPtr c, const Eigen::Vector3f& normal) const
00210 {
00211 c->sum_orientations_ += normal;
00212 }
00213
00214 inline void clearOrientation(ClusterPtr c) const
00215 {
00216 c->sum_orientations_ = Eigen::Vector3f::Zero();
00217 }
00218
00219 inline void merge(ClusterPtr source, ClusterPtr target)
00220 {
00221 for (ClusterType::iterator idx = source->begin(); idx != source->end(); ++idx)
00222 {
00223 addPoint(target, *idx);
00224 labels_->points[*idx].label = target->id();
00225 }
00226 erase(source);
00227 }
00228
00229 inline void setLabelCloudInOut(LabelCloudPtr labels) { labels_ = labels; }
00230 inline void setPointCloudIn(PointCloudConstPtr points) { surface_ = points; }
00231 inline void setNormalCloudIn(NormalCloudConstPtr normals) { normals_ = normals; }
00232
00233 void computeClusterComponents(ClusterPtr c);
00234 void computeCurvature(ClusterPtr c);
00235 void computePointCurvature(ClusterPtr c, int search_size);
00236 bool computePrincipalComponents(ClusterPtr c);
00237 void computeNormalIntersections(ClusterPtr c);
00238
00239
00240 void addBorderIndicesToClusters()
00241 {
00242 int w = labels_->width;
00243 int mask[] = { -w, 1, w, -1 };
00244 int curr_label, count;
00245
00246 for (size_t y = w; y < labels_->size() - w; y+=w)
00247 {
00248
00249 for (size_t i=y+1; i < y+w-1; ++i)
00250 {
00251 curr_label = (*labels_)[i].label;
00252 if(curr_label == I_NAN) continue;
00253 count = 0;
00254 for (int m=0; m<4; ++m) count += (curr_label != (*labels_)[ i+mask[m] ].label);
00255 if(count >= 4 || count < 1) continue;
00256 id_to_cluster_[curr_label]->border_points.push_back(PolygonPoint(i%w,i/w));
00257 }
00258 }
00259 }
00260
00261 void mapClusterBorders(pcl::PointCloud<pcl::PointXYZRGB>::Ptr points)
00262 {
00263
00264 for (ClusterPtr c = clusters_.begin(); c != clusters_.end(); ++c)
00265 {
00266 for(std::vector<PolygonPoint>::iterator bp = c->border_points.begin();
00267 bp != c->border_points.end(); ++bp)
00268 {
00269 points->points[bp->y*points->width+bp->x].rgb = LBL_BORDER;
00270 }
00271 }
00272 }
00273
00274 void mapClusterNormalIntersectionResults(
00275 pcl::PointCloud<pcl::PointXYZ>::Ptr ints_centroids,
00276 pcl::PointCloud<pcl::Normal>::Ptr comp1,
00277 pcl::PointCloud<pcl::Normal>::Ptr comp2,
00278 pcl::PointCloud<pcl::Normal>::Ptr comp3,
00279 pcl::PointCloud<pcl::PointXYZ>::Ptr centroids,
00280 pcl::PointCloud<pcl::Normal>::Ptr connection)
00281 {
00282 ints_centroids->width = comp1->width = comp2->width = comp3->width
00283 = centroids->width = connection->width = numClusters();
00284 ints_centroids->height = comp1->height = comp2->height = comp3->height
00285 = centroids->width = connection->height = 1;
00286 ints_centroids->resize(numClusters());
00287 comp1->resize(numClusters());
00288 comp2->resize(numClusters());
00289 comp3->resize(numClusters());
00290 centroids->resize(numClusters());
00291 connection->resize(numClusters());
00292
00293 int i = 0;
00294 for (ClusterPtr c = clusters_.begin(); c != clusters_.end(); ++c)
00295 {
00296 if (c->type != I_CYL) continue;
00297 ints_centroids->points[i].getVector3fMap() = c->pca_inter_centroid;
00298 comp1->points[i].getNormalVector3fMap()
00299 = c->pca_inter_comp1 * c->pca_inter_values(2);
00300 comp2->points[i].getNormalVector3fMap()
00301 = c->pca_inter_comp2 * c->pca_inter_values(1);
00302 comp3->points[i].getNormalVector3fMap()
00303 = c->pca_inter_comp3 * c->pca_inter_values(0);
00304 centroids->points[i].getVector3fMap() = c->getCentroid();
00305 connection->points[i].getNormalVector3fMap()
00306 = c->pca_inter_centroid - c->getCentroid();
00307 ++i;
00308 }
00309 }
00310
00311 private:
00312 LabelCloudPtr labels_;
00313 PointCloudConstPtr surface_;
00314 NormalCloudConstPtr normals_;
00315 };
00316
00317 }
00318
00319 #endif