點雲數據可以用ASCII碼的形式存儲在PCD文件中(關於該格式的描述可以參考鏈接:The PCD (Point Cloud Data) file format)。為了生成三維點雲數據,在excel中用rand()函數生成200行0-1的小數,ABC三列分別代表空間點的xyz坐標。
# .PCD v.7 - Point Cloud Data file format VERSION .7 FIELDS x y z SIZE 4 4 4 TYPE F F F COUNT 1 1 1 WIDTH 200 HEIGHT 1 VIEWPOINT 0 0 0 1 0 0 0 POINTS 200 DATA ascii 0.88071666 0.369209703 0.062937221 0.06418104 0.579762553 0.221359779 ... ... 0.640053058 0.480279041 0.843647334 0.245554712 0.825770496 0.626442137
進行點雲的變換主要用到的函數是pcl::transformPointCloud,函數原型為:
void pcl::transformPointCloud(const pcl::PointCloud< PointT > & cloud_in,
pcl::PointCloud< PointT > & cloud_out,
const Eigen::Matrix4f & transform )
參數中cloud_in為源點雲,cloud_out為變換后的點雲,transform為變換矩陣。下面的代碼對源點雲繞Z軸旋轉45°,然后沿X軸平移了2.5個單位:
#include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_cloud.h> #include <pcl/common/transforms.h> //allows us to use pcl::transformPointCloud function #include <pcl/visualization/pcl_visualizer.h> // This is the main function int main (int argc, char** argv) { //creates a PointCloud<PointXYZ> boost shared pointer and initializes it. pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZ> ()); // Load PCD file if (pcl::io::loadPCDFile<pcl::PointXYZ> ("sample.pcd", *source_cloud) == -1) { PCL_ERROR ("Couldn't read file sample.pcd \n"); return (-1); } /* Reminder: how transformation matrices work : |-------> This column is the translation | 1 0 0 x | \ | 0 1 0 y | }-> The identity 3x3 matrix (no rotation) on the left | 0 0 1 z | / | 0 0 0 1 | -> We do not use this line (and it has to stay 0,0,0,1) METHOD #1: Using a Matrix4f This is the "manual" method, perfect to understand but error prone ! */ Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity(); // Define a rotation matrix (see https://en.wikipedia.org/wiki/Rotation_matrix) // Here we defined a 45° (PI/4) rotation around the Z axis and a translation on the X axis. float theta = M_PI/4; // The angle of rotation in radians transform_1 (0,0) = cos (theta); transform_1 (0,1) = -sin(theta); transform_1 (1,0) = sin (theta); transform_1 (1,1) = cos (theta); // (row, column) // Define a translation of 2.5 meters on the x axis. transform_1 (0,3) = 2.5; // Print the transformation printf ("Method #1: using a Matrix4f\n"); std::cout << transform_1 << std::endl; // Executing the transformation pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZ> ()); /* void pcl::transformPointCloud(const pcl::PointCloud< PointT > & cloud_in, pcl::PointCloud< PointT > & cloud_out, const Eigen::Matrix4f & transform ) */ // Apply an affine transform defined by an Eigen Transform. pcl::transformPointCloud (*source_cloud, *transformed_cloud, transform_1); // Visualization printf( "\nPoint cloud colors : white = original point cloud\n" " red = transformed point cloud\n"); pcl::visualization::PCLVisualizer viewer ("Matrix transformation example"); // Define R,G,B colors for the point cloud pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source_cloud_color_handler (source_cloud, 255, 255, 255); // We add the point cloud to the viewer and pass the color handler viewer.addPointCloud (source_cloud, source_cloud_color_handler, "original_cloud"); pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> transformed_cloud_color_handler (transformed_cloud, 230, 20, 20); // Red viewer.addPointCloud (transformed_cloud, transformed_cloud_color_handler, "transformed_cloud"); viewer.addCoordinateSystem (1.0, 0); //Adds 3D axes describing a coordinate system to screen at 0,0,0. viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud"); viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud"); //viewer.setPosition(800, 400); // Setting visualiser window position while (!viewer.wasStopped ()) { // Display the visualiser until 'q' key is pressed viewer.spinOnce (); } return 0; }
在PCL官網下載All-in-one installers,由於使用的是Win7 32位系統,因此選擇了Windows MSVC 2010 (32bit)進行安裝,這個All-in-one的安裝程序會同時安裝除QT外的一些第三方依賴庫,比如boost、Eigen、VTK、OpenNI等。
安裝好之后如果是自己在VS2010中配置工程屬性,將會很麻煩,可以參考Using PCL in your own project。下面通過Cmake來自動生成VS2010的項目。首先創建一個CMakeLists.txt文件(注意其中PCL的版本)。如果編譯軟件使用了外部庫,事先並不知道它的頭文件和鏈接庫的位置。得在編譯命令中加上包含它們的查找路徑。CMake使用find_package命令來解決這個問題。
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(pcl-matrix_transform)
find_package(PCL 1.6 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (matrix_transform matrix_transform.cpp)
target_link_libraries (matrix_transform ${PCL_LIBRARIES})
然后使用CMake的GUI程序來生成工程文件。Where is the source code欄選擇源代碼所在路徑,這里代碼放在桌面上;Where to build the binaries欄選擇生成文件所在的路徑,默認在桌面上的build文件夾中。點擊Configure之后會彈出對話框,選擇Visual Studio 2010,最后點擊生成按鈕,將會在build文件夾中生成VS2010的工程文件。
在編譯之前需要注意一點,由於All-in-one的安裝程序沒有安裝QT(需要單獨安裝),需要在工程屬性的附加依賴項中刪掉QT的lib(這個程序中暫時也沒有用到QT相關的東西),否則會出現編譯錯誤。最后運行程序,結果如下圖所示。其中紅色的點雲為變換后的。
參考:
Using a matrix to transform a point cloud
http://pointclouds.org/documentation/tutorials/matrix_transform.php#matrix-transform
The PCD (Point Cloud Data) file format
http://pointclouds.org/documentation/tutorials/pcd_file_format.php#pcd-file-format
Reading Point Cloud data from PCD files
http://pointclouds.org/documentation/tutorials/reading_pcd.php#reading-pcd
PCL學習筆記(1):pcl1.6.0+vs2010環境配置以及第一個pcl程序
http://www.voidcn.com/blog/chentravelling/article/p-3487308.html