Я следую учебному пособию по документам PCL для расчета 2D выпуклой оболочки посмотреть здесь.
У меня есть облако и некоторые индексы, проецируем их на плоскость с заданными коэффициентами и затем вычисляем выпуклую оболочку. Вот код:
PointCloud<PointXYZ>::Ptr tmpInliers(new PointCloud<PointXYZ>());
ProjectInliers<PointXYZ> proj;
proj.setModelType(SACMODEL_PLANE);
proj.setInputCloud(someCloud);
proj.setIndices(someIndices);
proj.setModelCoefficients(someCoefficients);
proj.filter(*tmpInliers);
PointCloud<PointXYZ>::Ptr hull(new PointCloud<PointXYZ>());
ConvexHull<PointXYZ> chull;
chull.setInputCloud(tmpInliers);
chull.setComputeAreaVolume(true);
chull.setDimension(3); <--- see below
chull.reconstruct(*hull);
Результаты, которые я получаю для общей площади и объема:
Area & Volume of convex hull: 7.8726e-312 2.122e-314
Для значений tmpInliers начиная вокруг
(-0.80562,-0.787018,2.25184)
(-0.477351,-0.798953,2.11432)
(-0.633823,-0.750283,2.96717)
[....]
Если я изменяю «setDimensions» на «2», я получаю следующую ошибку
[pcl::ConvexHull::performReconstrution2D] ERROR: qhull was unable to compute a convex hull for the given point cloud (size of cloud)!
В следующем примере я создаю пример и в каждом случае не работаю (setDimension установлен на 2 или 3) с одним из предыдущих сбоев (либо «qhull не удалось …», либо странным результатом в соответствии со значениями из ConvexHull.
PointCloud<PointXYZ>::Ptr hugeBox(new PointCloud<PointXYZ>());
hugeBox->push_back(PointXYZ(10, 10, 10));
hugeBox->push_back(PointXYZ(10, 10, -10));
hugeBox->push_back(PointXYZ(10, -10, 10));
hugeBox->push_back(PointXYZ(10, -10, -10));
hugeBox->push_back(PointXYZ(-10, 10, 10));
hugeBox->push_back(PointXYZ(-10, 10, -10));
hugeBox->push_back(PointXYZ(-10, -10, 10));
hugeBox->push_back(PointXYZ(-10, -10, -10));
// Project inliers onto plane model
PointCloud<PointXYZ>::Ptr hugePlane(new PointCloud<PointXYZ>());
ProjectInliers<PointXYZ> proj;
proj.setModelType(SACMODEL_PLANE);
proj.setInputCloud(hugeBox);
proj.setModelCoefficients(coefficients);
proj.filter(*hugePlane);
// get the convex hull of plane
vector<Vertices> polygonsOut;
PointCloud<PointXYZ>::Ptr hugeHull(new PointCloud<PointXYZ>());
ConvexHull<PointXYZ> chull;
chull.setInputCloud(hugePlane);
chull.setDimension(2);
chull.reconstruct(*hugeHull, polygonsOut);
Я немного застрял здесь. Почему не получается, если я установил 2 измерения? И если я установлю его на 3 измерения, я иногда получаю следующее предупреждение:
qhull precision warning:
The initial hull is narrow (cosine of min. angle is 0.9999999999999991).
A coplanar point may lead to a wide facet.
Я понимаю, что это так, если у меня плоская проекция, но как этого избежать?
Я не знаю, какую платформу вы используете, но дайте мне догадаться: вы проецируете точки на плоскость, встроенную в трехмерный объем, я прав? Совершенно очевидно, что 3-мерный алгоритм выпуклой оболочки не работает, потому что точки, спроецированные на плоскость, являются компланарными — по определению. С другой стороны, даже если они проецируются на плоскость, которая встроена в трехмерное пространство, точки также находятся в трехмерном пространстве — я полагаю. С другой стороны, алгоритм двумерной выпуклой оболочки предполагает наличие реальных двумерных точек — скорее всего. Таким образом, я думаю, что это приведет к уменьшению спроецированных точек до реального 2-мерного пространства посредством какого-либо отображения, а затем применит алгоритм 2-й выпуклой оболочки.
Хорошо, проблема была в том, что PCL связывался со старым libqhull (v0.5) из системы вместо новой v0.6 который присутствовал, но не был правильно связан.
Проблемы возникают не регулярно, но в некоторых особых случаях со старой версией, например, если у вас есть плоская проекция от 3d до 2d и вы пытаетесь наложить на нее корпус.
Я отправлю запрос в pcl-people, чтобы добавить требование к номеру версии.