文章目录
- 一、安装
- 1.1 下载PCL
- 1.2 安装PCL
- 1.3 安装OSGeo4W
- 二、配置
- 2.1 配置环境变量
- 2.2 配置VS2019
- 三、点云格式转换以及可视化
- 参考
一、安装
1.1 下载PCL
首先我们需要下载pcl1.11.0 ,这个版本与vs2019对应。
有两种下载方法:百度网盘、官网下载。二选一即可~
下载方法1:百度网盘
链接:https://pan.baidu.com/s/1tQEzhvY4HYw1OJw6W-0fOQ
提取码:qi8w
下载方法2:官网下载
- 官网链接: https://github.com/PointCloudLibrary/pcl/releases/tag/pcl-1.11.0
- 下载两个文件:
PCL-1.11.0-AllInOne-msvc2019-win64.exe
pcl-1.11.0-pdb-msvc2019-win64.zip
1.2 安装PCL
- 双击“
PCL-1.9.0-AllInOne-msvc2017-win64.exe
”进行安装
选择“Add PCL to the system PATH for all users
”,自动把路径添加到系统环境变量中。
在这里插入图片描述
默认是C:\Program Files\PCL 1.11.0
,也可以改到其他的路径,但是需要记住安装的根路径,方便后续对环境进行配置。
如果安装的过程中提示
path too long installer unable to modify path
, 不要慌,说明只是环境变量没有自动配置好,接下来我们手动配置即可。
- 解压“
pcl-1.11.0-pdb-msvc2019-win64.zip
”,将解压得到的文件夹中的内容添加“C:\Program Files\\PCL 1.11.0\bin
”中。
- 检测路径
C:\Program Files\PCL 1.11.0\3rdParty\OpenNI2
下是否安装了OpenNI2:
如果文件夹中只有下图红框标注的.msi
文件,则说明未安装OpenNI2,则需要点击该.msi
文件进行手动安装。
否则跳过这一步就可以啦。
点击该.msi
文件进行手动安装,注意安装的路径选择C:\Program Files\PCL 1.11.0\3rdParty\OpenNI2
1.3 安装OSGeo4W
- OSGeo4W下载地址
- 安装OSGeo4W
选择默认的安装路径(也可以自定义路径,但需要记住安装的根路径,方便后续添加环境变量)
选择https://ftp.osuosl.org
搜索框输入pdal
,点击skip
,选中图中版本。
开始安装各种依赖
安装完成后,如下图
二、配置
2.1 配置环境变量
- 搜索
查看高级系统设置
- 点击
环境变量
- 查看系统变量,已经有自动设置好的
PCL_ROOT
- 双击
Path
新建如下环境变量
%PCL_ROOT%\bin
%PCL_ROOT%\3rdParty\FLANN\bin
%PCL_ROOT%\3rdParty\VTK\bin
%PCL_ROOT%\3rdParty\Qhull\bin
%PCL_ROOT%\3rdParty\OpenNI2\Tools
%PCL_ROOT%\3rdParty\OpenNI2\Redist
C:\OSGeo4W\bin
- 点击确定,
重启
电脑后生效
2.2 配置VS2019
- 打开VS2019,创建一个名为
testPCL
的空项目
- 编译环境改为
X64,Release
版本。
视图
-其他窗口
-属性管理器
Release|x64
-添加新项目属性表
- 给属性表命名
- 双击新建的属性表
VC++ 目录
VC++ 目录
-包含目录/库目录
-下三角
-<编辑..>
包含目录
中添加以下7个目录:(注意版本和路径以及名称,建议点击右上角黄色的图标手动添加)
C:\Program Files\PCL 1.11.0\3rdParty\VTK\include\vtk-8.2
C:\Program Files\PCL 1.11.0\3rdParty\OpenNI2\Include
C:\Program Files\PCL 1.11.0\3rdParty\Qhull\include
C:\Program Files\PCL 1.11.0\3rdParty\FLANN\include
C:\Program Files\PCL 1.11.0\3rdParty\Eigen\eigen3
C:\Program Files\PCL 1.11.0\3rdParty\Boost\include\boost-1_73
C:\Program Files\PCL 1.11.0\include\pcl-1.11
库目录
中添加以下7个目录:
C:\Program Files\PCL 1.11.0\3rdParty\OpenNI2\Lib
C:\OSGeo4W\lib
C:\Program Files\PCL 1.11.0\3rdParty\VTK\lib
C:\Program Files\PCL 1.11.0\3rdParty\Qhull\lib
C:\Program Files\PCL 1.11.0\3rdParty\FLANN\lib
C:\Program Files\PCL 1.11.0\3rdParty\Boost\lib
C:\Program Files\PCL 1.11.0\lib
C/C++—>预处理器—>预处理器定义
- 点击
预处理定义
- 添加如下内容
BOOST_USE_WINDOWS_H
NOMINMAX
_CRT_SECURE_NO_DEPRECATE
C/C++ ->所有选项->SDL检查
- 在
属性页
中将SDL检查设为否
- 在
项目
也中将SDL检查设为否
链接器—>输入—>附加的依赖项
- 将
PCL 1.11.0\3rdParty\VTK\lib
和PCL 1.11.0\lib
以及C:\OSGeo4W\lib
这三个文件夹下的lib
文件的release
版本添加到附加依赖项中
pcl_common.lib
pcl_features.lib
pcl_filters.lib
pcl_io.lib
pcl_io_ply.lib
pcl_kdtree.lib
pcl_keypoints.lib
pcl_ml.lib
pcl_octree.lib
pcl_outofcore.lib
pcl_people.lib
pcl_recognition.lib
pcl_registration.lib
pcl_sample_consensus.lib
pcl_search.lib
pcl_segmentation.lib
pcl_stereo.lib
pcl_surface.lib
pcl_tracking.lib
pcl_visualization.lib
vtkChartsCore-8.2.lib
vtkCommonColor-8.2.lib
vtkCommonComputationalGeometry-8.2.lib
vtkCommonCore-8.2.lib
vtkCommonDataModel-8.2.lib
vtkCommonExecutionModel-8.2.lib
vtkCommonMath-8.2.lib
vtkCommonMisc-8.2.lib
vtkCommonSystem-8.2.lib
vtkCommonTransforms-8.2.lib
vtkDICOMParser-8.2.lib
vtkDomainsChemistry-8.2.lib
vtkDomainsChemistryOpenGL2-8.2.lib
vtkdoubleconversion-8.2.lib
vtkexodusII-8.2.lib
vtkexpat-8.2.lib
vtkFiltersAMR-8.2.lib
vtkFiltersCore-8.2.lib
vtkFiltersExtraction-8.2.lib
vtkFiltersFlowPaths-8.2.lib
vtkFiltersGeneral-8.2.lib
vtkFiltersGeneric-8.2.lib
vtkFiltersGeometry-8.2.lib
vtkFiltersHybrid-8.2.lib
vtkFiltersHyperTree-8.2.lib
vtkFiltersImaging-8.2.lib
vtkFiltersModeling-8.2.lib
vtkFiltersParallel-8.2.lib
vtkFiltersParallelImaging-8.2.lib
vtkFiltersPoints-8.2.lib
vtkFiltersProgrammable-8.2.lib
vtkFiltersSelection-8.2.lib
vtkFiltersSMP-8.2.lib
vtkFiltersSources-8.2.lib
vtkFiltersStatistics-8.2.lib
vtkFiltersTexture-8.2.lib
vtkFiltersTopology-8.2.lib
vtkFiltersVerdict-8.2.lib
vtkfreetype-8.2.lib
vtkGeovisCore-8.2.lib
vtkgl2ps-8.2.lib
vtkglew-8.2.lib
vtkGUISupportMFC-8.2.lib
vtkhdf5-8.2.lib
vtkhdf5_hl-8.2.lib
vtkImagingColor-8.2.lib
vtkImagingCore-8.2.lib
vtkImagingFourier-8.2.lib
vtkImagingGeneral-8.2.lib
vtkImagingHybrid-8.2.lib
vtkImagingMath-8.2.lib
vtkImagingMorphological-8.2.lib
vtkImagingSources-8.2.lib
vtkImagingStatistics-8.2.lib
vtkImagingStencil-8.2.lib
vtkInfovisCore-8.2.lib
vtkInfovisLayout-8.2.lib
vtkInteractionImage-8.2.lib
vtkInteractionStyle-8.2.lib
vtkInteractionWidgets-8.2.lib
vtkIOAMR-8.2.lib
vtkIOAsynchronous-8.2.lib
vtkIOCityGML-8.2.lib
vtkIOCore-8.2.lib
vtkIOEnSight-8.2.lib
vtkIOExodus-8.2.lib
vtkIOExport-8.2.lib
vtkIOExportOpenGL2-8.2.lib
vtkIOExportPDF-8.2.lib
vtkIOGeometry-8.2.lib
vtkIOImage-8.2.lib
vtkIOImport-8.2.lib
vtkIOInfovis-8.2.lib
vtkIOLegacy-8.2.lib
vtkIOLSDyna-8.2.lib
vtkIOMINC-8.2.lib
vtkIOMovie-8.2.lib
vtkIONetCDF-8.2.lib
vtkIOParallel-8.2.lib
vtkIOParallelXML-8.2.lib
vtkIOPLY-8.2.lib
vtkIOSegY-8.2.lib
vtkIOSQL-8.2.lib
vtkIOTecplotTable-8.2.lib
vtkIOVeraOut-8.2.lib
vtkIOVideo-8.2.lib
vtkIOXML-8.2.lib
vtkIOXMLParser-8.2.lib
vtkjpeg-8.2.lib
vtkjsoncpp-8.2.lib
vtklibharu-8.2.lib
vtklibxml2-8.2.lib
vtklz4-8.2.lib
vtklzma-8.2.lib
vtkmetaio-8.2.lib
vtkNetCDF-8.2.lib
vtkogg-8.2.lib
vtkParallelCore-8.2.lib
vtkpng-8.2.lib
vtkproj-8.2.lib
vtkpugixml-8.2.lib
vtkRenderingAnnotation-8.2.lib
vtkRenderingContext2D-8.2.lib
vtkRenderingContextOpenGL2-8.2.lib
vtkRenderingCore-8.2.lib
vtkRenderingExternal-8.2.lib
vtkRenderingFreeType-8.2.lib
vtkRenderingGL2PSOpenGL2-8.2.lib
vtkRenderingImage-8.2.lib
vtkRenderingLabel-8.2.lib
vtkRenderingLOD-8.2.lib
vtkRenderingOpenGL2-8.2.lib
vtkRenderingVolume-8.2.lib
vtkRenderingVolumeOpenGL2-8.2.lib
vtksqlite-8.2.lib
vtksys-8.2.lib
vtktheora-8.2.lib
vtktiff-8.2.lib
vtkverdict-8.2.lib
vtkViewsContext2D-8.2.lib
vtkViewsCore-8.2.lib
vtkViewsInfovis-8.2.lib
vtkzlib-8.2.lib
pdalcpp.lib
pdal_util.lib
libpdal_plugin_writer_pgpointcloud.lib
libpdal_plugin_reader_pgpointcloud.lib
libpdal_plugin_kernel_fauxplugin.lib
liblas_c.lib
liblas.lib
laszip3.lib
三、点云格式转换以及可视化
PCL
各种三维格式转PCD
文件(ply、stl、xyz、obj、asc、txt、las、laz、bin
)
//#pragma execution_character_set("utf-8")//解决中文
#include <Winsock2.h>
#include <windows.h>
//pcd
#include <pcl/io/pcd_io.h>
//ply
#include <pcl/io/ply_io.h>
//stl
#include <pcl/io/vtk_lib_io.h>
//mesh
#include <vtkTriangleFilter.h>
#include <pcl/common/common.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pdal/PointTable.hpp>
#include <pdal/Options.hpp>
#include <pdal/io/LasHeader.hpp>
#include <pdal/io/LasReader.hpp>
#include <string>
using namespace std;
typedef pcl::PointXYZ PointT;
typedef pcl::PointXYZI PointTI;
void ply2pcd(std::string filename, pcl::PointCloud<PointT>::Ptr& cloud)
{
pcl::PLYReader reader;
reader.read<PointT>(filename, *cloud);
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
void stl2pcd(std::string filename, pcl::PointCloud<PointT>::Ptr& cloud)
{
//读取STL格式模型
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
polydata = reader->GetOutput();
polydata->GetNumberOfPoints();
//从poly转pcd
pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
void obj2pcd(std::string filename, pcl::PointCloud<PointT>::Ptr& cloud)
{
//读取STL格式模型
vtkSmartPointer<vtkPolyData> polydata;
vtkSmartPointer<vtkOBJReader> reader = vtkSmartPointer<vtkOBJReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
polydata = reader->GetOutput();
pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
struct tagPOINT_3D
{
float x;
float y;
float z;
float I;
};
void txt2pcd(std::string filename, pcl::PointCloud<PointT>::Ptr& cloud)
{
int number_Txt;
string line;
tagPOINT_3D TxtPoint;
vector<tagPOINT_3D> m_vTxtPoints;
//输入txt文件
ifstream input(filename);
//读取文件中的有效值
while (getline(input, line)) {
tagPOINT_3D TxtPoint;
replace(line.begin(), line.end(), ',', ' ');//将逗号替换为空格
istringstream record(line);
record >> TxtPoint.x;
record >> TxtPoint.y;
record >> TxtPoint.z;
//record >> TxtPoint.I;
//先将数据写入m_vTxtPoints
m_vTxtPoints.push_back(TxtPoint);
}
number_Txt = m_vTxtPoints.size();
// 设置pcd文件属性
cloud->width = number_Txt;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
//将m_vTxtPoints数据写入pcd文件
for (size_t i = 0; i < cloud->points.size(); ++i)
{
cloud->points[i].x = m_vTxtPoints[i].x;
cloud->points[i].y = m_vTxtPoints[i].y;
cloud->points[i].z = m_vTxtPoints[i].z;
//cloud->points[i].intensity = m_vTxtPoints[i].I;
}
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
//导入文件
bool
loadCloud(const std::string& filename, pcl::PointCloud<PointT>& cloud)
{
std::ifstream fs;
fs.open(filename.c_str(), std::ios::binary);
if (!fs.is_open() || fs.fail())
{
PCL_ERROR("Could not open file '%s'! Error : %s\n", filename.c_str(), strerror(errno));
fs.close();
return (false);
}
std::string line;
std::vector<std::string> st;
while (!fs.eof())
{
std::getline(fs, line);
//忽略空行
if (line.empty())
continue;
// 标记线
boost::trim(line);
boost::split(st, line, boost::is_any_of("\t\r "), boost::token_compress_on);
if (st.size() != 3)
continue;
//将数据写入pcd文件
cloud.push_back(PointT(float(atof(st[0].c_str())), float(atof(st[1].c_str())), float(atof(st[2].c_str()))));
}
fs.close();
//设置pcd文件属性
cloud.width = cloud.size(); cloud.height = 1; cloud.is_dense = true;
return (true);
}
void xyz2pcd(std::string filename, pcl::PointCloud<PointT>::Ptr& cloud)
{
//读取xyz格式模型
if (!loadCloud(filename, *cloud))
cout << filename << "读取失败" << endl;
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
void bin2pcd(std::string filename, pcl::PointCloud<PointTI>::Ptr& cloud)
{
// load point cloud
fstream input(filename.c_str(), ios::in | ios::binary);
if (!input.good()) {
cerr << "Could not read file: " << filename << endl;
exit(EXIT_FAILURE);
}
input.seekg(0, ios::beg);
//pcl::PointCloud<PointTI>::Ptr points(new pcl::PointCloud<PointXYZI>);
int i;
for (i = 0; input.good() && !input.eof(); i++) {
pcl::PointXYZI point;
input.read((char*)&point.x, 3 * sizeof(float));
input.read((char*)&point.intensity, sizeof(float));
cloud->push_back(point);
}
input.close();
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
void las2pcd(const std::string filename, pcl::PointCloud<PointTI>::Ptr& cloud) {
//中文可能会有乱码
cout << "读取" << filename << "..." << endl;
pdal::Option las_opt("filename", filename);
pdal::Options las_opts;
las_opts.add(las_opt);
pdal::PointTable table;
pdal::LasReader las_reader;
las_reader.setOptions(las_opts);
las_reader.prepare(table);
pdal::PointViewSet point_view_set = las_reader.execute(table);
pdal::PointViewPtr point_view = *point_view_set.begin();
pdal::Dimension::IdList dims = point_view->dims();
pdal::LasHeader las_header = las_reader.header();
//头文件信息
unsigned int PointCount = las_header.pointCount();
double scale_x = las_header.scaleX();
double scale_y = las_header.scaleY();
double scale_z = las_header.scaleZ();
double offset_x = las_header.offsetX();
double offset_y = las_header.offsetY();
double offset_z = las_header.offsetZ();
//读点
unsigned int n_features = las_header.pointCount();
int count = 0;
for (pdal::PointId id = 0; id < point_view->size(); ++id)
{
double x = point_view->getFieldAs<double>(pdal::Dimension::Id::X, id);
double y = point_view->getFieldAs<double>(pdal::Dimension::Id::Y, id);
double z = point_view->getFieldAs<double>(pdal::Dimension::Id::Z, id);
double intensity = point_view->getFieldAs<double>(pdal::Dimension::Id::Intensity, id);
PointTI point(x, y, z, intensity);
cloud->push_back(point);
}
//用对应的文件名保存pcd文件
std::string pp = boost::filesystem::path(filename).filename().string();
string name = pp.substr(0, pp.rfind("."));
std::string pcdfilename = name.append(".pcd");
cout << pcdfilename << endl;
pcl::io::savePCDFileASCII(pcdfilename, *cloud);
//依据需要选择保存的格式
//pcl::io::savePCDFileBinary(pcdfilename, *cloud);
if (!cloud->empty())
{
cout << filename << "转换完成" << endl;
}
}
int
main(int argc, char* argv[]) {
pcl::PointCloud<pcl::PointXYZI>::Ptr lascloud(new pcl::PointCloud<pcl::PointXYZI>);
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
string file0 = "E:\\VS2019Projects\\PCL\\2pcd\\Data1\\bunny.ply";
//ply2pcd(file0, cloud);
string file1 = "E:\\VS2019Projects\\PCL\\2pcd\\Data1\\AfricanAnimals.stl";
//stl2pcd(file1, cloud);
string file2 = "E:\\dataset\\PCL\\kitti_000008_points.obj";
obj2pcd(file2, cloud);
string file3 = "E:\\VS2019Projects\\PCL\\2pcd\\Data1\\dragon.txt";
//txt2pcd(file3, cloud);
string file4 = "E:\\VS2019Projects\\PCL\\2pcd\\Data1\\目标1.asc";
//txt2pcd(file4, cloud);
string file5 = "E:\\VS2019Projects\\PCL\\2pcd\\Data1\\crystal_4000.xyz";
//xyz2pcd(file5, cloud);
string file6 = "E:\\VS2019Projects\\PCL\\2pcd\\data\\000000.bin";
// bin2pcd(file6, lascloud);
//las2pcd(file, lascloud, true);
//--------------------------------------可视化--------------------------
pcl::visualization::PCLVisualizer viewer;
viewer.addPointCloud<PointT>(cloud, "cloud");
viewer.addCoordinateSystem();
while (!viewer.wasStopped())
{
viewer.spinOnce(100);
}
//清空内存
cloud->points.clear();
}
以obj
转pcd
文件为例
运行效果如下:
参考
win10+vs2019+pcl1.11.0安装教程_a_zhua66的博客-CSDN博客_vs pcl1.11
配置PCL过程中提示 path too long installer unable to modify path解决_Quelquefois的博客-CSDN博客_pcl path too long
https://github.com/PointCloudLibrary/pcl/releases/tag/pcl-1.11.0
PCL 各种三维格式转PCD文件(ply、stl、xyz、obj、asc、txt、las、laz、bin)_stay hungry foolish的博客-CSDN博客_pcd格式转换
最具体和最简单的PDAL库配置及在VS2019上测试_stay hungry foolish的博客-CSDN博客_osgeo4w安装liblas