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

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中的选点功能。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值