PointXYZRGB点云与meshcolor网格互转

PointXYZRGB转meshcolor

参考:如何使用PCL将XYZRGB点云转换为彩色mesh模型

#include <iostream>
#include <string>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/surface/poisson.h>
#include <pcl/visualization/pcl_visualizer.h>


void PointXYZRGB2meshcolor(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud)
{
	pcl::NormalEstimationOMP<pcl::PointXYZRGB, pcl::Normal> ne;
	ne.setNumberOfThreads(8);
	ne.setInputCloud(cloud);
	ne.setKSearch(10);
	Eigen::Vector4f centroid;
	compute3DCentroid(*cloud, centroid);
	ne.setViewPoint(centroid[0], centroid[1], centroid[2]);//将向量计算原点置于点云中心

	pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
	ne.compute(*cloud_normals);

	//将法向量反向
	for (size_t i = 0; i < cloud_normals->size(); ++i)
	{
		cloud_normals->points[i].normal_x *= -1;
		cloud_normals->points[i].normal_y *= -1;
		cloud_normals->points[i].normal_z *= -1;
	}

	//融合RGB点云和法向
	pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr cloud_smoothed_normals(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
	pcl::concatenateFields(*cloud, *cloud_normals, *cloud_smoothed_normals);

	//泊松重建
	pcl::Poisson<pcl::PointXYZRGBNormal> poisson;
	poisson.setDegree(2);
	poisson.setDepth(8);
	poisson.setSolverDivide(8);
	poisson.setIsoDivide(8);
	poisson.setConfidence(false);
	poisson.setManifold(false);
	poisson.setOutputPolygons(false);
	poisson.setInputCloud(cloud_smoothed_normals);
	pcl::PolygonMesh mesh;
	poisson.reconstruct(mesh);

	//给mesh染色
	pcl::PointCloud<pcl::PointXYZRGB> cloud_color_mesh;
	pcl::fromPCLPointCloud2(mesh.cloud, cloud_color_mesh);

	pcl::KdTreeFLANN<pcl::PointXYZRGB> kdtree;
	kdtree.setInputCloud(cloud); //使用kdtree在原RGB点云上建立一个搜索索引

	int K = 10;
	std::vector<int> pointIdxNKNSearch(K);
	std::vector<float> pointNKNSquaredDistance(K);
	for (int i = 0; i < cloud_color_mesh.points.size(); ++i)
	{
		uint8_t r = 0, g = 0, b = 0;
		int sum_r = 0, sum_g = 0, sum_b = 0;
		float dist = 0.0;

		if (kdtree.nearestKSearch(cloud_color_mesh.points[i], K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0) //对mesh上的每一个点都搜索对应原RGB点云上的临近点
		{	//求得这些对应临近点的RGB通道均值,作为mesh上那个点的颜色信息
			for (int j = 0; j < pointIdxNKNSearch.size(); ++j)
			{
				r = cloud->points[pointIdxNKNSearch[j]].r;
				g = cloud->points[pointIdxNKNSearch[j]].g;
				b = cloud->points[pointIdxNKNSearch[j]].b;

				sum_r += int(r);
				sum_g += int(g);
				sum_b += int(b);
				dist += 1.0 / pointNKNSquaredDistance[j];
			}
		}

		cloud_color_mesh.points[i].r = int(sum_r / pointIdxNKNSearch.size() + 0.5);
		cloud_color_mesh.points[i].g = int(sum_g / pointIdxNKNSearch.size() + 0.5);
		cloud_color_mesh.points[i].b = int(sum_b / pointIdxNKNSearch.size() + 0.5);
	}

	pcl::toPCLPointCloud2(cloud_color_mesh, mesh.cloud);
	pcl::io::savePLYFile("mesh.ply", mesh);
	
	pcl::visualization::PCLVisualizer viewer("viewer");
	viewer.addPolygonMesh(mesh);
	while (!viewer.wasStopped())
	{
		viewer.spinOnce(100);
	}
}


int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::io::loadPCDFile("bunny_color.pcd", *cloud);

	PointXYZRGB2meshcolor(cloud);
	return 0;
}

在这里插入图片描述

meshcolor转PointXYZRGB

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/visualization/pcl_visualizer.h>


void meshcolor2PointXYZRGB(pcl::PolygonMesh mesh)
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
	pcl::io::savePCDFile("bunny_cloud.pcd", *cloud);
	pcl::io::savePLYFile("bunny_cloud.ply", *cloud);

	std::ofstream outfile;
	outfile.open("bunny_cloud.txt");
	for (size_t i = 0; i < cloud->size(); i++)
	{
		pcl::PointXYZRGB p = cloud->points[i];
		outfile << p.x << " " << p.y << " " << p.z << " " << (int)p.r << " " << (int)p.g << " " << (int)p.b << std::endl;
	}
	outfile.close();

	pcl::visualization::PCLVisualizer viewer("Viewer");
	viewer.addPointCloud(cloud, "cloud");
	while (!viewer.wasStopped())
	{
		viewer.spinOnce(100);
	}
}


