pcl1.91 官方文檔的位置http://docs.pointclouds.org/1.9.1/group__io.html
1. PCD 數據格式的了解
為什么要使用新的文件格式?
PCD文件格式並不意味着徹底改變,而只是為了補充現有的文件格式,該文件格式由於某種原因不支持PCL帶給nD點雲處理的某些擴展。
PCD不是第一個支持3D點雲數據的文件類型。特別是計算機圖形學和計算幾何學社區已經創建了多種格式來描述使用激光掃描儀獲取的任意多邊形和點雲。其中一些格式包括:
-
PLY-由Turk等人在斯坦福大學開發的多邊形文件格式
-
STL -3D Systems創建的立體光刻CAD軟件固有的文件格式
-
OBJ -Wavefront Technologies最初開發的一種幾何定義文件格式
-
X3D-用於表示3D計算機圖形數據的基於ISO標准的XML文件格式
上述所有文件格式都有一些缺點,這將在下一部分中進行解釋-這是自然的,因為它們是在發明感應技術和算法之前為不同的目的和在不同的時間創建的。
文件格式
文件格式標題
每個PCD文件都包含一個標頭,該標頭標識並聲明存儲在文件中的點雲數據的某些屬性。PCD的標頭必須以ASCII編碼。
注意
使用新行(\ n)分隔PCD文件中指定的每個標頭條目以及ascii點數據(見下文)。
從0.7版本開始,PCD標頭包含以下條目:
-
VERSION-指定PCD文件版本
-
FIELDS-指定點可以具有的每個維度/字段的名稱。例子:
FIELDS x y z # XYZ data FIELDS x y z rgb # XYZ + colors FIELDS x y z normal_x normal_y normal_z # XYZ + surface normals FIELDS j1 j2 j3 # moment invariants ... -
SIZE-指定每個維度的大小(以字節為單位)。例子:
-
無符號char / char有1個字節
-
無符號的short / short有2個字節
-
unsigned int / int / float有4個字節
-
double有8個字節
-
-
TYPE-將每個維度的類型指定為char。當前接受的類型是:
-
I-表示帶符號的類型int8(char),int16(short)和int32(int)
-
U-表示無符號類型uint8(unsigned char),uint16(unsigned short),uint32(unsigned int)
-
F-表示浮點類型
-
-
COUNT-指定每個維度有多少個元素。例如,x數據通常有1個元素,但是像VFH這樣的特征描述符 有308個。基本上,這是在每個點引入nD直方圖描述符並將它們視為單個連續內存塊的方法。默認情況下,如果不存在COUNT,則所有尺寸的計數均設置為1。
-
WIDTH-以點數指定點雲數據集的寬度。WIDTH具有兩個含義:
-
它可以為未組織的數據集指定雲中的點總數(等於POINTS,請參見下文);
-
它可以指定組織的點雲數據集的寬度(一行中的總點數)。
另請參閱HEIGHT。
注意
一個有組織的點雲數據集是賦予點雲類似於一個有組織的圖像(或矩陣)狀的結構,其中,數據被划分為行和列的名稱。這種點雲的示例包括來自立體攝像機或飛行時間攝像機的數據。有組織的數據集的優勢在於,通過了解相鄰點(例如,像素)之間的關系,最近鄰居操作會更加高效,從而加快了計算速度並降低了PCL中某些算法的成本。
例子:
WIDTH 640 # there are 640 points per line -
-
HEIGHT-以點數指定點雲數據集的高度。HEIGHT有兩個含義:
-
它可以指定有組織的點雲數據集的高度(總行數);
-
對於未組織的數據集,將其設置為1(從而用於檢查數據集是否已組織)。
例:
WIDTH 640 # Image-like organized structure, with 480 rows and 640 columns, HEIGHT 480 # thus 640*480=307200 points total in the dataset例:
WIDTH 307200 HEIGHT 1 # unorganized point cloud dataset with 307200 points -
-
VIEWPOINT-為數據集中的點指定采集視點。以后可能會用它來構建不同坐標系之間的變換,或者用於輔助需要一致方向的特征(例如表面法線)。
視點信息被指定為平移(tx ty tz)+四元數(qw qx qy qz)。默認值為:
VIEWPOINT 0 0 0 1 0 0 0 -
POINTS-指定雲中的總點數。從0.7版開始,它的用途有點多余,因此我們希望在將來的版本中將其刪除。
例:
POINTS 307200 # the total number of points in the cloud -
DATA-指定存儲點雲數據的數據類型。從0.7版開始,支持兩種數據類型:ascii和binary。有關更多詳細信息,請參見下一部分。
注意
標頭最后一行(DATA)之后的下一個字節被視為點雲數據的一部分,因此將被解釋為點雲數據。
警告
標頭條目必須按照上述順序精確指定,即:
VERSION
FIELDS SIZE TYPE COUNT WIDTH HEIGHT VIEWPOINT POINTS DATA
資料儲存類型
從0.7版開始,.PCD文件格式使用兩種不同的模式來存儲數據:
-
以ASCII形式,每個點都換行:
p_1 p_2 p_3 p_4 ... p_n
注意
從PCL版本1.0.1開始,NaN的字符串表示形式為“ nan”。
-
以二進制形式,其中數據是pcl :: PointCloud.points數組/向量的完整內存副本 。在Linux系統上,我們使用mmap / munmap 操作對數據進行最快的讀/寫訪問。
以簡單的ascii格式存儲點雲數據,將點,行,空格或制表符上的每個點分隔開,上面沒有任何其他字符,並以二進制轉儲格式存儲,這使我們能夠同時兼顧兩個方面的優點:速度,取決於基礎應用程序。ascii格式允許用戶打開 點雲文件並使用gnuplot等標准軟件工具對其進行繪制, 或使用sed,awk等工具對其進行操作。
2.pcd 文件的讀寫
1 #include<iostream> 2 #include<pcl/io/pcd_io.h> 3 #include<pcl/point_types.h> 4 5 int 6 main(int argc, char**argv) 7 { 8 //聲明點雲對象指針(點雲類型為XYZ點雲結構),並初始化該對象,pointcloud是一個泛型類,所以每次使用的記得申明 9 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); 10 // 11 int flatMeathod = 1; 12 //方式1 13 if (flatMeathod ==0) 14 { 15 printf("采用pcl::io::loadPCDFile<pcl::PointXYZ>的方式讀取 \n"); 16 17 18 //判斷文件是否存在 19 if (pcl::io::loadPCDFile<pcl::PointXYZ>("C:/Users/Admin/Desktop/PCL/bin/2/read_pcd/Debug/test_pcd.pcd", *cloud) == -1) 20 { 21 PCL_ERROR("could not find test_pcd.pcd"); 22 return -1; 23 } 24 } 25 //方式2 26 else 27 { 28 printf("采用pcl::PCLPointCloud2 的方式讀取"); 29 //整理需要先轉換為PCLPointCloud2類型 30 pcl::PCLPointCloud2 cloud2; 31 pcl::io::loadPCDFile("C:/Users/Admin/Desktop/PCL/bin/2/read_pcd/Debug/test_pcd.pcd", cloud2); 32 if (pcl::io::loadPCDFile("", cloud2) == -1) 33 { 34 return -1; 35 } 36 else 37 { 38 pcl::fromPCLPointCloud2(cloud2, *cloud); 39 } 40 41 42 } 43 for (size_t i = 0; i < cloud->points.size(); i++) 44 { 45 std::cout << " " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl; 46 } 47 return 0; 48 49 50 51 52 53 54 }
3 pcd 寫入
1 #include <iostream> 2 #include <pcl/io/pcd_io.h> 3 #include <pcl/point_types.h> 4 5 int 6 main(int argc,char**argv) 7 { 8 pcl::PointCloud<pcl::PointXYZ> cloud; 9 // 創建點雲 10 cloud.width=5; //點雲數據的寬度 11 cloud.height=1; //點雲數據的高度 12 cloud.is_dense=false;//是否為密度點雲 13 cloud.points.resize(cloud.width*cloud.height); 14 for(size_t i=0;i<cloud.points.size();++i) 15 { 16 cloud.points[i].x=1024*rand()/(RAND_MAX+1.0f); 17 cloud.points[i].y=1024*rand()/(RAND_MAX+1.0f); 18 cloud.points[i].z=1024*rand()/(RAND_MAX+1.0f); 19 } 20 pcl::io::savePCDFileASCII("test_pcd.pcd",cloud); 21 std::cerr<<"Saved "<<cloud.points.size()<<" data points to test_pcd.pcd."<<std::endl; 22 for(size_t i=0;i<cloud.points.size();++i) 23 std::cerr<<" "<<cloud.points[i].x<<" "<<cloud.points[i].y<<" "<<cloud.points[i].z<<std::endl; 24 return(0); 25 }
