您的位置:首页 > 其它

《PCL点云库学习&VS2010(X64)》Part 10 PCL1.72(VTK6.2.0)选点操作

2016-06-21 20:31 465 查看
Part 10 PCL1.72(VTK6.2.0)选点操作




1、单点选取程序:

cpp:

#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>

typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

// Mutex: //
boost::mutex cloud_mutex;

struct callback_args{
// structure used to pass arguments to the callback function
PointCloudT::Ptr clicked_points_3d;
pcl::visualization::PCLVisualizer::Ptr viewerPtr;
};

void
pp_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);
data->clicked_points_3d->points.push_back(current_point);
// Draw clicked points in red:
pcl::visualization::PointCloudColorHandlerCustom<PointT> red(data->clicked_points_3d, 255, 0, 0);
data->viewerPtr->removePointCloud("clicked_points");
data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl;
}

void main()
{
std::string filename("bunny.pcd");
//visualizer
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer"));

if (pcl::io::loadPCDFile(filename, *cloud))
{
std::cerr << "ERROR: Cannot open file " << filename << "! Aborting..." << std::endl;
return;
}
std::cout << cloud->points.size() << std::endl;

//viewer->addPointCloud(cloud, "bunny");

cloud_mutex.lock();    // for not overwriting the point cloud

// Display pointcloud:
viewer->addPointCloud(cloud, "bunny");
viewer->setCameraPosition(0, 0, -2, 0, -1, 0, 0);

// Add point picking callback to viewer:
struct callback_args cb_args;
PointCloudT::Ptr clicked_points_3d(new PointCloudT);
cb_args.clicked_points_3d = clicked_points_3d;
cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(viewer);
viewer->registerPointPickingCallback(pp_callback, (void*)&cb_args);
std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl;

// Spin until 'Q' is pressed:
viewer->spin();
std::cout << "done." << std::endl;

cloud_mutex.unlock();

while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}

编译运行:



注:使用shift键配合鼠标选点。

2、区域选点

#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <vector>

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer"));
pcl::PointCloud<pcl::PointXYZ>::Ptr clicked_points_3d(new pcl::PointCloud<pcl::PointXYZ>);
int num = 0;

void pp_callback(const pcl::visualization::AreaPickingEvent& event, void* args)
{
std::vector< int > indices;
if (event.getPointsIndices(indices)==-1)
return;

for (int i = 0; i < indices.size(); ++i)
{
clicked_points_3d->points.push_back(cloud->points.at(indices[i]));
}

pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(clicked_points_3d, 255, 0, 0);

std::stringstream ss;
std::string cloudName;
ss << num++;
ss >> cloudName;
cloudName += "_cloudName";

viewer->addPointCloud(clicked_points_3d, red, cloudName);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, cloudName);
}

void main()
{
if (pcl::io::loadPCDFile("bunny.pcd", *cloud))
{
std::cerr << "ERROR: Cannot open file " << std::endl;
return;
}

viewer->addPointCloud(cloud, "bunny");
viewer->setCameraPosition(0, 0, -2, 0, -1, 0, 0);
viewer->registerAreaPickingCallback(pp_callback, (void*)&cloud);

while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}

编译运行:



注:使用x键配合鼠标左键选择区域,同时再按下x取消框选。

3、单点选择:

程序中对所以的鼠标点都会罗列在控制台中,和第一个有点差异

cpp:

#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>

typedef pcl::PointXYZRGBA PointT_XYZ;
typedef pcl::PointCloud<PointT_XYZ> PointCloudT_XYZ;

// Mutex: //
boost::mutex cloud_mutex;

struct callback_args{
// structure used to pass arguments to the callback function
PointCloudT_XYZ::Ptr clicked_points_3d;
pcl::visualization::PCLVisualizer::Ptr viewerPtr;
};

void
pp_callback(const pcl::visualization::PointPickingEvent& event, void* args)
{

struct callback_args* data = (struct callback_args *)args;
std::cout << "Picking event active" << std::endl;
PointT_XYZ 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;
data->clicked_points_3d->points.push_back(current_point);

}
// Draw clicked points in red:
pcl::visualization::PointCloudColorHandlerCustom<PointT_XYZ> red(data->clicked_points_3d, 255, 0, 0);
data->viewerPtr->removePointCloud("clicked_points");
data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::endl;
}

