22 #include <pcl/common/time.h> 23 #include <pcl/filters/voxel_grid.h> 141 if (out_Version) *out_Version = 0;
189 out << v3normal(0) << v3normal(1) << v3normal(2);
190 out << v3center(0) << v3center(1) << v3center(2);
191 out << v3PpalDir(0) << v3PpalDir(1) << v3PpalDir(2);
192 out << v3colorNrgb(0) << v3colorNrgb(1) << v3colorNrgb(2);
195 out << dominantIntensity;
196 out << bDominantColor;
207 out << label_context;
223 out << (
uint32_t)polygonContourPtr->size();
224 for (
uint32_t i = 0; i < polygonContourPtr->size(); i++)
225 out << polygonContourPtr->points[i].x
226 << polygonContourPtr->points[i].y
227 << polygonContourPtr->points[i].z;
298 in >> v3normal(0) >> v3normal(1) >> v3normal(2);
299 in >> v3center(0) >> v3center(1) >> v3center(2);
300 in >> v3PpalDir(0) >> v3PpalDir(1) >> v3PpalDir(2);
301 d = -v3normal.dot(v3center);
302 in >> v3colorNrgb(0) >> v3colorNrgb(1) >> v3colorNrgb(2);
305 in >> dominantIntensity;
306 in >> bDominantColor;
343 polygonContourPtr->resize(
n);
344 for (
unsigned i = 0; i <
n; i++)
345 in >> polygonContourPtr->points[i].x >>
346 polygonContourPtr->points[i].y >>
347 polygonContourPtr->points[i].z;
366 const double D = -(v3normal.dot(v3center));
367 for (
unsigned i = 0; i < planePointCloudPtr->size(); i++)
369 double dist = v3normal[0] * planePointCloudPtr->points[i].x +
370 v3normal[1] * planePointCloudPtr->points[i].y +
371 v3normal[2] * planePointCloudPtr->points[i].z + D;
372 planePointCloudPtr->points[i].x -= v3normal[0] * dist;
373 planePointCloudPtr->points[i].y -= v3normal[1] * dist;
374 planePointCloudPtr->points[i].z -= v3normal[2] * dist;
377 for (
unsigned i = 0; i < polygonContourPtr->size(); i++)
379 double dist = v3normal[0] * polygonContourPtr->points[i].x +
380 v3normal[1] * polygonContourPtr->points[i].y +
381 v3normal[2] * polygonContourPtr->points[i].z + D;
382 polygonContourPtr->points[i].x -= v3normal[0] * dist;
383 polygonContourPtr->points[i].y -= v3normal[1] * dist;
384 polygonContourPtr->points[i].z -= v3normal[2] * dist;
396 k0 = (fabs(v3normal[0]) > fabs(v3normal[1])) ? 0 : 1;
397 k0 = (fabs(v3normal[k0]) > fabs(v3normal[2])) ? k0 : 2;
403 float ct = fabs(v3normal[k0]);
405 float p_i[3], p_j[3];
407 for (
unsigned int i = 0; i < polygonContourPtr->points.size(); i++)
409 p_i[0] = polygonContourPtr->points[i].x;
410 p_i[1] = polygonContourPtr->points[i].y;
411 p_i[2] = polygonContourPtr->points[i].z;
412 int j = (i + 1) % polygonContourPtr->points.size();
413 p_j[0] = polygonContourPtr->points[j].x;
414 p_j[1] = polygonContourPtr->points[j].y;
415 p_j[2] = polygonContourPtr->points[j].z;
417 AreaX2 += p_i[k1] * p_j[k2] - p_i[k2] * p_j[k1];
419 AreaX2 = fabs(AreaX2) / (2 * ct);
432 k0 = (fabs(v3normal[0]) > fabs(v3normal[1])) ? 0 : 1;
433 k0 = (fabs(v3normal[k0]) > fabs(v3normal[2])) ? k0 : 2;
439 float ct = fabs(v3normal[k0]);
441 Eigen::Vector3f massCenter = Eigen::Vector3f::Zero();
442 float p_i[3], p_j[3];
444 for (
unsigned int i = 0; i < polygonContourPtr->points.size(); i++)
446 p_i[0] = polygonContourPtr->points[i].x;
447 p_i[1] = polygonContourPtr->points[i].y;
448 p_i[2] = polygonContourPtr->points[i].z;
449 int j = (i + 1) % polygonContourPtr->points.size();
450 p_j[0] = polygonContourPtr->points[j].x;
451 p_j[1] = polygonContourPtr->points[j].y;
452 p_j[2] = polygonContourPtr->points[j].z;
453 double cross_segment = p_i[k1] * p_j[k2] - p_i[k2] * p_j[k1];
455 AreaX2 += cross_segment;
456 massCenter[k1] += (p_i[k1] + p_j[k1]) * cross_segment;
457 massCenter[k2] += (p_i[k2] + p_j[k2]) * cross_segment;
459 areaHull = fabs(AreaX2) / (2 * ct);
461 massCenter[k1] /= (3 * AreaX2);
462 massCenter[k2] /= (3 * AreaX2);
463 massCenter[k0] = (v3normal.dot(v3center) - v3normal[k1] * massCenter[k1] -
464 v3normal[k2] * massCenter[k2]) /
467 v3center = massCenter;
469 d = -(v3normal.dot(v3center));
474 pcl::PCA<PointT> pca;
475 pca.setInputCloud(planePointCloudPtr);
476 Eigen::VectorXf eigenVal = pca.getEigenValues();
479 elongation = sqrt(eigenVal[0] / eigenVal[1]);
480 Eigen::MatrixXf eigenVect = pca.getEigenVectors();
483 v3PpalDir[0] = eigenVect(0, 0);
484 v3PpalDir[1] = eigenVect(1, 0);
485 v3PpalDir[2] = eigenVect(2, 0);
493 assert(planePointCloudPtr->size() > 0);
495 r.resize(planePointCloudPtr->size());
496 g.resize(planePointCloudPtr->size());
497 b.resize(planePointCloudPtr->size());
498 intensity.resize(planePointCloudPtr->size());
501 for (
size_t i = 0; i < planePointCloudPtr->size(); i++)
503 float sumRGB = (float)planePointCloudPtr->points[i].r +
504 planePointCloudPtr->points[i].g +
505 planePointCloudPtr->points[i].b;
506 intensity[i] = sumRGB;
509 r[countPix] = planePointCloudPtr->points[i].r / sumRGB;
510 g[countPix] = planePointCloudPtr->points[i].g / sumRGB;
511 b[countPix] = planePointCloudPtr->points[i].b / sumRGB;
518 intensity.resize(countPix);
523 c1.resize(planePointCloudPtr->size());
524 c2.resize(planePointCloudPtr->size());
525 c3.resize(planePointCloudPtr->size());
527 for (
unsigned i = 0; i < planePointCloudPtr->size(); i++)
530 (
double)planePointCloudPtr->points[i].r,
532 planePointCloudPtr->points[i].g,
533 planePointCloudPtr->points[i].b));
535 (
double)planePointCloudPtr->points[i].g,
537 planePointCloudPtr->points[i].r,
538 planePointCloudPtr->points[i].b));
540 (
double)planePointCloudPtr->points[i].b,
542 planePointCloudPtr->points[i].r,
543 planePointCloudPtr->points[i].g));
552 const float FLOAT_TO_BYTE = 255.0f;
553 const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
555 vector<int> H(74, 0);
557 for (
unsigned i = 0; i < planePointCloudPtr->size(); i++)
560 fR = planePointCloudPtr->points[i].r * BYTE_TO_FLOAT;
561 fG = planePointCloudPtr->points[i].g * BYTE_TO_FLOAT;
562 fB = planePointCloudPtr->points[i].b * BYTE_TO_FLOAT;
568 if (planePointCloudPtr->points[i].b < planePointCloudPtr->points[i].g)
570 if (planePointCloudPtr->points[i].b <
571 planePointCloudPtr->points[i].r)
574 if (planePointCloudPtr->points[i].r >
575 planePointCloudPtr->points[i].g)
577 iMax = planePointCloudPtr->points[i].r;
582 iMax = planePointCloudPtr->points[i].g;
590 iMax = planePointCloudPtr->points[i].g;
595 if (planePointCloudPtr->points[i].g <
596 planePointCloudPtr->points[i].r)
599 if (planePointCloudPtr->points[i].b >
600 planePointCloudPtr->points[i].r)
603 iMax = planePointCloudPtr->points[i].b;
608 iMax = planePointCloudPtr->points[i].r;
615 iMax = planePointCloudPtr->points[i].b;
618 fDelta = fMax - fMin;
641 float ANGLE_TO_UNIT = 12.0f / fDelta;
642 if (iMax == planePointCloudPtr->points[i].r)
644 fH = (fG - fB) * ANGLE_TO_UNIT;
646 else if (iMax == planePointCloudPtr->points[i].g)
648 fH = (2.0f / 6.0f) + (fB - fR) * ANGLE_TO_UNIT;
652 fH = (4.0f / 6.0f) + (fR - fG) * ANGLE_TO_UNIT;
655 if (fH < 0.0f) fH += 72.0f;
656 if (fH >= 72.0f) fH -= 72.0f;
664 for (
unsigned i = 0; i < H.size(); i++) numPixels += H[i];
666 for (
unsigned i = 0; i < H.size(); i++) hist_H[i] = H[i] / numPixels;
675 assert(planePointCloudPtr->size() > 0);
679 std::vector<Eigen::Vector4f>
color(planePointCloudPtr->size());
682 size_t stepColor = std::max(
683 planePointCloudPtr->size() / 2000,
686 for (
size_t i = 0; i < planePointCloudPtr->size(); i += stepColor)
688 float sumRGB = (float)planePointCloudPtr->points[i].r +
689 planePointCloudPtr->points[i].g +
690 planePointCloudPtr->points[i].b;
693 color[countPix][0] = planePointCloudPtr->points[i].r / sumRGB;
694 color[countPix][1] = planePointCloudPtr->points[i].g / sumRGB;
695 color[countPix][2] = planePointCloudPtr->points[i].b / sumRGB;
696 color[countPix][3] = sumRGB;
704 color.resize(countPix);
705 intensity.resize(countPix);
707 float concentration, histStdDev;
709 Eigen::Vector4f dominantColor =
711 v3colorNrgb = dominantColor.head(3);
712 dominantIntensity = dominantColor(3);
715 bDominantColor =
true;
717 bDominantColor =
false;
760 dominantIntensity = 0;
761 int countFringe05 = 0;
762 for (
unsigned i = 0; i <
r.size(); i++)
763 if (fabs(
r[i] - v3colorNrgb(0)) < 0.05 &&
764 fabs(
g[i] - v3colorNrgb(1)) < 0.05 &&
765 fabs(
b[i] - v3colorNrgb(2)) < 0.05)
767 dominantIntensity += intensity[i];
770 assert(countFringe05 > 0);
771 dominantIntensity /= countFringe05;
772 float concentration05 =
static_cast<float>(countFringe05) /
r.size();
782 if (concentration05 > 0.5)
783 bDominantColor =
true;
785 bDominantColor =
false;
821 return x <
p.x || (
x ==
p.x &&
y <
p.y);
827 return (A.
x - O.
x) * (B.
y - O.
y) - (A.
y - O.
y) * (B.
x - O.
x);
903 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr& pointCloud,
909 k0 = (fabs(v3normal(0)) > fabs(v3normal[1])) ? 0 : 1;
910 k0 = (fabs(v3normal(k0)) > fabs(v3normal(2))) ? k0 : 2;
912 std::vector<mPointHull> P;
913 P.resize(pointCloud->size());
915 for (
size_t i = 0; i < pointCloud->size(); i++)
917 P[i].x = pointCloud->points[i].y;
918 P[i].y = pointCloud->points[i].z;
922 for (
size_t i = 0; i < pointCloud->size(); i++)
924 P[i].x = pointCloud->points[i].x;
925 P[i].y = pointCloud->points[i].z;
929 for (
size_t i = 0; i < pointCloud->size(); i++)
931 P[i].x = pointCloud->points[i].x;
932 P[i].y = pointCloud->points[i].y;
936 int n = P.size(), k = 0;
937 std::vector<mPointHull> H(2 *
n);
940 std::sort(P.begin(), P.end());
943 for (
int i = 0; i <
n; i++)
945 while (k >= 2 &&
cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
947 if (k > 0) assert(H[k - 1].
id != H[k - 2].
id);
951 for (
int i =
n - 2,
t = k + 1; i >= 0; i--)
953 while (k >=
t &&
cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
958 size_t hull_noRep = k - 1;
960 polygonContourPtr->resize(hull_noRep);
963 for (
size_t i = 0; i < hull_noRep; i++)
965 polygonContourPtr->points[i] = pointCloud->points[H[i].id];
971 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr& pointCloud,
977 k0 = (fabs(v3normal(0)) > fabs(v3normal[1])) ? 0 : 1;
978 k0 = (fabs(v3normal(k0)) > fabs(v3normal(2))) ? k0 : 2;
982 std::vector<mPointHull> P;
983 P.resize(pointCloud->size());
985 for (
size_t i = 0; i < pointCloud->size(); i++)
987 P[i].x = pointCloud->points[i].y;
988 P[i].y = pointCloud->points[i].z;
992 for (
size_t i = 0; i < pointCloud->size(); i++)
994 P[i].x = pointCloud->points[i].z;
995 P[i].y = pointCloud->points[i].x;
999 for (
size_t i = 0; i < pointCloud->size(); i++)
1001 P[i].x = pointCloud->points[i].x;
1002 P[i].y = pointCloud->points[i].y;
1006 int n = P.size(), k = 0;
1007 std::vector<mPointHull> H(2 *
n);
1010 std::sort(P.begin(), P.end());
1013 for (
int i = 0; i <
n; i++)
1015 while (k >= 2 &&
cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
1017 if (k > 0) assert(H[k - 1].
id != H[k - 2].
id);
1021 for (
int i =
n - 2,
t = k + 1; i >= 0; i--)
1023 while (k >=
t &&
cross(H[k - 2], H[k - 1], P[i]) <= 0) k--;
1028 size_t hull_noRep = k - 1;
1030 polygonContourPtr->resize(hull_noRep);
1033 for (
size_t i = 0; i < hull_noRep; i++)
1035 polygonContourPtr->points[i] = pointCloud->points[H[i].id];
1040 float ct = fabs(v3normal[k0]);
1042 Eigen::Vector3f massCenter = Eigen::Vector3f::Zero();
1043 for (
size_t i = 0, j = 1; i < hull_noRep; i++, j++)
1045 float cross_segment = H[i].x * H[j].y - H[i].y * H[j].x;
1047 AreaX2 += cross_segment;
1048 massCenter[k1] += (H[i].x + H[j].x) * cross_segment;
1049 massCenter[k2] += (H[i].y + H[j].y) * cross_segment;
1051 areaHull = fabs(AreaX2) / (2 * ct);
1053 v3center[k1] /= (3 * AreaX2);
1054 v3center[k2] /= (3 * AreaX2);
1056 (-d - v3normal[k1] * massCenter[k1] - v3normal[k2] * massCenter[k2]) /
1059 d = -v3normal.dot(v3center);
1062 Eigen::Matrix2f covariances = Eigen::Matrix2f::Zero();
1063 Eigen::Vector2f p1, p2;
1064 p2[0] = H[0].x - massCenter[k1];
1065 p2[1] = H[0].y - massCenter[k2];
1067 for (
size_t i = 1; i < hull_noRep; i++)
1070 p2[0] = H[i].x - massCenter[k1];
1071 p2[1] = H[i].y - massCenter[k2];
1072 float lenght_side = (p1 - p2).
norm();
1075 lenght_side * (p1 * p1.transpose() + p2 * p2.transpose());
1080 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> evd(covariances);
1082 for (
int i = 0; i < 2; ++i)
1084 std::cout <<
"Eig " << evd.eigenvalues()[i] <<
" v " 1085 << evd.eigenvectors().col(i).transpose() <<
"\n";
1087 if (evd.eigenvalues()[0] > 2 * evd.eigenvalues()[1])
1089 elongation = sqrt(evd.eigenvalues()[0] / evd.eigenvalues()[1]);
1090 v3PpalDir[k1] = evd.eigenvectors()(0, 0);
1091 v3PpalDir[k2] = evd.eigenvectors()(1, 0);
1093 (-d - v3normal[k1] * v3PpalDir[k1] - v3normal[k2] * v3PpalDir[k2]) /
1095 v3PpalDir /= v3PpalDir.norm();
1103 float distThres2 = distThreshold * distThreshold;
1107 if ((v3center - plane_nearby.
v3center).squaredNorm() < distThres2)
1110 for (
unsigned i = 1; i < polygonContourPtr->size(); i++)
1113 .squaredNorm() < distThres2)
1119 .squaredNorm() < distThres2)
1122 for (
unsigned i = 1; i < polygonContourPtr->size(); i++)
1125 polygonContourPtr->points[i],
1127 .squaredNorm() < distThres2)
1133 for (
unsigned i = 1; i < polygonContourPtr->size(); i++)
1137 polygonContourPtr->points[i],
1138 polygonContourPtr->points[i - 1]),
1153 Plane& plane_nearby,
const float& cosAngleThreshold,
1154 const float& parallelDistThres,
const float& proxThreshold)
1157 if (v3normal.dot(plane_nearby.
v3normal) < cosAngleThreshold)
return false;
1161 float dist_normal = v3normal.dot(plane_nearby.
v3center - v3center);
1162 if (fabs(dist_normal) > parallelDistThres)
1166 if (!isPlaneNearby(plane_nearby, proxThreshold))
return false;
1176 Eigen::Matrix4f& Rt,
Plane& plane_,
const float& cosAngleThreshold,
1177 const float& parallelDistThres,
const float& proxThreshold)
1179 Plane plane = plane_;
1182 Rt.block(0, 0, 3, 3) * plane_.
v3center + Rt.block(0, 3, 3, 1);
1183 pcl::transformPointCloud(
1186 if (fabs(d - plane.
d) > parallelDistThres)
return false;
1189 if (v3normal.dot(plane.
v3normal) < cosAngleThreshold)
return false;
1206 return isPlaneNearby(plane, proxThreshold);
1212 (fabs(v3colorNrgb[0] - plane.
v3colorNrgb[0]) > colorThreshold ||
1213 fabs(v3colorNrgb[1] - plane.
v3colorNrgb[1]) > colorThreshold))
1229 assert(inliers.size() > 0 && same_plane_patch.
inliers.size() > 0);
1231 (inliers.size() * v3normal +
1233 v3normal = v3normal / v3normal.norm();
1238 *planePointCloudPtr +=
1245 static pcl::VoxelGrid<pcl::PointXYZRGBA> merge_grid;
1246 merge_grid.setLeafSize(0.05, 0.05, 0.05);
1247 pcl::PointCloud<pcl::PointXYZRGBA> mergeCloud;
1248 merge_grid.setInputCloud(planePointCloudPtr);
1249 merge_grid.filter(mergeCloud);
1250 planePointCloudPtr->clear();
1251 *planePointCloudPtr = mergeCloud;
1257 inliers.end(), same_plane_patch.
inliers.begin(),
1258 same_plane_patch.
inliers.end());
1262 computeMassCenterAndArea();
1264 d = -v3normal.dot(v3center);
1267 forcePtsLayOnPlane();
1272 areaVoxels = planePointCloudPtr->size() * 0.0025;
1279 assert(inliers.size() > 0 && same_plane_patch.
inliers.size() > 0);
1281 (inliers.size() * v3normal +
1283 v3normal = v3normal / v3normal.norm();
1286 *planePointCloudPtr +=
1292 inliers.end(), same_plane_patch.
inliers.begin(),
1293 same_plane_patch.
inliers.end());
1301 computeMassCenterAndArea();
1303 calcElongationAndPpalDir();
1305 d = -v3normal.dot(v3center);
1313 for (
size_t i = 0; i < hist_H.size(); i++)
1315 hist_H[i] += same_plane_patch.
hist_H[i];
1323 v3normal = Rt.block(0, 0, 3, 3) * v3normal;
1324 v3PpalDir = Rt.block(0, 0, 3, 3) * v3PpalDir;
1327 v3center = Rt.block(0, 0, 3, 3) * v3center + Rt.block(0, 3, 3, 1);
1329 d = -(v3normal.dot(v3center));
1332 pcl::transformPointCloud(*polygonContourPtr, *polygonContourPtr, Rt);
1334 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 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)
bool operator<(const mPointHull &p) const
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 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
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)
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Eigen::Vector3f getVector3fromPointXYZ(pointPCL &pt)