int main(int argc, char** argv)
{
	pcl::PolygonMesh mesh;
	pcl::io::loadPLYFile("mesh.ply", mesh);

	meshcolor2PointXYZRGB(mesh);
	return 0;
}

在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在OpenCvSharp中,点云网格之间的换可以使用pcl库(Point Cloud Library)来实现。具体步骤如下: 1. 将点云数据换为pcl中的PointCloud类对象。 ``` using PointCloud = PCL.PointCloud<PCL.PointXYZ>; PointCloud cloud = new PointCloud(); cloud.Width = pointCloud.Width; cloud.Height = pointCloud.Height; cloud.Points.Capacity = pointCloud.Width * pointCloud.Height; for (int i = 0; i < pointCloud.Height; i++) { for (int j = 0; j < pointCloud.Width; j++) { Vector3 point = pointCloud[i, j]; cloud.Points.Add(new PCL.PointXYZ(point.X, point.Y, point.Z)); } } ``` 其中,pointCloud是一个Mat对象,存储了点云数据。 2. 使用pcl库中的Poisson方法将点云数据换为网格数据。 ``` using PolygonMesh = PCL.PolygonMesh; PolygonMesh mesh = new PolygonMesh(); PCL.Poisson<PointXYZ, Normal> poisson = new PCL.Poisson<PointXYZ, Normal>(); poisson.SetDepth(8); poisson.SetSolverDivide(8); poisson.InputCloud = cloud; poisson.Reconstruct(mesh); ``` 3. 将pcl中的PolygonMesh对象换为OpenCvSharp中的网格对象。 ``` using Mesh = OpenCvSharp.Mesh; Mesh opencvMesh = new Mesh(); int vertexCount = mesh.Cloud.Points.Count; int triangleCount = mesh.Polygons.Count; opencvMesh.Vertices.SetSize(vertexCount); opencvMesh.Triangles.SetSize(triangleCount); for (int i = 0; i < vertexCount; i++) { PCL.PointXYZ pclVertex = mesh.Cloud.Points[i]; Vector3 opencvVertex = new Vector3((float)pclVertex.X, (float)pclVertex.Y, (float)pclVertex.Z); opencvMesh.Vertices.SetVec3fAt(i, opencvVertex); } for (int i = 0; i < triangleCount; i++) { PCL.Vertices vertices = mesh.Polygons[i].Vertices; opencvMesh.Triangles.SetPointAt(i, 0, vertices[0]); opencvMesh.Triangles.SetPointAt(i, 1, vertices[1]); opencvMesh.Triangles.SetPointAt(i, 2, vertices[2]); } ``` 其中,pcl中的PolygonMesh对象存储了三角形网格的顶点和索引信息,可以通过Vertices和Polygons属性进行访问。OpenCvSharp中的Mesh对象类似,可以通过Vertices和Triangles属性进行访问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

给算法爸爸上香

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

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

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

打赏作者

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

抵扣说明:

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

余额充值