void main()
{

//visualizer
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("viewer"));

pcl::io::loadPCDFile("Bunny.pcd", *cloud);

//viewer->addPointCloud(cloud, "bunny");

cloud_mutex.lock();    // for not overwriting the point cloud

// Display pointcloud:
viewer->addPointCloud(cloud, "bunny");

// Add point picking callback to viewer:
struct callback_args cb_args;
PointCloudT_XYZ::Ptr clicked_points_3d(new PointCloudT_XYZ);
cb_args.clicked_points_3d = clicked_points_3d;
cb_args.viewerPtr = pcl::visualization::PCLVisualizer::Ptr(viewer);
viewer->registerPointPickingCallback(pp_callback, (void*)&cb_args);

std::cout << "Shift+click on three floor points, then press 'Q'..." << std::endl;

// Spin until 'Q' is pressed:
viewer->spin();
std::cout << "done." << std::endl;

cloud_mutex.unlock();

while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}


*4、选点程序,没有标出点,注意,要输入三个数才能进行操作,如1 1 1,按C键可以显示信息

cpp:

#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;
////pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> red(p->clicked_points_3d, 255, 0, 0);
////data->viewerPtr->removePointCloud("clicked_points");
////data->viewerPtr->addPointCloud(data->clicked_points_3d, red, "clicked_points");
////data->viewerPtr->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
////std::cout << current_point.x << " " << current_point.y << " " << current_point.z << std::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::loadPCDFile("Bunny.pcd", *cloud);
//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;
}

5、整合到Qt+VTK的界面中的技巧:

参看博文

http://blog.csdn.net/hopedengxiwang/article/details/6940719

http://stackoverflow.com/questions/14267895/error-with-callback-function?answertab=active#tab-top

http://stackoverflow.com/questions/9596276/how-to-explain-callbacks-in-plain-english-how-are-they-different-from-calling-o

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

如何在类中封装回调函数(第一个链接)

我们知道回调函数只能是全局的或是静态的。
全局函数会破坏类的封装性,故不予采用。
而静态函数只能访问类的静态成员,不能访问类中非静态成员。

那么如何让静态函数访问类的非静态成员呢?
1).声明一静态函数a(),将类实例对象指针做为参数传入。如:
class A()
{
static void a(A *); //静态函数
void b(); //非静态函数
}
void A::a(A * pThis)
{
pThis->b(); //静态函数中调用非静态函数
}

2).回调函数中访问非静态成员

由于回调函数往往有固定定义,并不接受 A * pThis 参数

如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);

【解决方案1】:本方案当遇到有多个类实例对象时会有问题。原因是pThis指针只能指向一个对象。

class A()

{

static void a(); //静态回调函数

void b(); //非静态函数

static A * pThis; //静态对象指针

}

A * A::pThis=NULL;

A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象

{

pThis=this;

}

void A::a()

{

if (pThis==NULL) return;

pThis->b(); //回调函数中调用非静态函数

}

【解决方案2】:本方案解决多个类实例对象时方案1的问题。用映射表存所有对象地址,每个对象保存自己的ID号。

typedef CMap<UINT,UINT,A*,A*> CAMap;

class A()

{

static void a(); //静态回调函数

void b(); //非静态函数

int m_ID; //本对象在列表中的ID号

static int m_SID; //静态当前对象ID (需要时,将m_ID赋值给m_SID以起到调用本对象函数的功能)

static CAMap m_Map; //静态对象映射表

}

CAMap A::m_Map;

int A::m_SID=0;

A::A() //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象

{

if(m_Map.IsEmpty())

{

m_ID=1;

}

else

{

m_ID=m_Map.GetCount()+1;

}

m_Map.SetAt( m_ID, this );

}

void A::a()

{

if (m_Map.IsEmpty()) return;

A * pThis=NULL;

if(m_Map.Lookup(m_SID,pThis))

{

pThis->b(); //回调函数中调用非静态函数

};

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

参考下,仔细琢磨一下,可以实现在Qt中的选点功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: