Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include <limits>
00009 #include <vector>
00010 #include <boost/foreach.hpp>
00011 #define foreach BOOST_FOREACH
00012 #include "ros/ros.h"
00013 #include "pcl16/surface/convex_hull.h"
00014 #include "semanticmodel/blob.hh"
00015
00016 namespace semanticmodel
00017 {
00018 Blob::Blob(const PointCloud::ConstPtr& cluster)
00019 : cloud(new PointCloud(*cluster)), hull(new PointCloud()), id(next_id++)
00020 {
00021
00022
00023
00024
00025
00026 hull->header.frame_id = cloud->header.frame_id;
00027 hullerize(cluster);
00028 }
00029
00030 bool Blob::overlaps(const Blob& rhs) const
00031 {
00032 return oneSidedIntersect(hull, rhs.hull) ||
00033 oneSidedIntersect(rhs.hull, hull);
00034 }
00035
00036 void Blob::mergeFrom(const Blob& rhs)
00037 {
00038
00039 id = std::min(id, rhs.id);
00040 (*cloud) += *(rhs.cloud);
00041 (*hull) += *(rhs.hull);
00042 hullerize(hull);
00043 }
00044
00045 void Blob::RGB(float& r, float& g, float& b) const
00046 {
00047 r = g = b = 0.0;
00048 foreach(Point& p, *cloud)
00049 {
00050
00051 uint32_t rgb = *reinterpret_cast<int*>(&p.rgb);
00052 uint8_t rb = (rgb >> 16) & 0x0000ff;
00053 uint8_t gb = (rgb >> 8) & 0x0000ff;
00054 uint8_t bb = (rgb) & 0x0000ff;
00055
00056 r += rb / 255.0;
00057 g += gb / 255.0;
00058 b += bb / 255.0;
00059 }
00060
00061 r /= cloud->points.size();
00062 g /= cloud->points.size();
00063 b /= cloud->points.size();
00064 }
00065
00066 void Blob::size(double& x, double& y, double& z) const
00067 {
00068 float minx = cloud->points[0].x;
00069 float maxx = cloud->points[0].x;
00070 float miny = cloud->points[0].y;
00071 float maxy = cloud->points[0].y;
00072 float minz = cloud->points[0].z;
00073 float maxz = cloud->points[0].z;
00074 foreach(const Point& p, *cloud)
00075 {
00076 minx = std::min(minx, p.x);
00077 maxx = std::max(maxx, p.x);
00078 miny = std::min(miny, p.y);
00079 maxy = std::max(maxy, p.y);
00080 minz = std::min(minz, p.z);
00081 maxz = std::max(maxz, p.z);
00082 }
00083 x = maxx - minx;
00084 y = maxy - miny;
00085 z = maxz - minz;
00086 }
00087
00088
00089
00090 Blob::PointCloud::Ptr Blob::flatten(PointCloud::Ptr& in, double z)
00091 {
00092 PointCloud::Ptr res(new PointCloud(*in));
00093 foreach(Point& p, *res)
00094 p.z = z;
00095 return res;
00096 }
00097
00098 void Blob::MergeBlobWithSet(std::vector<Blob*>& objects, Blob* blob)
00099 {
00100
00101 objects.push_back(blob);
00102 while (MergeBlobWithSetHelper(objects)) {};
00103 }
00104
00105 bool Blob::MergeBlobWithSetHelper(std::vector<Blob*>& objects)
00106 {
00107 Blob* end = objects.back();
00108 for (size_t i = 0 ; i < objects.size() - 1 ; ++i)
00109 {
00110 if (objects[i]->overlaps(*end))
00111 {
00112 ROS_DEBUG_STREAM_NAMED ("merge_blobs", "Merging blob " << end->id <<
00113 " into " << objects[i]->id);
00114 objects[i]->mergeFrom(*end);
00115 delete end;
00116 objects.pop_back();
00117 std::swap(objects[i], objects.back());
00118 return true;
00119 }
00120 }
00121 return false;
00122 }
00123
00124
00125 void Blob::hullerize(const Blob::PointCloud::ConstPtr& cloud)
00126 {
00127 (*hull) += (*cloud);
00128 PointCloud::Ptr flat(Blob::flatten(hull, 0.0));
00129 pcl16::ConvexHull<Point> huller;
00130 huller.setInputCloud(flat);
00131 huller.setDimension(2);
00132 huller.reconstruct(*hull);
00133 }
00134
00135
00136 bool Blob::oneSidedIntersect(const Blob::PointCloud::ConstPtr& p1,
00137 const Blob::PointCloud::ConstPtr& p2) const
00138 {
00139 size_t n = p1->points.size();
00140 for (size_t i = 0 ; i < n ; ++i)
00141 {
00142 size_t j;
00143 if (i > 0)
00144 j = i - 1;
00145 else
00146 j = n - 1;
00147
00148 double min1, max1, min2, max2;
00149 projectOntoNormal(p1, p1->points[i], p1->points[j], min1, max1);
00150 projectOntoNormal(p2, p1->points[i], p1->points[j], min2, max2);
00151 if (max2 < min1 || max1 < min2)
00152 return false;
00153 }
00154 return true;
00155 }
00156
00157
00158 void Blob::projectOntoNormal(const Blob::PointCloud::ConstPtr& poly,
00159 const Point& q1, const Point& q2,
00160 double& inf, double& sup) const
00161 {
00162 Eigen::Vector2f d;
00163 d[0] = q2.x - q1.x;
00164 d[1] = q2.y - q1.y;
00165 Eigen::Vector2f perp(d[1], -d[0]);
00166 perp.normalize();
00167 inf = std::numeric_limits<double>::infinity();
00168 sup = std::numeric_limits<double>::infinity();
00169 foreach(const Point& p, *poly)
00170 {
00171 Eigen::Vector2f v(p.x, p.y);
00172 float proj = perp.dot(v);
00173 if (!pcl_isfinite(inf) || proj < inf)
00174 inf = proj;
00175 if (!pcl_isfinite(sup) || proj > sup)
00176 sup = proj;
00177 }
00178 assert (pcl_isfinite(inf));
00179 assert (pcl_isfinite(sup));
00180 }
00181
00182 unsigned int Blob::next_id = 0;
00183
00184 }