STL模型多视角可视点云数据获取

STL模型多视角可视点云数据获取

摘要

本文使用VTK库通过多面体细分提取给定STL模型的多视点可视点云数据。

实现

函数主体

void get_template(vtkSmartPointer<vtkPolyData> polydata, std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> &tem)
{

	double CoM[3];
	vtkIdType npts_com = 0;
	vtkIdType *ptIds_com = nullptr;

	vtkSmartPointer<vtkCellArray> cells_com = vtkSmartPointer<vtkCellArray>::New();
	cells_com = polydata->GetPolys();

	double  center[3], p1_com[3], p2_com[3], p3_com[3], totalArea_com = 0;
	double comx = 0, comy = 0, comz = 0;

	for (cells_com->InitTraversal(); cells_com->GetNextCell(npts_com, ptIds_com);)
	{
		polydata->GetPoint(ptIds_com[0], p1_com);
		polydata->GetPoint(ptIds_com[1], p2_com);
		polydata->GetPoint(ptIds_com[2], p3_com);
		vtkTriangle::TriangleCenter(p1_com, p2_com, p3_com, center);
		double area_com = vtkTriangle::TriangleArea(p1_com, p2_com, p3_com);
		comx += center[0] * area_com;
		comy += center[1] * area_com;
		comz += center[2] * area_com;
		totalArea_com += area_com;
	}

	CoM[0] = comx / totalArea_com;
	CoM[1] = comy / totalArea_com;
	CoM[2] = comz / totalArea_com;

	vtkSmartPointer<vtkTransform> trans_center = vtkSmartPointer<vtkTransform>::New();
	trans_center->Translate(-CoM[0], -CoM[1], -CoM[2]);
	vtkSmartPointer<vtkMatrix4x4> matrixCenter = trans_center->GetMatrix();

	vtkSmartPointer<vtkTransformFilter> trans_filter_center = vtkSmartPointer<vtkTransformFilter>::New();
	trans_filter_center->SetTransform(trans_center);
	trans_filter_center->SetInputData(polydata);
	trans_filter_center->Update();

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(trans_filter_center->GetOutputPort());
	mapper->Update();

	double bb[6];
	mapper->GetBounds(bb);
	double ms = (std::max)((std::fabs)(bb[0] - bb[1]), (std::max) ((std::fabs) (bb[2] - bb[3]), (std::fabs) (bb[4] - bb[5])));
	double max_side = radius_sphere / 2.0;
	double scale_factor = ms / max_side;

	vtkSmartPointer<vtkPlatonicSolidSource> ico = vtkSmartPointer<vtkPlatonicSolidSource>::New();
	ico->SetSolidTypeToIcosahedron();
	ico->Update();

	vtkSmartPointer<vtkLoopSubdivisionFilter> subdivide = vtkSmartPointer<vtkLoopSubdivisionFilter>::New();
	subdivide->SetNumberOfSubdivisions(tesselation_level);
	subdivide->SetInputConnection(ico->GetOutputPort());
	subdivide->Update();

	vtkSmartPointer<vtkPolyData> sphere_pre = vtkSmartPointer<vtkPolyData>::New();
	sphere_pre = subdivide->GetOutput();

	vtkSmartPointer<vtkTransform> trans_scale = vtkSmartPointer<vtkTransform> ::New();
	trans_scale->Scale(scale_factor, scale_factor, scale_factor);
	vtkSmartPointer<vtkMatrix4x4> matrixScale = trans_scale->GetMatrix();
	vtkSmartPointer<vtkTransformFilter> trans_filter_scale = vtkSmartPointer<vtkTransformFilter>::New();
	trans_filter_scale->SetTransform(trans_scale);
	trans_filter_scale->SetInputData(sphere_pre);//相机放缩 这个自适应方法可以
	trans_filter_scale->Update();

	vtkSmartPointer<vtkPolyData> sphere = trans_filter_scale->GetPolyDataOutput();

	vtkSmartPointer<vtkWorldPointPicker> worldPicker = vtkSmartPointer<vtkWorldPointPicker>::New();

	std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> cam_positions;

	cam_positions.resize(sphere->GetNumberOfPoints());
	for (vtkIdType i = 0; i < sphere->GetNumberOfPoints(); i++)
	{
		double cam_pos[3];
		sphere->GetPoint(i, cam_pos);
		cam_positions[i] = Eigen::Vector3f(float(cam_pos[0]), float(cam_pos[1]), float(cam_pos[2]));
		cam_positions[i].normalized();
	}

	for (const auto &cam_position : cam_positions)
	{
		PointCloudT::Ptr t(new PointCloudT);

		double cam_pos[3];

		cam_pos[0] = cam_position[0];
		cam_pos[1] = cam_position[1];
		cam_pos[2] = cam_position[2];
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);
		Eigen::Vector3f cam_pos_3f = cam_position;
		Eigen::Vector3f perp = cam_pos_3f.cross(cam_pos_3f.cross(Eigen::Vector3f::UnitY()));

		vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New();
		cam->SetFocalPoint(0, 0, 0);
		cam->SetViewUp(-perp[0], -perp[1], -perp[2]);
		cam->SetPosition(cam_pos);
		cam->SetViewAngle(view_angle);
		cam->Modified();

		vtkSmartPointer<vtkRenderer> render = vtkSmartPointer<vtkRenderer>::New();
		render->AddActor(actor);
		render->SetBackground(0, 0, 0);
		render->SetActiveCamera(cam);

		vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
		rw->AddRenderer(render);
		rw->SetSize(xres, yres);
		rw->SetWindowName("multiview");
		rw->SetOffScreenRendering(1);
		rw->Render();

		vtkSmartPointer<vtkWorldPointPicker> worldpicker = vtkSmartPointer<vtkWorldPointPicker>::New();
		double coords[3];

		for (int y = 0; y < yres; y++)
		{
			for (int x = 0; x < xres; x++)
			{
				double z = rw->GetZbufferDataAtPoint(x, y);
				if (z == 1)
				{
					continue;
				}
				else
				{
					worldpicker->Pick(x, y, z, render);
					worldpicker->GetPickPosition(coords);
					PointT tmp;
					tmp.x = coords[0];
					tmp.y = coords[1];
					tmp.z = coords[2];
					t->push_back(tmp);
				}
			}
		}
		if (t->size() != 0) {
			tem.push_back(t);
		}
	}
}

