//#define vtkRenderingCore_AUTOINIT 2(vtkRenderingOpenGL, vtkInteractionStyle)
//#include "vtkAutoInit.h"
#include <iostream>
#include <vector>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/min_cut_segmentation.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <boost/thread/thread.hpp>
using namespace std;
using namespace pcl::console;
using namespace pcl;
/**/
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
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>);
PointT current_point1;//新加部分——定义了一个全局变量用来接收点击的坐标
// Mutex: //
boost::mutex cloud_mutex;
/*zhuti*/
int num = 0;
unsigned char* pointmark;//点云分类标记
void pp_callback1(const pcl::visualization::AreaPickingEvent& event, void* args)
{
std::vector< int > indices;
if (event.getPointsIndices(indices) == -1)
return;
//添加点云(去掉重复的点)
int addcount = 0;//添加点计数
long bt = clock();//开始时间
for (int i = 0; i < indices.size(); ++i)
{
if (pointmark[indices[i]] == 0)
{
clicked_points_3d->points.push_back(cloud->points.at(indices[i]));
addcount++;
pointmark[indices[i]] = 1;//将点云标记为已圈选状态
}
}
long et = clock();//开始时间
std::cout << "花费时间:" << et - bt << "ms" << endl;
std::cout << "添加点数:" << addcount << endl;
clicked_points_3d->height = 1;
clicked_points_3d->width += addcount;
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, 5, cloudName);
// 保存点云
pcl::PLYWriter writer;
writer.write<pcl::PointXYZ>("tooth_hand_seg.ply", *clicked_points_3d);
}
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);
current_point1 = current_point;//新加部分——把点击的点赋值给全局变量
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 select() {
char path[100];
sprintf_s(path, "mahang.ply");
if (pcl::io::loadPLYFile(path, *cloud))
{
std::cerr << "ERROR: Cannot open file " << std::endl;
return;
}
pointmark = new unsigned char[cloud->size()];
for (size_t i = 0; i < cloud->size(); i++)
{
pointmark[i] = 0;//初始化点云分类标识,0为未标记点
}
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud");
clicked_points_3d->width = 0;//初始化点云个数
viewer->registerAreaPickingCallback(pp_callback1, (void*)&cloud);//注册事件
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
delete[]pointmark;
PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
if (io::loadPLYFile("tooth_hand_seg.ply", *cloud) == -1) {
cerr << "can't read file bunny.pcd" << endl;
}
//io::savePCDFile("D:\\data\\PCL_data\\bunny.pcd", *cloud);
/* 创建视窗对象,并给标题栏定义一个名称"3D viewer"。viewer的类型为boost::shared_ptr只能共享指针,
* 这样做可以保证该指针在整个程序中全局使用,而不引起内存错误。
*/
boost::shared_ptr<visualization::PCLVisualizer> viewer(new visualization::PCLVisualizer("3D viewer"));
/*设置窗口viewer的背景颜色*/
viewer->setBackgroundColor(0, 0, 0);
/*将点云数据添加到视窗中,并为其定义一个唯一的字符串作为ID号,利用此ID号保证其他成员方法也能表示该点云。
* 多次调用addPointCloud()可以实现多个点云的叠加,每调用一次就创建一个新的ID号。如果想要更新一个已经
* 显示的点云,用户必须先调用removePointCloud(),并提供新的ID号。(在PCL1.1版本之后直接调用updatePointCloud()
* 就可以了,不必手动调用removePointCloud()就可实现点云更新)
*/
viewer->addPointCloud<PointXYZ>(cloud, "sample cloud");
/*修改现实点云的尺寸。用户可通过该方法控制点云在视窗中的显示方式*/
viewer->setPointCloudRenderingProperties(visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");
/*设置XYZ三个坐标轴的大小和长度,该值也可以缺省
*查看复杂的点云图像会让用户没有方向感,为了让用户保持正确的方向判断,需要显示坐标轴。三个坐标轴X(R,红色)
* Y(G,绿色)Z(B,蓝色)分别用三种不同颜色的圆柱体代替。
*/
viewer->addCoordinateSystem(1.0);
/*通过设置相机参数是用户从默认的角度和方向观察点*/
viewer->initCameraParameters();
}
void click()
{
std::string filename("tooth_hand_seg.ply");
//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::loadPLYFile(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, "tooth_hand_seg");
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();
}
/*zhuti*/
int main()
{
select();
click();
time_t start, end, diff[5], option;
start = time(0);
int NumberOfNeighbours = 14;//设置默认参数
bool Bool_Cuting = false;//设置默认参数
float far_cuting = 1, near_cuting = 0, C_x = 21.4733, C_y = 13.2185, C_z = 12.9154,
Sigma = 0.55, Radius = 2.0, SourceWeight = 1.0;//设置默认输入参数
pcl::PointCloud <pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud <pcl::PointXYZ>);// 创建一个PointCloud <pcl::PointXYZRGB>共享指针并进行实例化
if (pcl::io::loadPLYFile <pcl::PointXYZ>("tooth_hand_seg.ply", *cloud) == -1)// 加载点云数据
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
pcl::IndicesPtr indices(new std::vector <int>);//创建一组索引
if (Bool_Cuting)//判断是否需要直通滤波
{
pcl::PassThrough<pcl::PointXYZ> pass;//设置直通滤波器对象
pass.setInputCloud(cloud);//设置输入点云
pass.setFilterFieldName("z");//设置指定过滤的维度
pass.setFilterLimits(near_cuting, far_cuting);//设置指定纬度过滤的范围
pass.filter(*indices);//执行滤波,保存滤波结果在上述索引中
}
//生成分割器
pcl::MinCutSegmentation<pcl::PointXYZ> seg;
//分割输入分割目标
seg.setInputCloud(cloud);
//指定打击目标(目标点)
pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointXYZ point;
point.x = current_point1.x;//新加部分——把全局变量的XYZ坐标分别交给前景点云进行分割
point.y = current_point1.y;
point.z = current_point1.y;
foreground_points->points.push_back(point);
seg.setForegroundPoints(foreground_points);
//指定权函数sigma
seg.setSigma(0.5);
//物体大概范围
seg.setRadius(8.42);
//用多少生成图
seg.setNumberOfNeighbours(14);
//和目标点相连点的权值(至少有14个)
seg.setSourceWeight(1.0);
//分割结果
std::vector <pcl::PointIndices> clusters;
seg.extract(clusters);
std::cout << "Maximum flow is " << seg.getMaxFlow() << std::endl;//计算并输出分割期间所计算出的流值
pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.getColoredCloud();//对前景点赋予红色,对背景点赋予白色。
pcl::visualization::PCLVisualizer viewer("点云库PCL学习教程第二版-最小割分割方法");
viewer.addPointCloud(colored_cloud, "sample");
/*viewer.addSphere(point, Radius, 122, 122, 0, "sphere");
viewer.setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.2, "sphere");*/
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample");
while (!viewer.wasStopped())
{
viewer.spin();
}//进行可视化
return (0);
}
勾画+点击+分割
最新推荐文章于 2024-05-31 13:31:26 发布