勾画+点击+分割


//#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);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值