如何从 PCL 中的查看器中选择两个点

Posted

技术标签:

【中文标题】如何从 PCL 中的查看器中选择两个点【英文标题】:how to pick two points from viewer in PCL 【发布时间】:2015-01-21 23:26:42 【问题描述】:

我想从点云中选择两个点并返回两个点的坐标。为了解决这个问题,我使用了 PCL 的PointPickingEvent,并编写了一个包含点云、可视化器和一个向量的类来存储选定的点。我的代码:

#include <pcl/point_cloud.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/visualization/pcl_visualizer.h>

using namespace pcl;
using namespace std;

class pickPoints  
public: 

    pickPoints::pickPoints ()  
        viewer.reset (new pcl::visualization::PCLVisualizer ("Viewer", true)); 
        viewer->registerPointPickingCallback (&pickPoints::pickCallback, *this); 
     

    ~pickPoints ()  

    void setInputCloud (PointCloud<PointXYZ>::Ptr cloud) 
     
        cloudTemp = cloud; 
     

    vector<float> getpoints()  
        return p; 
     

    void simpleViewer () 
     
        // Visualizer
        viewer->addPointCloud<pcl::PointXYZ>(cloudTemp, "Cloud"); 
        viewer->resetCameraViewpoint ("Cloud"); 
        viewer->spin(); 
     

protected: 
    void pickCallback (const pcl::visualization::PointPickingEvent& event, void*) 
     
        if (event.getPointIndex () == -1) 
            return; 

        PointXYZ picked_point1,picked_point2; 
        event.getPoints(picked_point1.x,picked_point1.y,picked_point1.z,
            picked_point2.x,picked_point2.y,picked_point2.z); 
        p.push_back(picked_point1.x); // store points
        p.push_back(picked_point1.y);
        p.push_back(picked_point1.z); 
        p.push_back(picked_point2.x);
        p.push_back(picked_point2.y);
        p.push_back(picked_point2.z); 

        //cout<<"first selected point: "<<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;
        //cout<<"second selected point: "<<p[3]<<" "<<p[4]<<" "<<p[5]<<endl;
     

private: 
    // Point cloud data 
    PointCloud<pcl::PointXYZ>::Ptr cloudTemp; 

    // The visualizer 
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer; 

    // The picked point 
    vector<float> p; 
; 

int main()

    //LOAD;
    PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ> ());
    pcl::PolygonMesh mesh;
    pcl::io::loadPolygonFilePLY("test.ply", mesh);
    pcl::fromPCLPointCloud2(mesh.cloud, *cloud);

    pickPoints pickViewer; 
    pickViewer.setInputCloud(cloud); // A pointer to a cloud 
    pickViewer.simpleViewer(); 
    vector<float> pointSelected; 
    pointSelected= pickViewer.getpoints(); 

    cout<<pointSelected[0]<<" "<<pointSelected[1]<<" "<<pointSelected[2]<<endl;
    cout<<pointSelected[3]<<" "<<pointSelected[4]<<" "<<pointSelected[5]<<endl;

    cin.get();
    return 0;

但是当代码被调试时,我什么也没得到。我也知道用左键选择点时,应该按下 SHIFT 键。提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

我发现 getPoints() 方法没有按我的预期工作。但是,getPoint() 运行良好。这是打印出所选点并将它们存储为向量的代码:

std::vector<pcl::PointXYZ> selectedPoints;

void pointPickingEventOccurred(const pcl::visualization::PointPickingEvent& event, void* viewer_void)

    float x, y, z;
    if (event.getPointIndex() == -1)
    
        return;
    
    event.getPoint(x, y, z);
    std::cout << "Point coordinate ( " << x << ", " << y << ", " << z << ")" << std::endl;
    selectedPoints.push_back(pcl::PointXYZ(x, y, z));


void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, const std::string& window_name)

    if (cloud->size() < 1)
    
        std::cout << window_name << " display failure. Cloud contains no points\n";
        return;
    

    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
    pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(cloud, "intensity");

    viewer->addPointCloud< pcl::PointXYZI >(cloud, point_cloud_color_handler, "id");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");

    viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
    viewer->registerPointPickingCallback(pointPickingEventOccurred, (void*)&viewer);

    while (!viewer->wasStopped() && !close_window)
        viewer->spinOnce(50);
    
    close_window = false;
    viewer->close();

选择点后,您还可以很容易地找到它们之间的距离。

    if (selectedPoints.size() > 1)
    
        float distance = pcl::euclideanDistance(selectedPoints[0], selectedPoints[1]);
        std::cout << "Distance is " << distance << std::endl;
    

如果您想从拾取点开始,可以使用键盘事件清空 selectedPoints 向量。

【讨论】:

以上是关于如何从 PCL 中的查看器中选择两个点的主要内容,如果未能解决你的问题,请参考以下文章

MS 报告查看器中的报告标题

如何从 Flash 查看器中提取图像?

如何在 任务管理器中 查看某一个进程的cpu占用率?

如何在特定查看器中从内部存储打开文件? [复制]

如何以编程方式校准 Autodesk forge 查看器?

如何通过提供文件路径在默认图像查看器中打开图像?