基于PCL的屏幕选点、框选点云、单点选取等c++实现

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

猜你喜欢

转载自blog.csdn.net/qq_38446366/article/details/81908618