验证

HPR.h
#ifndef HIDDEN_POINT_REMOVAL
#define HIDDEN_POINT_REMOVAL
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <string>
#include <vector>
#include <math.h>
#include <algorithm>
#include <iostream>

#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/common/transforms.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/filters/extract_indices.h>
#include <Eigen/Dense>
#include <pcl/PolygonMesh.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkTriangle.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkTransformFilter.h>
#include <vtkLoopSubdivisionFilter.h>
#include <vtkPlatonicSolidSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkWorldPointPicker.h>
#include <vtkcamera.h>

#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

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

void HPR(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& cloud_in, std::vector<float> camera_pos, int param, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_out); // Hidden Point Removal

void get_template(std::string model_path, std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> &tem);

void get_template(vtkSmartPointer<vtkPolyData> polydata, std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> &tem);

#endif
HPR.cpp
#include "HPR.h"

using namespace Eigen;
using namespace pcl;

#define radius_sphere 1
#define tesselation_level 1
#define use_vertices FALSE
#define xres 120 
#define yres 120
#define view_angle 90

void get_template(vtkSmartPointer<vtkPolyData> polydata, std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> &tem)
{

	double CoM[3];
	vtkIdType npts_com = 0;
	vtkIdType *ptIds_com = nullptr;

	vtkSmartPointer<vtkCellArray> cells_com = vtkSmartPointer<vtkCellArray>::New();
	cells_com = polydata->GetPolys();

	double  center[3], p1_com[3], p2_com[3], p3_com[3], totalArea_com = 0;
	double comx = 0, comy = 0, comz = 0;

	for (cells_com->InitTraversal(); cells_com->GetNextCell(npts_com, ptIds_com);)
	{
		polydata->GetPoint(ptIds_com[0], p1_com);
		polydata->GetPoint(ptIds_com[1], p2_com);
		polydata->GetPoint(ptIds_com[2], p3_com);
		vtkTriangle::TriangleCenter(p1_com, p2_com, p3_com, center);
		double area_com = vtkTriangle::TriangleArea(p1_com, p2_com, p3_com);
		comx += center[0] * area_com;
		comy += center[1] * area_com;
		comz += center[2] * area_com;
		totalArea_com += area_com;
	}

	CoM[0] = comx / totalArea_com;
	CoM[1] = comy / totalArea_com;
	CoM[2] = comz / totalArea_com;

	vtkSmartPointer<vtkTransform> trans_center = vtkSmartPointer<vtkTransform>::New();
	trans_center->Translate(-CoM[0], -CoM[1], -CoM[2]);
	vtkSmartPointer<vtkMatrix4x4> matrixCenter = trans_center->GetMatrix();

	vtkSmartPointer<vtkTransformFilter> trans_filter_center = vtkSmartPointer<vtkTransformFilter>::New();
	trans_filter_center->SetTransform(trans_center);
	trans_filter_center->SetInputData(polydata);
	trans_filter_center->Update();

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(trans_filter_center->GetOutputPort());
	mapper->Update();

	double bb[6];
	mapper->GetBounds(bb);
	double ms = (std::max)((std::fabs)(bb[0] - bb[1]), (std::max) ((std::fabs) (bb[2] - bb[3]), (std::fabs) (bb[4] - bb[5])));
	double max_side = radius_sphere / 2.0;
	double scale_factor = ms / max_side;

	vtkSmartPointer<vtkPlatonicSolidSource> ico = vtkSmartPointer<vtkPlatonicSolidSource>::New();
	ico->SetSolidTypeToIcosahedron();
	ico->Update();

	vtkSmartPointer<vtkLoopSubdivisionFilter> subdivide = vtkSmartPointer<vtkLoopSubdivisionFilter>::New();
	subdivide->SetNumberOfSubdivisions(tesselation_level);
	subdivide->SetInputConnection(ico->GetOutputPort());
	subdivide->Update();

	vtkSmartPointer<vtkPolyData> sphere_pre = vtkSmartPointer<vtkPolyData>::New();
	sphere_pre = subdivide->GetOutput();

	vtkSmartPointer<vtkTransform> trans_scale = vtkSmartPointer<vtkTransform> ::New();
	trans_scale->Scale(scale_factor, scale_factor, scale_factor);
	vtkSmartPointer<vtkMatrix4x4> matrixScale = trans_scale->GetMatrix();
	vtkSmartPointer<vtkTransformFilter> trans_filter_scale = vtkSmartPointer<vtkTransformFilter>::New();
	trans_filter_scale->SetTransform(trans_scale);
	trans_filter_scale->SetInputData(sphere_pre);//相机放缩 这个自适应方法可以
	trans_filter_scale->Update();

	vtkSmartPointer<vtkPolyData> sphere = trans_filter_scale->GetPolyDataOutput();

	vtkSmartPointer<vtkWorldPointPicker> worldPicker = vtkSmartPointer<vtkWorldPointPicker>::New();

	std::vector<Eigen::Vector3f, Eigen::aligned_allocator<Eigen::Vector3f>> cam_positions;

	cam_positions.resize(sphere->GetNumberOfPoints());
	for (vtkIdType i = 0; i < sphere->GetNumberOfPoints(); i++)
	{
		double cam_pos[3];
		sphere->GetPoint(i, cam_pos);
		cam_positions[i] = Eigen::Vector3f(float(cam_pos[0]), float(cam_pos[1]), float(cam_pos[2]));
		cam_positions[i].normalized();
	}

	for (const auto &cam_position : cam_positions)
	{
		PointCloudT::Ptr t(new PointCloudT);

		double cam_pos[3];

		cam_pos[0] = cam_position[0];
		cam_pos[1] = cam_position[1];
		cam_pos[2] = cam_position[2];
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);
		Eigen::Vector3f cam_pos_3f = cam_position;
		Eigen::Vector3f perp = cam_pos_3f.cross(cam_pos_3f.cross(Eigen::Vector3f::UnitY()));

		vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New();
		cam->SetFocalPoint(0, 0, 0);
		cam->SetViewUp(-perp[0], -perp[1], -perp[2]);
		cam->SetPosition(cam_pos);
		cam->SetViewAngle(view_angle);
		cam->Modified();

		vtkSmartPointer<vtkRenderer> render = vtkSmartPointer<vtkRenderer>::New();
		render->AddActor(actor);
		render->SetBackground(0, 0, 0);
		render->SetActiveCamera(cam);

		vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
		rw->AddRenderer(render);
		rw->SetSize(xres, yres);
		rw->SetWindowName("multiview");
		rw->SetOffScreenRendering(1);
		rw->Render();

		vtkSmartPointer<vtkWorldPointPicker> worldpicker = vtkSmartPointer<vtkWorldPointPicker>::New();
		double coords[3];

		for (int y = 0; y < yres; y++)
		{
			for (int x = 0; x < xres; x++)
			{
				double z = rw->GetZbufferDataAtPoint(x, y);
				if (z == 1)
				{
					continue;
				}
				else
				{
					worldpicker->Pick(x, y, z, render);
					worldpicker->GetPickPosition(coords);
					PointT tmp;
					tmp.x = coords[0];
					tmp.y = coords[1];
					tmp.z = coords[2];
					t->push_back(tmp);
				}
			}
		}
		if (t->size() != 0) {
			tem.push_back(t);
		}
	}
}
main.cpp

#include"HPR.h"
using namespace pcl;

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

int main()
{
	vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
	reader->SetFileName("C:/Users/chensi/Desktop/cup.stl");
	reader->Update();

	vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
	polydata = reader->GetOutput();

	std::vector<PointCloudT::Ptr> v_pc;

	get_template(polydata, v_pc);

	pcl::visualization::PCLVisualizer::Ptr view(new pcl::visualization::PCLVisualizer);
	view->setBackgroundColor(0, 0, 0);
	view->addCoordinateSystem(0.1f);

	for (int i = 1; i < v_pc.size();i++)
	{
		PointCloudT::Ptr tmp = v_pc[i];
		pcl::visualization::PointCloudColorHandlerCustom<PointT>tmp_color(tmp, 100, 255, 200);
		view->removeAllPointClouds();
		view->addPointCloud(tmp, tmp_color, "tmp");
		view->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "tmp");
		view->spinOnce(1000);
	}
	cout << v_pc.size() << endl;
	return 0;
}

结果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结论

本文给出了多视角提取给定模型可视点云的算法。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wdmcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值