赞
踩
Pcl开发的应用中,当需要用户对点云做一些操作的时候,需要从屏幕拾取点云中某点的三维坐标。关于如何运用PCL实现这部分功能,很多介绍都是基于控制台程序的,调用写在main函数里,但是大部分时候,我们需要把这些事情封装在类中,这时候有一些小小的差别。
这次学习主要是记录了对回调机制的理解,封装pcl的选点的回调函数为类的成员函数,完成拾取屏幕坐标点的功能,也记录下完整的类和调用部分的代码。
在理解代码之前,要先明确三个概念:中间函数、回调函数、起始函数。
回调函数最好理解,是作为参数被传入的、后又被调用的函数。中间函数,是需要回调函数作为参数的那个函数,在第三方库中应用回调,通常是库函数去担任中间函数的角色。在传入一个回调函数之前,中间函数是不完整的。换句话说,程序可以在运行时,通过登记不同的回调函数,来决定、改变中间函数的行为,因此程序变得灵活。最后是起始函数,起始函数和回调函数是属于同一层级的函数,是中间函数的调用者,虽然这个函数可能就一两行,但是理解起始函数的作用对理解回调机制也很重要。
这三个部分共同作用,实现回调,有了高层(起始函数)调用底层(中间函数),底层再回过头来调用高层(回调函数)的过程,应该就是"回调"的含义。
A.中间函数:registerPointPickingCallback
函数第二个参数涉及的类:pcl::visualization::PointPickingEvent,是我们写回调函数的时候第一个参数的类类型。
A.中间函数:registerAreaPickingCallback()
函数第二个参数涉及的类:pcl::visualization::AreaPickingEvent:,是我们写回调函数的时候第一个参数的类类型。
B.bool pcl::visualization::AreaPickingEvent::getPointsIndices ( std::vector< int > & indices ) const
利用此函数可以获取视窗中选择的点云数据的索引,根据索引又可以获得确定的离散点数据。
差别主要是registerKeyboardCallback函数的调用。在大部分的例子中,都是在控制台程序的main函数中直接调用,只有两个参数,非类中调用的函数原型;
- registerKeyboardCallback (
- void (*callback) (const pcl::visualization::KeyboardEvent&, void*),
- void* cookie = NULL)
其中,KeyboardEvent是我们自定义的函数,在这里它是一个回调函数。也就是是一个通过函数指针来调用的函数。需要把函数的指针(地址)作为参数传递给另一个函数,用这个指针被用来调用其所指向的函数时。KeyboardEvent在里面包含了我们在点击、框选等动作时的处理声明。
当keyboard_callback函数是类的一部分时,需要指定类的实例,以便编译器能够确定要使用keyboard_callback函数的实例。这里调用的函数的参数传递有了差别,多了第二个参数 T& instance:调用这个中间函数的类的实例,可以传this指针。
- registerKeyboardCallback (
- void (T::*callback) (const pcl::visualization::KeyboardEvent&, void*),
- T& instance,
- void* cookie = NULL)
- #pragma once
- #include "stdafx.h"
- #include "utility.h"
- #include <fstream>
- #include <pcl/io/pcd_io.h>
- #include <pcl/point_cloud.h>
- #include <pcl/point_types.h>
- #include <pcl/visualization/cloud_viewer.h>
- #include <iostream>
- #include <pcl/io/io.h>
- #include <pcl/io/ply_io.h>
- #include <iostream>
- #include <pcl/console/parse.h>
-
- using namespace pcl;
- typedef pcl::PointXYZ PointT;
- typedef pcl::PointCloud<PointT> PointCloudT;
-
- class PtPicking
- {
- public:
- PtPicking(std::string filename);
- void reset();
- ~PtPicking();
-
- void keyboardEventOccurred(const visualization::KeyboardEvent &event, void* junk);
- void areaPicking(); //框选点云、
- void pointPicking(); //单点选取
- void ptActicPicking(); //屏幕选点
- pcl::PointXYZ randomPoint();
- void spin();
- protected:
- boost::mutex cloud_mutex;
- int num = 0;
- boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
- pcl::PointCloud<pcl::PointXYZ>::Ptr baseCloud; //加载的原始点云
- pcl::PointCloud<pcl::PointXYZ>::Ptr clicked_points_3d; //被选中的点云,可以用reset充值
-
- void areaPicking_callback(const pcl::visualization::AreaPickingEvent & event, void * args);
- void pointPicking_callback(const pcl::visualization::PointPickingEvent & event, void * args);
- void PtActivePick_callback(const pcl::visualization::PointPickingEvent & event, void * args);
- };
- #pragma once
- #include "stdafx.h"
- #include "PtPicking.h"
- PtPicking::~PtPicking()
- {
- }
- PtPicking::PtPicking(std::string filename) {
-
- clicked_points_3d.reset(new pcl::PointCloud<PointT>);
- baseCloud.reset(new pcl::PointCloud<PointT>());
-
- if (pcl::io::loadPCDFile(filename, *baseCloud))
- {
- std::cerr << "ERROR: Cannot open file " << filename << "! Aborting..." << std::endl;
- return;
- }
- reset();
- };
-
- void PtPicking:: reset()
- {
- // Create cloud
- clicked_points_3d.reset(new pcl::PointCloud<PointT>);
- // Create viewer
- viewer.reset(new pcl::visualization::PCLVisualizer("viewer"));
- viewer->addCoordinateSystem(1);
- viewer->addPointCloud(baseCloud, "cloud");
- viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud");
- }
-
- void PtPicking::keyboardEventOccurred(const visualization::KeyboardEvent &event, void* junk) {
-
- if (event.getKeySym() == "r" && event.keyDown()) {
- baseCloud->push_back(randomPoint());
- viewer->updatePointCloud(baseCloud, "cloud");
- }
- };
-
- //框选事件的调用
- void PtPicking::areaPicking()
- {
- // Register Keyboard Event
- //viewer->registerKeyboardCallback(&dummyClass::keyboardEventOccurred, *this);
- viewer->registerAreaPickingCallback(&PtPicking::areaPicking_callback, *this);//由于点云数据写成了成员变量,所以这里第三个参数不用传
- std::cout << "press X to strat or ending picking, then press 'Q'..." << std::endl;
- }
-
- //点选的调用
- void PtPicking::pointPicking()
- {
- cloud_mutex.lock(); // for not overwriting the point cloud
- viewer->registerPointPickingCallback(&PtPicking::pointPicking_callback, *this);
- std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl;
- cloud_mutex.unlock();
-
- }
-
- //点选的调用(这个比较灵活,可选屏幕任意位置)
- void PtPicking::ptActicPicking()
- {
- cloud_mutex.lock(); // for not overwriting the point cloud
- viewer->registerPointPickingCallback(&PtPicking::PtActivePick_callback, *this);
- std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl;
- cloud_mutex.unlock();
-
- }
-
-
- //框选事件的回调函数,
- //款选屏幕上的一部分点云
- //选择方式:输入一个x表示开始或者结束。两次x输入期间用鼠标左键框选点云,可以多次框选。输入q则腿粗选择
- void PtPicking::areaPicking_callback(const pcl::visualization::AreaPickingEvent& event, void *args)
- {
- struct callback_args * data = (struct callback_args *)args;//点云数据 & 可视化窗口
- std::vector<int > indices;
- if (event.getPointsIndices(indices) == false)
- return;
- for (size_t i = 0; i < indices.size(); i++)
- {
- clicked_points_3d->points.push_back(baseCloud->points.at(indices[i]));
- }
- pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(clicked_points_3d, 255, 0, 0);
- viewer->removePointCloud("clicked_points");
- viewer->addPointCloud(clicked_points_3d, red, "clicked_points");
- viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
- for (int i = 0; i < clicked_points_3d->points.size(); i++)
- std::cout << clicked_points_3d->points[i].x << std::endl;
- std::cout << "clicked_points_3d->points.size()" << clicked_points_3d->points.size() << std::endl;
-
- }
-
- //点选事件的回调函数
- //点选屏幕上的点云
- //选择方式:按住shift,鼠标左键点选
- void PtPicking::pointPicking_callback(const pcl::visualization::PointPickingEvent& event, void *args)
- {
- struct callback_args * data = (struct callback_args *)args;//点云数据 & 可视化窗口
- if (event.getPointIndex() == -1)
- return;
- PointT current_point;
- event.getPoint(current_point.x, current_point.y, current_point.z);
- clicked_points_3d->points.push_back(current_point);
- //Draw clicked points in red:
- pcl::visualization::PointCloudColorHandlerCustom<PointT> red(clicked_points_3d, 255, 0, 0);
- viewer->removePointCloud("clicked_points");
- viewer->addPointCloud(clicked_points_3d, red, "clicked_points");
- viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
- std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl;
-
- }
-
- //点选事件的回调函数
- //点选事件——点击屏幕上的任一点(pointPicking_callback()是一定要点击点云数据上的点)
- //选择方式:按住shift,鼠标左键选择。键盘输入 Q 则退出选择
- void PtPicking::PtActivePick_callback(const pcl::visualization::PointPickingEvent& event, void *args)
- {
- std::cout << "Picking event active" << std::endl;
- PointT current_point;
- if (event.getPointIndex() != -1)
- {
- float x, y, z;
- event.getPoint(current_point.x, current_point.y, current_point.z);
- //std::cout << x << ";" << y << ";" << z << std::endl;
- clicked_points_3d->points.push_back(current_point);
-
- }
- // Draw clicked points in red:
- pcl::visualization::PointCloudColorHandlerCustom<PointT> red(clicked_points_3d, 255, 0, 0);
- viewer->removePointCloud("clicked_points");
- viewer->addPointCloud(clicked_points_3d, red, "clicked_points");
- viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
- std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl;
-
- }
-
- pcl::PointXYZ PtPicking::randomPoint() {
- pcl::PointXYZ pt;
- pt.x = (double)rand() / RAND_MAX * 10 - 5;
- pt.y = (double)rand() / RAND_MAX * 10 - 5;
- pt.z = (double)rand() / RAND_MAX * 10 - 5;
- return pt;
- };
-
- void PtPicking::spin() {
- viewer->spin();
- };
调用时需要输入pcd文件路径
- char filePCD[32];
- printf("请输入pcd文件路径");
- scanf("%s", filePCD);/*输入文件名*/
- PtPicking dc(filePCD);
- //dc.pointPicking();
- //dc.ptActicPicking();
- dc.areaPicking();
- dc.spin();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。