🌟bye_pcl_rs点云库🌟/Point Cloud Library
点云库仍然在开发中, 功能实现不完全/Unimplemented!!!
📝简介/Description
点云库专门用于2D/3D图像和点云处理。🚀 使用纯Rust ⚙️ 进行编写。
The Point Cloud Library (PCL) is a standalone, large scale, open project for 2D/3D image and point cloud processing.
Implemented in pure Rust.
👉快来体验PCL的强大功能,为你的研究添砖加瓦吧!💪💡
#点云库 #PCL #3D图像处理 #研究工具 #开源项目
📖参考/Citation
@InProceedings{Rusu_ICRA2011_PCL,
author = {Radu Bogdan Rusu and Steve Cousins},
title = {{3D is here: Point Cloud Library (PCL)}},
booktitle = {{IEEE International Conference on Robotics and Automation (ICRA)}},
month = {May 9-13},
year = {2011},
address = {Shanghai, China},
publisher = {IEEE}
}
🎉示例/Example
cargo run --example surfel_mapping
代码:
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(non_fmt_panics)]
#![allow(unused_mut)]
#![allow(unused_assignments)]
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![allow(rustdoc::missing_crate_level_docs)]
#![allow(unsafe_code)]
#![allow(clippy::undocumented_unsafe_blocks)]
#![allow(unused_must_use)]
#![allow(non_snake_case)]
#![allow(unused_doc_comments)]
use std::fs::create_dir_all;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Write};
use std::path::Path;
use std::sync::Arc;
use std::cell::{Ref, RefCell, RefMut};
use nalgebra::{
Const, DMatrix, DVector, Isometry3, Matrix, Matrix2, Matrix3, Matrix3x1, Matrix6, Point3,
Quaternion, Rotation3, SVector, Translation3, UnitQuaternion, Vector2, Vector3, Vector6,
VectorView3, ViewStorage,
};
use rand::Rng;
use rand_distr::{Distribution, Normal};
use bye_pcl_rs::{
common::{PointXYZRGB, PointCloud, PointXYZRGBNormal},
io::pcd_io,
kdtree::{KdTreeRust, PointXYZRGBWithId, PointXYZRGBNormalWithId},
surface::{MovingLeastSquares, PolygonMesh, GreedyProjectionTriangulation},
};
fn reconstruct_surface(input: &PointCloud<PointXYZRGB>, radius: f64, polynomial_order: usize) -> PointCloud<PointXYZRGBNormal> {
let mut mls = MovingLeastSquares::<PointXYZRGBNormal, PointXYZRGBNormal>::new();
let mut kdtree = KdTreeRust::<PointXYZRGBWithId>::new(true);
let input_arc = input.points.clone().into();
kdtree.set_input_cloud(input_arc, None);
mls.set_search_radius(radius);
mls.set_compute_normals(true);
mls.set_polynomial_order(polynomial_order);
let new_points: Vec<PointXYZRGBNormal> = input.points.clone().into_iter().map(|p| {
let mut new_point = PointXYZRGBNormal::default();
new_point.x = p.x;
new_point.y = p.y;
new_point.z = p.z;
new_point.rgb = p.rgb;
new_point
}).collect();
let arc_points = Arc::new(new_points);
mls.set_input_cloud(arc_points);
let mut output = PointCloud::<PointXYZRGBNormal>::default();
mls.process();
output=PointCloud::<PointXYZRGBNormal>::from_points_vec(mls.output.clone());
output
}
fn triangulate_mesh(surfels: &PointCloud<PointXYZRGBNormalWithId>) -> PolygonMesh {
let mut kdtree = KdTreeRust::<PointXYZRGBNormalWithId>::new(true);
let points: Vec<PointXYZRGBNormal> = surfels.points.iter().map(|p| p.point.clone()).collect();
let surfels_arc = Arc::new(points);
kdtree.set_input_cloud(surfels_arc, None);
let mut gp3 = GreedyProjectionTriangulation::<PointXYZRGBNormalWithId>::new();
let mut triangles = PolygonMesh::default();
gp3.set_search_radius(0.05);
gp3.set_mu(2.5);
gp3.set_maximum_nearest_neighbors(100);
gp3.set_maximum_surface_angle(std::f64::consts::PI / 4.0);
gp3.set_minimum_angle(std::f64::consts::PI / 18.0);
gp3.set_maximum_angle(2.0 * std::f64::consts::PI / 3.0);
gp3.set_normal_consistency(true);
gp3.input = Some(surfels.clone());
gp3.kdtree = kdtree;
gp3.perform_reconstruction(&mut triangles);
triangles
}
fn main() {
let path = "./assets/office1.ply";
let result = PointCloud::<PointXYZRGB>::load_from_ply(path);
assert!(result.is_ok(), "加载PLY文件失败: {:?}", result.err());
let point_cloud = result.unwrap();
assert!(!point_cloud.points.is_empty(), "点云数据为空");
println!("成功加载 {} 个点", point_cloud.points.len());
println!("正在计算法线 ... ");
let mls_radius = 0.05;
let polynomial_order = 2;
let point_cloud_with_normal = reconstruct_surface(&point_cloud, mls_radius, polynomial_order);
let mut surfels = PointCloud::<PointXYZRGBNormalWithId>::default();
surfels.points = point_cloud_with_normal.points.iter().enumerate().map(|(id, point)| {
PointXYZRGBNormalWithId {
id,
point: point.clone(),
}
}).collect();
surfels.is_dense = point_cloud_with_normal.is_dense;
println!("正在计算网格 ... ");
let mesh = triangulate_mesh(&surfels);
println!("三角化完成,网格中有 {} 个多边形", mesh.polygons.len());
println!("显示点云网格使用其他库, 例如bevy, pasture\n");
println!("unimplemented!()");
}