如何使用PCL提取点云数据中的一组点?
How to extract a set of points in a point cloud data using PCL?
我有一个点云数据,通过点击一个点,我想提取半径范围内点击点周围的点。我还想将提取的点推送到新的云中。使用 Pointpikindingevent,我可以单击一个点并将其推送到云中。如何提取一组点,比如从单击点开始围绕 0.02 厘米半径的点并将它们推入新云中?
给定一个点云:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud
然后生成一个Kdtree来进行高效的范围搜索:
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud (cloud);
然后,给定一个点和一个半径:
pcl::PointXYZ searchPoint(1,2,3);
float radius = 4;
您可以得到距离点 searchPoint:
距离 radius 的所有点
std::vector<int> pointIdxRadiusSearch; //to store index of surrounding points
std::vector<float> pointRadiusSquaredDistance; // to store distance to surrounding points
if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
{
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
std::cout << " " << cloud->points[ pointIdxRadiusSearch[i] ].x
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].y
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].z
<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
您可以打印所有周围的点及其到 searchPoint 的距离以检查代码功能的正确性。
最后,用获得的点创建一个云:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
cloud_cluster->points.push_back(cloud->points[ pointIdxRadiusSearch[i] ]);
cloud_cluster->width = cloud_cluster->points.size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
为了能够选择一个点,您可以使用类似于 this answer 的 PointPickingEvent。
你的.h中的Class声明,
class PCLViewer : public QMainWindow
{
Q_OBJECT
public:
explicit PCLViewer (QWidget *parent = 0);
~PCLViewer ();
void pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*);
public slots:
protected:
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointXYZ src_point_;
bool src_point_selected_;
private:
Ui::PCLViewer *ui;
};
在你的 .cpp 中,
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::PCLViewer)
{
ui->setupUi (this);
[...]
viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
viewer->registerPointPickingCallback (&PCLViewer::pointPickCallback, *this);
[...]
}
和附加功能,
void
PCLViewer::pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
// Check to see if we got a valid point. Early exit.
int idx = event.getPointIndex ();
if (idx == -1)
return;
// Get the point that was picked
event.getPoint (src_point_.x, src_point_.y, src_point_.z);
PCL_INFO ("Src Window: Clicked point %d with X:%f Y:%f Z:%f\n", idx, src_point_.x, src_point_.y, src_point_.z);
src_point_selected_ = true;
}
在手动注册应用程序中有更详细的使用示例:
pcl/apps/src/manual_registration/manual_registration.cpp
pcl/apps/include/pcl/apps/manual_registration.h
我有一个点云数据,通过点击一个点,我想提取半径范围内点击点周围的点。我还想将提取的点推送到新的云中。使用 Pointpikindingevent,我可以单击一个点并将其推送到云中。如何提取一组点,比如从单击点开始围绕 0.02 厘米半径的点并将它们推入新云中?
给定一个点云:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud
然后生成一个Kdtree来进行高效的范围搜索:
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud (cloud);
然后,给定一个点和一个半径:
pcl::PointXYZ searchPoint(1,2,3);
float radius = 4;
您可以得到距离点 searchPoint:
距离 radius 的所有点std::vector<int> pointIdxRadiusSearch; //to store index of surrounding points
std::vector<float> pointRadiusSquaredDistance; // to store distance to surrounding points
if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
{
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
std::cout << " " << cloud->points[ pointIdxRadiusSearch[i] ].x
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].y
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].z
<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
您可以打印所有周围的点及其到 searchPoint 的距离以检查代码功能的正确性。
最后,用获得的点创建一个云:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
cloud_cluster->points.push_back(cloud->points[ pointIdxRadiusSearch[i] ]);
cloud_cluster->width = cloud_cluster->points.size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
为了能够选择一个点,您可以使用类似于 this answer 的 PointPickingEvent。
你的.h中的Class声明,
class PCLViewer : public QMainWindow
{
Q_OBJECT
public:
explicit PCLViewer (QWidget *parent = 0);
~PCLViewer ();
void pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*);
public slots:
protected:
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointXYZ src_point_;
bool src_point_selected_;
private:
Ui::PCLViewer *ui;
};
在你的 .cpp 中,
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::PCLViewer)
{
ui->setupUi (this);
[...]
viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
viewer->registerPointPickingCallback (&PCLViewer::pointPickCallback, *this);
[...]
}
和附加功能,
void
PCLViewer::pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
// Check to see if we got a valid point. Early exit.
int idx = event.getPointIndex ();
if (idx == -1)
return;
// Get the point that was picked
event.getPoint (src_point_.x, src_point_.y, src_point_.z);
PCL_INFO ("Src Window: Clicked point %d with X:%f Y:%f Z:%f\n", idx, src_point_.x, src_point_.y, src_point_.z);
src_point_selected_ = true;
}
在手动注册应用程序中有更详细的使用示例: pcl/apps/src/manual_registration/manual_registration.cpp pcl/apps/include/pcl/apps/manual_registration.h