点云三维重建主要有:
delaunay
- MC
- Poisson
- Stich
- Level set
网格主要用于计算机图形学中,有三角、四角网格等很多种。
计算机图形学中的网格处理绝大部分都是基于三角网格的,三角网格在图形学和三维建模中使用的非常广泛,用来模拟复杂物体的表面,如建筑、车辆、动物等,你看下图中的兔子、球等模型都是基于三角网格的
三角形表示网格也叫三角剖分。它有如下几个优点:
三角网格稳定性强。
三角网格比较简单(主要原因),实际上三角网格是最简单的网格类型之一,可以非常方便并且快速生成,在非结构化网格中最常见。而且相对于一般多边形网格,许多操作对三角网格更容易。
目前点云进行网格生成一般分为两大类方法:
插值法。顾名思义,也就是重建的曲面都是通过原始的数据点得到的
逼近法。用分片线性曲面或其他曲面来逼近原始数据点,得到的重建曲面是原始点集的一个逼近。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//#define FILE_PATH "xiaomianpian.XYZN"
//#define FILE_PATH "2DpointDatas.txt"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FILE_PATH "sxiaomianpian.XYZN"
/
---------------读取txt文件-------------------
void CreateCloudFromTxt(const std::string& file_path, pcl::PointCloud::Ptr cloud, pcl::PointCloud::Ptr normals)
{
std::ifstream file(file_path.c_str());//c_str():生成一个const char*指针,指向以空字符终止的数组。
std::string line;
pcl::PointXYZ point;
pcl::Normal nPoint;
int index = 0;
while (getline(file, line)) {
std::stringstream ss(line);
ss >> point.x;
ss >> point.y;
ss >> point.z;
ss >> nPoint.normal_x;
ss >> nPoint.normal_y;
ss >> nPoint.normal_z;
cloud->push_back(point);
normals->push_back(nPoint);
//printf("%f,%f,%f\n", point.x, point.y, point.z);
}
file.close();
printf("size %ld\n", cloud->size());
}
int main(int argc, char** argv)
{
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
//pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
//pcl::io::loadPCDFile(FILE_PATH, *cloud);
pcl::PointCloud::Ptr normals(new pcl::PointCloud); //存储估计的法线
CreateCloudFromTxt(FILE_PATH, cloud, normals);
//CreateCloudFromTxt(FILE_PATH, cloud);
// printf("size %d\n", cloud->size());
//pcl::visualization::PCLVisualizer viewer("viewer");
//viewer.addPointCloud(cloud);
//viewer.spin();
// Normal estimation*
//pcl::NormalEstimation n; //法线估计对象
//pcl::PointCloud::Ptr normals(new pcl::PointCloud); //存储估计的法线
//pcl::search::KdTree::Ptr tree(new pcl::search::KdTree); //定义kd树指针
//tree->setInputCloud(cloud); ///用cloud构建tree对象
//n.setInputCloud(cloud);
//n.setSearchMethod(tree);
//n.setKSearch(20);
//n.compute(*normals); 估计法线存储到其中
//* normals should not contain the point normals + surface curvatures
printf("normals=========\n");
// Concatenate the XYZ and normal fields*
pcl::PointCloud::Ptr cloud_with_normals(new pcl::PointCloud);
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals); //连接字段
//* cloud_with_normals = cloud + normals
printf("111normals=========\n");
//定义搜索树对象
pcl::search::KdTree::Ptr tree2(new pcl::search::KdTree);
tree2->setInputCloud(cloud_with_normals); //点云构建搜索树
printf("22 normals=========\n");
// Initialize objects
pcl::GreedyProjectionTriangulation gp3; //定义三角化对象
pcl::PolygonMesh triangles; //存储最终三角化的网络模型
附加顶点信息
//std::vector parts = gp3.getPartIDs();
//std::vector states = gp3.getPointStates();
std::cout << "Triangling..." << std::endl;
gp3.setSearchRadius(10);//设置连接点之间的最大距离(即为三角形最大边长)为0.025
std::cout << "1" << std::endl;
gp3.setMu(1);//设置被样本点搜索其邻近点的最远距离为2.5,为了适应点云密度的变化
std::cout << "2" << std::endl;
gp3.setMaximumNearestNeighbors(100);//设置样本点可搜索的邻域个数
std::cout << "3" << std::endl;
gp3.setMaximumSurfaceAngle(M_PI / 12);//45,180/4,设置某点法线方向偏离样本点法线方向的最大角度为45度
std::cout << "4" << std::endl;
gp3.setMinimumAngle(M_PI / 18);//10,180/18,设置三角化后得到三角形内角最小角度为10度
std::cout << "5" << std::endl;
gp3.setMaximumAngle(2 * M_PI / 12);//120,2*180/3,设置三角化后得到三角形内角最大角度为120度
std::cout << "6" << std::endl;
gp3.setNormalConsistency(true); //设置该参数保证法线朝向一致
std::cout << "7" << std::endl;
gp3.setInputCloud(cloud_with_normals);
std::cout << "8" << std::endl;
gp3.setSearchMethod(tree2);//设置搜索方式tree2
std::cout << "Triangling..." << std::endl;
gp3.reconstruct(triangles);//重建提取三角化
std::cout << "Finshed..." << std::endl;
pcl::io::saveVTKFile("wenwu_result.vtk", triangles);
//std::cout << "Done..." << std::endl;
std::cout << "Saved..." << std::endl;
pcl::io::savePolygonFile("wenwu_result.stl", triangles);
//std::vector parts = gp3.getPartIDs();//附加定点信息
//std::vector states = gp3.getPointStates();
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("可视化"));//三维可视化窗口
viewer->setBackgroundColor(0, 0, 0);
viewer->addPolygonMesh(triangles, "my");
viewer->addCoordinateSystem(50.0);
viewer->initCameraParameters();
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
std::cout << "Done..." << std::endl;
//pcl::io::saveVTKFile("mianpian.vtk", triangles);
//pcl::io::loadPolygonFile(const std::string &file_name, pcl::PolygonMesh& mesh);
printf("saveVTKFile=========\n");
system("pause");
return 0;
}
void saveSTL(vtkPolyData* StlPolyData)
{
vtkNew stlWriter;
stlWriter->SetFileName("./db-out.stl");
stlWriter->SetInputData((vtkDataObject *)StlPolyData );
stlWriter->Update();
stlWriter->Write();
}
int main()
{
//vtkSmartPointer vertices = vtkSmartPointer::New(); //_存放细胞顶点,用于渲染(显示点云所必须的)
vtkSmartPointer polyData = vtkSmartPointer::New();
//vtkSmartPointer pointMapper = vtkSmartPointer::New();
//vtkSmartPointer pointActor = vtkSmartPointer::New();
//vtkSmartPointer ren1 = vtkSmartPointer< vtkRenderer>::New();
//vtkSmartPointer renWin = vtkSmartPointer::New();
//vtkSmartPointer iren = vtkSmartPointer::New();
//vtkSmartPointer istyle = vtkSmartPointer::New();
vtkSmartPointer m_Points = vtkSmartPointer::New();
//_读进点云数据信息
ifstream infile(FILE_PATH, ios::in);
double x, y, z;
char line[128];
int i = 0;
while (infile.getline(line, sizeof(line)))
{
stringstream ss(line);
ss >> x;
ss >> y;
ss >> z;
m_Points->InsertPoint(i, x, y, z); //_加入点信息
///vertices->InsertNextCell(1); //_加入细胞顶点信息----用于渲染点集
//vertices->InsertCellPoint(i);
i++;
}
infile.close();
//_创建待显示数据源
polyData->SetPoints(m_Points); //_设置点集
// Triangulate the grid points
vtkSmartPointer delaunay =
vtkSmartPointer::New();
delaunay->SetInputData(polyData);
delaunay->SetAlpha(10);
//delaunay->SetTolerance(0.1);
delaunay->Update();
saveSTL(delaunay->GetOutput());
// Visualize
vtkSmartPointer colors =
vtkSmartPointer::New();
vtkSmartPointer meshMapper =
vtkSmartPointer::New();
meshMapper->SetInputConnection(delaunay->GetOutputPort());
vtkSmartPointer meshActor =
vtkSmartPointer::New();
meshActor->SetMapper(meshMapper);
//meshActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());
meshActor->GetProperty()->EdgeVisibilityOn();
vtkSmartPointer glyphFilter =
vtkSmartPointer::New();
glyphFilter->SetInputData(polyData);
vtkSmartPointer pointMapper =
vtkSmartPointer::New();
pointMapper->SetInputConnection(glyphFilter->GetOutputPort());
vtkSmartPointer pointActor =
vtkSmartPointer::New();
//pointActor->GetProperty()->SetColor(colors->GetColor3d("Tomato").GetData());
pointActor->GetProperty()->SetPointSize(5);
pointActor->SetMapper(pointMapper);
vtkSmartPointer renderer =
vtkSmartPointer::New();
vtkSmartPointer renderWindow =
vtkSmartPointer::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer renderWindowInteractor =
vtkSmartPointer::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(meshActor);
renderer->AddActor(pointActor);
//renderer->SetBackground(colors->GetColor3d("Mint").GetData());
renderWindow->Render();
renderWindowInteractor->Start();
}
显示点云,非三角化
pcl::PointCloud cloud;
vtkSmartPointerpoints = vtkSmartPointer::New();//点数据
vtkSmartPointer vertices = vtkSmartPointer::New();
int count = cloud.points.size();
std::cout << "old point s count : " << count << " " << std::endl;
for (int i = 0; i < count; i++)
{
//定义存储顶点索引的中间变量,类似Int、long类型
vtkIdType pointId[1];
//将每个点的坐标加入vtkPoints,InsertNextPoint()返回加入点的索引号
pointId[0] = points->InsertNextPoint(cloud.points[i].x, cloud.points[i].y, cloud.points[i].z);
//为每个坐标点分别创建一个顶点,顶点是单元类型里面的一种
vertices->InsertNextCell(1, pointId);
}
//指定数据的几何结构(由points指定)和拓扑结构(由vertices指定)
polyData->SetPoints(points);
polyData->SetVerts(vertices);