Tinyply讀取ply文件並顯示點雲

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章