21 #include <pcl/common/time.h> 22 #include <pcl/filters/voxel_grid.h> 171 out << v3normal(0) << v3normal(1) << v3normal(2);
172 out << v3center(0) << v3center(1) << v3center(2);
173 out << v3PpalDir(0) << v3PpalDir(1) << v3PpalDir(2);
174 out << v3colorNrgb(0) << v3colorNrgb(1) << v3colorNrgb(2);
176 out << dominantIntensity;
177 out << bDominantColor;
188 out << label_context;
202 out << (
uint32_t)polygonContourPtr->size();
203 for (
uint32_t i=0; i < polygonContourPtr->size(); i++)
204 out << polygonContourPtr->points[i].x << polygonContourPtr->points[i].y << polygonContourPtr->points[i].z;
266 in >> v3normal(0) >> v3normal(1) >> v3normal(2);
267 in >> v3center(0) >> v3center(1) >> v3center(2);
268 in >> v3PpalDir(0) >> v3PpalDir(1) >> v3PpalDir(2);
269 d = -v3normal.dot(v3center);
270 in >> v3colorNrgb(0) >> v3colorNrgb(1) >> v3colorNrgb(2);
272 in >> dominantIntensity;
273 in >> bDominantColor;
305 polygonContourPtr->resize(
n);
306 for (
unsigned i=0; i <
n; i++)
307 in >> polygonContourPtr->points[i].x >> polygonContourPtr->points[i].y >> polygonContourPtr->points[i].z;
324 const double D = -(v3normal.dot(v3center));
325 for(
unsigned i = 0; i < planePointCloudPtr->size(); i++)
327 double dist = v3normal[0]*planePointCloudPtr->points[i].x + v3normal[1]*planePointCloudPtr->points[i].y + v3normal[2]*planePointCloudPtr->points[i].z + D;
328 planePointCloudPtr->points[i].x -= v3normal[0] * dist;
329 planePointCloudPtr->points[i].y -= v3normal[1] * dist;
330 planePointCloudPtr->points[i].z -= v3normal[2] * dist;
333 for(
unsigned i = 0; i < polygonContourPtr->size(); i++)
335 double dist = v3normal[0]*polygonContourPtr->points[i].x + v3normal[1]*polygonContourPtr->points[i].y + v3normal[2]*polygonContourPtr->points[i].z + D;
336 polygonContourPtr->points[i].x -= v3normal[0] * dist;
337 polygonContourPtr->points[i].y -= v3normal[1] * dist;
338 polygonContourPtr->points[i].z -= v3normal[2] * dist;
350 k0 = (fabs (v3normal[0] ) > fabs (v3normal[1])) ? 0 : 1;
351 k0 = (fabs (v3normal[k0]) > fabs (v3normal[2])) ? k0 : 2;
356 float ct = fabs ( v3normal[k0] );
358 float p_i[3], p_j[3];
360 for (
unsigned int i = 0; i < polygonContourPtr->points.size (); i++)
362 p_i[0] = polygonContourPtr->points[i].x; p_i[1] = polygonContourPtr->points[i].y; p_i[2] = polygonContourPtr->points[i].z;
363 int j = (i + 1) % polygonContourPtr->points.size ();
364 p_j[0] = polygonContourPtr->points[j].x; p_j[1] = polygonContourPtr->points[j].y; p_j[2] = polygonContourPtr->points[j].z;
366 AreaX2 += p_i[k1] * p_j[k2] - p_i[k2] * p_j[k1];
368 AreaX2 = fabs (AreaX2) / (2 * ct);
380 k0 = (fabs (v3normal[0] ) > fabs (v3normal[1])) ? 0 : 1;
381 k0 = (fabs (v3normal[k0]) > fabs (v3normal[2])) ? k0 : 2;
386 float ct = fabs ( v3normal[k0] );
388 Eigen::Vector3f massCenter = Eigen::Vector3f::Zero();
389 float p_i[3], p_j[3];
391 for (
unsigned int i = 0; i < polygonContourPtr->points.size (); i++)
393 p_i[0] = polygonContourPtr->points[i].x; p_i[1] = polygonContourPtr->points[i].y; p_i[2] = polygonContourPtr->points[i].z;
394 int j = (i + 1) % polygonContourPtr->points.size ();
395 p_j[0] = polygonContourPtr->points[j].x; p_j[1] = polygonContourPtr->points[j].y; p_j[2] = polygonContourPtr->points[j].z;
396 double cross_segment = p_i[k1] * p_j[k2] - p_i[k2] * p_j[k1];
398 AreaX2 += cross_segment;
399 massCenter[k1] += (p_i[k1] + p_j[k1]) * cross_segment;
400 massCenter[k2] += (p_i[k2] + p_j[k2]) * cross_segment;
402 areaHull = fabs (AreaX2) / (2 * ct);
404 massCenter[k1] /= (3*AreaX2);
405 massCenter[k2] /= (3*AreaX2);
406 massCenter[k0] = (v3normal.dot(v3center) - v3normal[k1]*massCenter[k1] - v3normal[k2]*massCenter[k2]) / v3normal[k0];
408 v3center = massCenter;
410 d = -(v3normal. dot (v3center));
415 pcl::PCA< PointT > pca;
416 pca.setInputCloud(planePointCloudPtr);
417 Eigen::VectorXf eigenVal = pca.getEigenValues();
420 elongation = sqrt(eigenVal[0] / eigenVal[1]);
421 Eigen::MatrixXf eigenVect = pca.getEigenVectors();
423 v3PpalDir[0] = eigenVect(0,0);
424 v3PpalDir[1] = eigenVect(1,0);
425 v3PpalDir[2] = eigenVect(2,0);
433 assert( planePointCloudPtr->size() > 0);
435 r.resize(planePointCloudPtr->size());
436 g.resize(planePointCloudPtr->size());
437 b.resize(planePointCloudPtr->size());
438 intensity.resize(planePointCloudPtr->size());
441 for(
size_t i=0; i < planePointCloudPtr->size(); i++)
443 float sumRGB = (float)planePointCloudPtr->points[i].r + planePointCloudPtr->points[i].g + planePointCloudPtr->points[i].b;
444 intensity[i] = sumRGB;
447 r[countPix] = planePointCloudPtr->points[i].r / sumRGB;
448 g[countPix] = planePointCloudPtr->points[i].g / sumRGB;
449 b[countPix] = planePointCloudPtr->points[i].b / sumRGB;
456 intensity.resize(countPix);
461 c1.resize(planePointCloudPtr->size());
462 c2.resize(planePointCloudPtr->size());
463 c3.resize(planePointCloudPtr->size());
465 for(
unsigned i=0; i < planePointCloudPtr->size(); i++)
467 c1[i] = atan2((
double) planePointCloudPtr->points[i].r, (
double) max(planePointCloudPtr->points[i].g,planePointCloudPtr->points[i].b));
468 c2[i] = atan2((
double) planePointCloudPtr->points[i].g, (
double) max(planePointCloudPtr->points[i].r,planePointCloudPtr->points[i].b));
469 c3[i] = atan2((
double) planePointCloudPtr->points[i].b, (
double) max(planePointCloudPtr->points[i].r,planePointCloudPtr->points[i].g));
478 const float FLOAT_TO_BYTE = 255.0f;
479 const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
483 for(
unsigned i=0; i < planePointCloudPtr->size(); i++)
486 fR = planePointCloudPtr->points[i].r * BYTE_TO_FLOAT;
487 fG = planePointCloudPtr->points[i].g * BYTE_TO_FLOAT;
488 fB = planePointCloudPtr->points[i].b * BYTE_TO_FLOAT;
494 if (planePointCloudPtr->points[i].b < planePointCloudPtr->points[i].g) {
495 if (planePointCloudPtr->points[i].b < planePointCloudPtr->points[i].r) {
497 if (planePointCloudPtr->points[i].r > planePointCloudPtr->points[i].g) {
498 iMax = planePointCloudPtr->points[i].r;
502 iMax = planePointCloudPtr->points[i].g;
509 iMax = planePointCloudPtr->points[i].g;
513 if (planePointCloudPtr->points[i].g < planePointCloudPtr->points[i].r) {
515 if (planePointCloudPtr->points[i].b > planePointCloudPtr->points[i].r) {
517 iMax = planePointCloudPtr->points[i].b;
521 iMax = planePointCloudPtr->points[i].r;
527 iMax = planePointCloudPtr->points[i].b;
530 fDelta = fMax - fMin;
550 float ANGLE_TO_UNIT = 12.0f / fDelta;
551 if (iMax == planePointCloudPtr->points[i].r) {
552 fH = (fG - fB) * ANGLE_TO_UNIT;
554 else if (iMax == planePointCloudPtr->points[i].g) {
555 fH = (2.0f/6.0f) + ( fB - fR ) * ANGLE_TO_UNIT;
558 fH = (4.0f/6.0f) + ( fR - fG ) * ANGLE_TO_UNIT;
572 for(
unsigned i=0; i < H.size(); i++)
575 for(
unsigned i=0; i < H.size(); i++)
576 hist_H[i] = H[i]/numPixels;
585 assert( planePointCloudPtr->size() > 0);
589 std::vector<Eigen::Vector4f>
color(planePointCloudPtr->size());
592 size_t stepColor = std::max(planePointCloudPtr->size() / 2000,
static_cast<size_t>(1));
593 for(
size_t i=0; i < planePointCloudPtr->size(); i+=stepColor)
595 float sumRGB = (float)planePointCloudPtr->points[i].r + planePointCloudPtr->points[i].g + planePointCloudPtr->points[i].b;
598 color[countPix][0] = planePointCloudPtr->points[i].r / sumRGB;
599 color[countPix][1] = planePointCloudPtr->points[i].g / sumRGB;
600 color[countPix][2] = planePointCloudPtr->points[i].b / sumRGB;
601 color[countPix][3] = sumRGB;
607 color.resize(countPix);
608 intensity.resize(countPix);
610 float concentration, histStdDev;
613 v3colorNrgb = dominantColor.head(3);
614 dominantIntensity = dominantColor(3);
617 bDominantColor =
true;
619 bDominantColor =
false;
656 dominantIntensity = 0;
657 int countFringe05 = 0;
658 for(
unsigned i=0; i <
r.size(); i++)
659 if(fabs(
r[i] - v3colorNrgb(0)) < 0.05 && fabs(
g[i] - v3colorNrgb(1)) < 0.05 && fabs(
b[i] - v3colorNrgb(2)) < 0.05)
661 dominantIntensity += intensity[i];
664 assert(countFringe05 > 0);
665 dominantIntensity /= countFringe05;
666 float concentration05 =
static_cast<float>(countFringe05) /
r.size();
673 if(concentration05 > 0.5)
674 bDominantColor =
true;
676 bDominantColor =
false;
705 return x <
p.x || (
x ==
p.x &&
y <
p.y);
711 return (A.
x - O.
x) * (B.
y - O.
y) - (A.
y - O.
y) * (B.
x - O.
x);
788 k0 = (fabs (v3normal(0) ) > fabs(v3normal[1])) ? 0 : 1;
789 k0 = (fabs (v3normal(k0) ) > fabs(v3normal(2))) ? k0 : 2;
791 std::vector<mPointHull> P;
792 P.resize(pointCloud->size() );
794 for(
size_t i=0; i < pointCloud->size(); i++)
796 P[i].x = pointCloud->points[i].y;
797 P[i].y = pointCloud->points[i].z;
801 for(
size_t i=0; i < pointCloud->size(); i++)
803 P[i].x = pointCloud->points[i].x;
804 P[i].y = pointCloud->points[i].z;
808 for(
size_t i=0; i < pointCloud->size(); i++)
810 P[i].x = pointCloud->points[i].x;
811 P[i].y = pointCloud->points[i].y;
815 int n = P.size(), k = 0;
816 std::vector<mPointHull> H(2*
n);
819 std::sort(P.begin(), P.end());
822 for (
int i = 0; i <
n; i++)
824 while (k >= 2 &&
cross(H[k-2], H[k-1], P[i]) <= 0)
828 assert(H[k-1].
id != H[k-2].
id);
832 for (
int i =
n-2,
t = k+1; i >= 0; i--)
834 while (k >=
t &&
cross(H[k-2], H[k-1], P[i]) <= 0)
840 size_t hull_noRep = k-1;
842 polygonContourPtr->resize(hull_noRep);
845 for(
size_t i=0; i < hull_noRep; i++)
847 polygonContourPtr->points[i] = pointCloud->points[ H[i].id ];
858 k0 = (fabs (v3normal(0) ) > fabs(v3normal[1])) ? 0 : 1;
859 k0 = (fabs (v3normal(k0) ) > fabs(v3normal(2))) ? k0 : 2;
863 std::vector<mPointHull> P;
864 P.resize(pointCloud->size() );
866 for(
size_t i=0; i < pointCloud->size(); i++)
868 P[i].x = pointCloud->points[i].y;
869 P[i].y = pointCloud->points[i].z;
873 for(
size_t i=0; i < pointCloud->size(); i++)
875 P[i].x = pointCloud->points[i].z;
876 P[i].y = pointCloud->points[i].x;
880 for(
size_t i=0; i < pointCloud->size(); i++)
882 P[i].x = pointCloud->points[i].x;
883 P[i].y = pointCloud->points[i].y;
887 int n = P.size(), k = 0;
888 std::vector<mPointHull> H(2*
n);
891 std::sort(P.begin(), P.end());
894 for (
int i = 0; i <
n; i++)
896 while (k >= 2 &&
cross(H[k-2], H[k-1], P[i]) <= 0)
900 assert(H[k-1].
id != H[k-2].
id);
904 for (
int i =
n-2,
t = k+1; i >= 0; i--)
906 while (k >=
t &&
cross(H[k-2], H[k-1], P[i]) <= 0)
912 size_t hull_noRep = k-1;
914 polygonContourPtr->resize(hull_noRep);
917 for(
size_t i=0; i < hull_noRep; i++)
919 polygonContourPtr->points[i] = pointCloud->points[ H[i].id ];
924 float ct = fabs ( v3normal[k0] );
926 Eigen::Vector3f massCenter = Eigen::Vector3f::Zero();
927 for(
size_t i=0, j=1; i < hull_noRep; i++, j++)
929 float cross_segment = H[i].x * H[j].y - H[i].y * H[j].x;
931 AreaX2 += cross_segment;
932 massCenter[k1] += (H[i].x + H[j].x) * cross_segment;
933 massCenter[k2] += (H[i].y + H[j].y) * cross_segment;
935 areaHull = fabs (AreaX2) / (2 * ct);
937 v3center[k1] /= (3*AreaX2);
938 v3center[k2] /= (3*AreaX2);
939 v3center[k0] = (-d - v3normal[k1]*massCenter[k1] - v3normal[k2]*massCenter[k2]) / v3normal[k0];
941 d = -v3normal .dot( v3center );
944 Eigen::Matrix2f covariances = Eigen::Matrix2f::Zero();
945 Eigen::Vector2f p1, p2;
946 p2[0] = H[0].x-massCenter[k1]; p2[1] = H[0].y-massCenter[k2];
948 for(
size_t i=1; i < hull_noRep; i++)
951 p2[0] = H[i].x-massCenter[k1]; p2[1] = H[i].y-massCenter[k2];
952 float lenght_side = (p1 - p2).
norm();
954 covariances += lenght_side * (p1*p1.transpose() + p2*p2.transpose());
959 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> evd (covariances);
961 for (
int i = 0; i < 2; ++i)
963 std::cout <<
"Eig " << evd.eigenvalues()[i] <<
" v " << evd.eigenvectors().col(i).transpose() <<
"\n";
965 if( evd.eigenvalues()[0] > 2 * evd.eigenvalues()[1] )
967 elongation = sqrt(evd.eigenvalues()[0] / evd.eigenvalues()[1]);
968 v3PpalDir[k1] = evd.eigenvectors()(0,0);
969 v3PpalDir[k2] = evd.eigenvectors()(1,0);
970 v3PpalDir[k0] = (-d - v3normal[k1]*v3PpalDir[k1] - v3normal[k2]*v3PpalDir[k2]) / v3normal[k0];
971 v3PpalDir /= v3PpalDir.norm();
978 float distThres2 = distThreshold * distThreshold;
981 if( (v3center - plane_nearby.
v3center).squaredNorm() < distThres2 )
984 for(
unsigned i=1; i < polygonContourPtr->size(); i++)
992 for(
unsigned i=1; i < polygonContourPtr->size(); i++)
1000 for(
unsigned i=1; i < polygonContourPtr->size(); i++)
1010 bool Plane::isSamePlane(
Plane &plane_nearby,
const float &cosAngleThreshold,
const float ¶llelDistThres,
const float &proxThreshold)
1013 if( v3normal .dot (plane_nearby.
v3normal) < cosAngleThreshold )
1017 float dist_normal = v3normal .dot (plane_nearby.
v3center - v3center);
1018 if(fabs(dist_normal) > parallelDistThres )
1022 if( !isPlaneNearby(plane_nearby, proxThreshold) )
1030 bool Plane::isSamePlane(Eigen::Matrix4f &Rt,
Plane &plane_,
const float &cosAngleThreshold,
const float ¶llelDistThres,
const float &proxThreshold)
1032 Plane plane = plane_;
1037 if(fabs(d - plane.
d) > parallelDistThres )
1041 if( v3normal.dot(plane.
v3normal) < cosAngleThreshold )
1054 return isPlaneNearby(plane, proxThreshold);
1060 (fabs(v3colorNrgb[0] - plane.
v3colorNrgb[0]) > colorThreshold ||
1061 fabs(v3colorNrgb[1] - plane.
v3colorNrgb[1]) > colorThreshold )
1077 assert(inliers.size() > 0 && same_plane_patch.
inliers.size() > 0);
1078 v3normal = (inliers.size()*v3normal + same_plane_patch.
inliers.size()*same_plane_patch.
v3normal);
1079 v3normal = v3normal / v3normal.norm();
1086 static pcl::VoxelGrid<pcl::PointXYZRGBA> merge_grid;
1087 merge_grid.setLeafSize(0.05,0.05,0.05);
1088 pcl::PointCloud<pcl::PointXYZRGBA> mergeCloud;
1089 merge_grid.setInputCloud (planePointCloudPtr);
1090 merge_grid.filter (mergeCloud);
1091 planePointCloudPtr->clear();
1092 *planePointCloudPtr = mergeCloud;
1097 inliers.insert(inliers.end(), same_plane_patch.
inliers.begin(), same_plane_patch.
inliers.end());
1101 computeMassCenterAndArea();
1103 d = -v3normal .dot( v3center );
1106 forcePtsLayOnPlane();
1111 areaVoxels= planePointCloudPtr->size() * 0.0025;
1119 assert(inliers.size() > 0 && same_plane_patch.
inliers.size() > 0);
1120 v3normal = (inliers.size()*v3normal + same_plane_patch.
inliers.size()*same_plane_patch.
v3normal);
1121 v3normal = v3normal / v3normal.norm();
1126 inliers.insert(inliers.end(), same_plane_patch.
inliers.begin(), same_plane_patch.
inliers.end());
1132 computeMassCenterAndArea();
1134 calcElongationAndPpalDir();
1136 d = -v3normal .dot( v3center );
1142 for(
size_t i=0; i < hist_H.size(); i++)
1144 hist_H[i] += same_plane_patch.
hist_H[i];
1153 v3normal = Rt.block(0,0,3,3) * v3normal;
1154 v3PpalDir = Rt.block(0,0,3,3) * v3PpalDir;
1157 v3center = Rt.block(0,0,3,3) * v3center + Rt.block(0,3,3,1);
1159 d = -(v3normal. dot (v3center));
1162 pcl::transformPointCloud(*polygonContourPtr, *polygonContourPtr, Rt);
1164 pcl::transformPointCloud(*planePointCloudPtr, *planePointCloudPtr, Rt);
Eigen::Vector4f getMultiDimMeanShift_color(std::vector< Eigen::Vector4f > &data, dataType &stdDevHist, dataType &concentration)
Eigen::Vector3f diffPoints(const POINT &P1, const POINT &P2)
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr polygonContourPtr
void readFromStream(mrpt::utils::CStream &in, int version)
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
void transform(Eigen::Matrix4f &Rt)
The virtual base class which provides a unified interface for all persistent objects in MRPT...
A class used to store a planar feature (Plane for short).
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
void mergePlane2(Plane &plane)
GLuint GLuint GLsizei GLenum const GLvoid * indices
void mergePlane(Plane &plane)
Eigen::Vector3f v3colorNrgb
! Radiometric description
void calcConvexHullandParams(pcl::PointCloud< pcl::PointXYZRGBA >::Ptr &pointCloud, std::vector< size_t > &indices=DEFAULT_VECTOR)
void calcElongationAndPpalDir()
! mPointHull serves to calculate the convex hull of a set of points in 2D, which are defined by its p...
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
pcl::PointCloud< pcl::PointXYZRGBA >::Ptr planePointCloudPtr
dataType getHistogramMeanShift(std::vector< dataType > &data, double range, dataType &stdDevHist_out)
void forcePtsLayOnPlane()
float cross(const mPointHull &O, const mPointHull &A, const mPointHull &B)
bool isSamePlane(Plane &plane, const float &cosAngleThreshold, const float &distThreshold, const float &proxThreshold)
bool isPlaneNearby(Plane &plane, const float distThreshold)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
float compute2DPolygonalArea()
Compute the area of a 2D planar polygon patch - using a given normal.
float PBMAP_IMPEXP dist3D_Segment_to_Segment2(Segment S1, Segment S2)
GLdouble GLdouble GLdouble r
void computeMassCenterAndArea()
Compute the patch's convex-hull area and mass center.
std::vector< int32_t > inliers
! Convex Hull
std::vector< float > hist_H
bool operator<(const CPoint< DERIVEDCLASS > &a, const CPoint< DERIVEDCLASS > &b)
Used by STL algorithms.
Eigen::Vector3f v3center
! Geometric description
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
float concentrationThreshold
unsigned __int32 uint32_t
bool hasSimilarDominantColor(Plane &plane, const float colorThreshold)
void calcConvexHull(pcl::PointCloud< pcl::PointXYZRGBA >::Ptr &pointCloud, std::vector< size_t > &indices=DEFAULT_VECTOR)
! Calculate the plane's convex hull with the monotone chain algorithm.
CONTAINER::Scalar norm(const CONTAINER &v)
Eigen::Vector3f getVector3fromPointXYZ(pointPCL &pt)