背景:
PCL + VTK
项目地址:https://github.com/dezbracaty/PCD_Area_cut_tool
后期添加其他功能maybe
通过PVL_VISUALIZATION显示点云图像,然后通过按X进入框选模式,然后接受PCL::VISUALIZATION返回的点云索引,然后通过索引将所选择的点云文件导出。
函数介绍:
pcl::visualization::PCLVisualizer::Ptr
viewer(new pcl::visualization::PCLVisualizer("Carviewer"));
viewer->registerAreaPickingCallback(areapickingcallback);
registerAreaPickingCallback介绍:
/** \brief Register a callback function for area picking events * \param[in] cb a boost function that will be registered as a callback for an area picking event * \return a connection object that allows to disconnect the callback function. */ boost::signals2::connection registerAreaPickingCallback (boost::function<void (const pcl::visualization::AreaPickingEvent&)> cb);
函数的参数是一个回调函数,这个函数主要针对的是picking 事件。
接下来是自己写的回调函数:
void areapickingcallback(const pcl::visualization::AreaPickingEvent &event,void *userdata);
接受event,以及一个空指针。
再来看一下AreaPickingEvent的函数内容:
namespace pcl { namespace visualization { /** /brief Class representing 3D area picking events. */ class PCL_EXPORTS AreaPickingEvent { public: AreaPickingEvent (int nb_points, const std::vector<int>& indices) : nb_points_ (nb_points) , indices_ (indices) {} /** \brief For situations where a whole are is selected, return the points indices. * \param[out] indices indices of the points under the area selected by user. * \return true, if the area selected by the user contains points, false otherwise */ inline bool getPointsIndices (std::vector<int>& indices) const { if (nb_points_ <= 0) return (false); indices = indices_; return (true); } private: int nb_points_; std::vector<int> indices_; }; } //namespace visualization } //namespace pcl
event只提供一个返回点云索引的函数,所以通过event获取索引,然后通过索引从点云提取所需要的点 即可。
通过点云索引提取点云需要使用 pcl::ExtractIndices,他的使用方式是:
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud); //导入点云数据
extract.setIndices(ind_plane); //设置点云索引
extract.setNegative(false); //设置为false,选择索引指向的点导出
extract.filter(*secloud); //输出所选点云
这里的索引他的类属性是pcl::IndicesPtr,但是event返回的是一个std::vector<int>的容器,所以需要添加一步转换操作:
pcl::IndicesPtr ind_plane=boost::make_shared<std::vector<int>>(indices);
至此程序的代码逻辑已经结束,下面是完整的代码:
main.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/common.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/extract_indices.h>
#include <vtkAreaPicker.h>
#include <string>
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
typedef pcl::PointXYZ PointType;
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Carviewer"));
void areapickingcallback(const pcl::visualization::AreaPickingEvent &event,void *userdata)
{
pcl::PointCloud<PointType>::Ptr secloud(new pcl::PointCloud<PointType>());
std::cout<<"Into here"<<std::endl;
std::vector<int> indices;
event.getPointsIndices(indices);
pcl::IndicesPtr ind_plane=boost::make_shared<std::vector<int>>(indices);
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud); //导入点云数据
extract.setIndices(ind_plane); //设置点云索引
extract.setNegative(false); //设置为false,选择索引指向的点导出
extract.filter(*secloud); //输出所选点云
std::cout<<"Nums selected\t"<<secloud->points.size()<<std::endl;
pcl::io::savePCDFile("car.pcd",*secloud);
}
int main() {
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Carviewer"));
pcl::io::loadPCDFile("car6.pcd",*cloud);
viewer->setBackgroundColor(0,0,0);
viewer->addPointCloud(cloud,"car");
viewer->registerAreaPickingCallback(areapickingcallback);
while (!viewer->wasStopped ())
{
viewer->spinOnce (100);
boost::this_thread::sleep (boost::posix_time::microseconds (100000));
}
std::cout << "Hello, World!" << std::endl;
return 0;
}
CMakeList.txt
cmake_minimum_required(VERSION 3.17)
project(pcdtools)
find_package(PCL REQUIRED)
set(CMAKE_CXX_STANDARD 11)
include_directories(${PCL_INClUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(pcdtools main.cpp)
target_link_libraries(pcdtools ${PCL_LIBRARIES})