Introduction
本篇文章主要介紹了使用Tinyply讀取點雲並顯示,其中也包含了ply文件的簡單介紹,讀取ply文件的兩種方式及其優缺點,以及顯示點雲部分。
PLY文件簡介
PLY爲Polygon File Format的首字母縮寫,是Stanford大學開發的一套三維mesh模型數據格式,又稱Stanford Triangle Format,PLY格式描述了一個3D對象,這個對象包含了頂點、面、和其他元素的集合,以及可以附加到這些元素的顏色和法線方向等屬性。
如何讀取Ply文件
目前讀取PLY文件有很多種方式,最常見的如PCL,在PCL裏有可以直接讀取點雲的模塊,使用時只需要包含頭文件
#include <pcl/io/ply_io.h>
其讀取PLY文件如下所示:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// Fill in the cloud data
if (pcl::io::loadPLYFile(argv[1], *cloud) < 0)
{
PCL_ERROR("Error loading cloud %s.\n", argv[1]);
return (-1);
}
但是PCL庫過於龐大,而且配置起來比較麻煩,所以如果只是爲了讀取點雲數據的話,我們可以使用更爲小巧、方便、零依賴的Tinyply.
我們可以通過在github上搜索tinyply找到,如下圖所示:
使用時只需把以下頭文件和cpp文件下載下來即可:
其中example.cpp裏有如何讀寫ply文件的例子,在實際使用中可對代碼做稍微調整即可。
以下是使用Tinyply讀取ply文件的代碼:
void PlyReader::ReadPlyFile(const std::string & filepath)
{
try
{
std::ifstream ss(filepath, std::ios::binary);
if (ss.fail())
{
throw std::runtime_error("failed to open " + filepath);
}
tinyply::PlyFile file;
file.parse_header(ss);
std::shared_ptr<tinyply::PlyData> vertices, colors;
try
{
vertices = file.request_properties_from_element("vertex", { "x", "y", "z" });
}
catch (const std::exception & e)
{
std::cerr << "tinyply exception: " << e.what() << std::endl;
}
try
{
colors = file.request_properties_from_element("vertex", { "red", "green", "blue" });
}
catch (const std::exception & e)
{
std::cerr << "tinyply exception: " << e.what() << std::endl;
}
file.read(ss);
if (vertices)
{
std::cout << "\tRead " << vertices->count << " total vertices " << std::endl;
}
for (int i = 0; i < colors->buffer.size_bytes(); i = i + 3)
{
unsigned char temp = colors->buffer.get()[i];
colors->buffer.get()[i] = colors->buffer.get()[i + 2];
colors->buffer.get()[i + 2] = temp;
}
m_spPclDisplayInReader->SendPointCloud((float*)vertices->buffer.get(), (unsigned char*)colors->buffer.get(), vertices->count);
}
catch (const std::exception & e)
{
std::cerr << "Caught tinyply exception: " << e.what() << std::endl;
}
這是我在讀取ply文件示例中使用到的代碼,其中去掉了法線,面等屬性的讀取,只讀取了頂點和其顏色並顯示,PlyReader是我對tinyply的一個封裝類,m_spPclDisplayInReader是Qt顯示時候所使用的一個OpenGL控件。
顯示點雲
點雲顯示使用Qt的OpenGL即可,我定義的顯示類如下所示
class PCLDisplay : public QOpenGLWidget
{
public:
PCLDisplay(QWidget* parent = nullptr);
~PCLDisplay();
int SendPointCloud(float* Xi_pPositions, unsigned char *Xi_pColors, size_t Xi_pointSize);
protected:
void initializeGL();
void paintGL();
private:
std::vector<STPoint> m_vecPoints;
std::mutex m_mutex;
};
整體效果如下:
工程與代碼
系統環境: Win10 pro/VS2015/Qt5.8.0
Source Code: https://github.com/yazhouzheng/TinyPlyReaderTest.git
參考
Ply介紹: http://paulbourke.net/dataformats/ply/
https://github.com/ddiakopoulos/tinyply
https://doc.qt.io/qt-5/qopenglwidget.html
https://github.com/PointCloudLibrary/pcl/blob/master/io/include/pcl/io/ply_io.h