目前深度圖像的獲取方法有激光雷達深度成像法,計算機立體視覺成像,坐標測量機法,莫爾條紋法,結構光法等等,針對深度圖像的研究重點主要集中在以下幾個方面,深度圖像的分割技術 ,深度圖像的邊緣檢測技術 ,基於不同視點的多幅深度圖像的配准技術,基於深度數據的三維重建技術,基於三維深度圖像的三維目標識別技術,深度圖像的多分辨率建模和幾何壓縮技術等等,在PCL 中深度圖像與點雲最主要的區別在於 其近鄰的檢索方式的不同,並且可以互相轉換。
(這一章是我認為非常重要的)
模塊RangeImage相關概念以及算法的介紹
深度圖像(Depth Images)也被稱為距離影像(Range Image),是指將從圖像采集器到場景中各點的距離值作為像素值的圖像,它直接反應了景物可見表面的幾何形狀,利用它可以很方便的解決3D目標描述中的許多問題,深度圖像經過點雲變換可以計算為點雲數據,有規則及有必要信息的點雲數據可以反算為深度圖像數據

不同視角獲得深度圖像的過程:

(1)PCL中的模塊RangeImage相關類的介紹
pcl_range_image庫中包含兩個表達深度圖像和對深度圖像進行操作的類,其依賴於pcl::common模塊,深度圖像(距離圖像)的像素值代表從傳感器到物體的距離以及深度, 深度圖像是物體的三維表示形式,一般通過立體照相機或者ToF照相機獲取,如果具備照相機的內標定參數,就可以將深度圖像轉換為點雲
1.class pcl::RangeImage
RangeImage類繼承於PointCloud,主要功能是實現一個特定視點得到一個三維場景的深度圖像。其繼承關系如下:

類RangeImage的成員有:
Public Member Functions |
|
| template<typename PointCloudType > | |
| void | createFromPointCloud (const PointCloudType &point_cloud, float angular_resolution=pcl::deg2rad(0.5f), float max_angle_width=pcl::deg2rad(360.0f), float max_angle_height=pcl::deg2rad(180.0f), const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
| 從點雲創建深度圖像,point_cloud為指向創建深度圖像所需要的點雲的引用,angular_resolution為模擬的深度傳感器的角度分辨率,即深度圖像中一個像素對應的角度大小,max_angle_width為模擬的深度傳感器的水平最大采樣角度,max_angle_height為模擬傳感器的垂直方向最大采樣角度,sensor_pose設置模擬的深度傳感器的位姿是一個仿射變換矩陣,默認為4*4的單位矩陣變換,coordinate_frame定義按照那種坐標系統的習慣默認為CAMERA_FRAME,noise_level獲取深度圖像深度時,近鄰點對查詢點距離值的影響水平,min_range設置最小的獲取距離,小於最小獲取距離的位置為傳感器的盲區,border_size獲得深度圖像的邊緣的寬度 默認為0 該函數中涉及的角度的單位都是弧度 | |
| template<typename PointCloudType > | |
| void | createFromPointCloudWithKnownSize (const PointCloudType &point_cloud, float angular_resolution, const Eigen::Vector3f &point_cloud_center, float point_cloud_radius, const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
| 從點雲創建深度圖像,其中參數中有關場景大小的提示,提高了獲取深度圖像時的計算速度。point_cloud為指向創建深度圖像所需要的點雲的引用,angular_resolution為模擬的深度傳感器的角度分辨率,弧度表示,point_cloud_center為點雲外接球體的中心,默認為(0,0,0)point_cloud_radius為點雲外接球體的半徑,sensor_pose設置模擬的深度傳感器的位姿是一個仿射變換矩陣,默認為4*4的單位矩陣變換,coordinate_frame定義按照那種坐標系統的習慣默認為CAMERA_FRAME,noise_level獲取深度圖像深度時,近鄰點對查詢點距離值的影響距離,以米為單位,min_range設置最小的獲取距離,小於最小獲取距離的位置為傳感器的盲區,border_size獲得深度圖像的邊緣的寬度 默認為0 該函數中涉及的角度的單位都是弧度 |
|
| template<typename PointCloudTypeWithViewpoints > | |
| void | createFromPointCloudWithViewpoints (const PointCloudTypeWithViewpoints &point_cloud, float angular_resolution, float max_angle_width, float max_angle_height, CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
| 從點雲創建深度圖像,點雲中包含深度信息,其中,point_cloud為指向創建深度圖像所需要的點雲的引用,angular_resolution為模擬的深度傳感器的角度分辨率,即深度圖像中一個像素對應的角度大小,max_angle_width為模擬的深度傳感器的水平最大采樣角度,max_angle_height為模擬傳感器的垂直方向最大采樣角度,sensor_pose設置模擬的深度傳感器的位姿是一個仿射變換矩陣,默認為4*4的單位矩陣變換,coordinate_frame定義按照那種坐標系統的習慣默認為CAMERA_FRAME,noise_level獲取深度圖像深度時,近鄰點對查詢點距離值的影響水平,如果該值比較小,則常用Z-緩沖區中深度平均值作為查詢點的深度,min_range設置最小的可視深度,小於最小獲取距離的位置為傳感器的盲區,border_size獲得深度圖像的邊緣的寬度 默認為0 該函數中涉及的角度的單位都是弧度 | |
| void | createEmpty (float angular_resolution, const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), RangeImage::CoordinateFrame coordinate_frame=CAMERA_FRAME, float angle_width=pcl::deg2rad(360.0f), float angle_height=pcl::deg2rad(180.0f)) |
| 創建一個空的深度圖像,以當前視點不可見點填充,其中,angle_width為模擬的深度傳感器的水平采樣角度,默認為PI*2(360);angle_height垂直方向的采樣角度默認為PI(180)*****其他參數同上 | |
| template<typename PointCloudType > | |
| void | integrateFarRanges (const PointCloudType &far_ranges) |
| 將已有的遠距離測量結果融合到深度圖像中, | |
| PCL_EXPORTS void | cropImage (int border_size=0, int top=-1, int right=-1, int bottom=-1, int left=-1) |
| 裁剪深度圖像到最小尺寸,使這個最小尺寸包含所有點雲,其中,board_size設置裁剪后深度圖像的邊界尺寸, top為裁剪框的邊界***********默認都為-1 | |
| void | setTransformationToRangeImageSystem (const Eigen::Affine3f &to_range_image_system) |
| 設置從深度圖像坐標系(傳感器的坐標系)轉換到世界坐標系的變換矩陣 | |
| float | getAngularResolution () const |
| 獲得深度圖像X和Y方向的角分辨率 弧度表示 | |
| void | setAngularResolution (float angular_resolution) |
| 設置深度圖像在X方向和Y方向的新的角分辨率,angular_resolution即每個像素所對應的弧度 | |
| void | calculate3DPoint (float image_x, float image_y, float range, PointWithRange &point) const |
| 根據深度圖像點(X Y)和距離(range)計算返回場景中的3D點的point | |
| void | calculate3DPoint (float image_x, float image_y, PointWithRange &point) const |
| 根據給定的深度圖像點和離該點最近像素上的距離值計算返回場景中的3D 點point | |
(詳細的解釋請官網查看)
(2)class pcl::RangeImagePlanner
RangeImagePlanner 來源於最原始的深度圖像,但又區別於原始的深度圖像,因為該類不使用球類投影方式,而是通過一個平面投影方式進行投影(相機一一般采用這種投影方式),因此對於已有的利用深度傳感器獲取的深度圖像來說比較實用,類的繼承關系如下:

Public Member Functions |
|
| PCL_EXPORTS void | setDisparityImage (const float *disparity_image, int di_width, int di_height, float focal_length, float base_line, float desired_angular_resolution=-1) |
| 從給定的視差圖像中創建圖像,其中disparity_image是輸入的視差圖像,di_width視差圖像的寬度di_height視差圖像的高度focal_length, 產生視差圖像的照相機的焦距,base_line是用於產生視差圖像的立體相對的基線長度,desired_angular_resolution預設的角分辨率 每個像素對應的弧度,該值不能大於點雲的密度, | |
| PCL_EXPORTS void | setDepthImage (const float *depth_image, int di_width, int di_height, float di_center_x, float di_center_y, float di_focal_length_x, float di_focal_length_y, float desired_angular_resolution=-1) |
| 從已存在的深度影像中創建深度圖像,其中,depth_image是輸入的浮點形的深度圖像,di_width,深度圖像的寬度,di_height圖像的高度,di_center_x di_center_y 是照相機投影中心XY的坐標。di_focal_length_x di_focal_length_y是照相機水平 垂直方向上的焦距,desired_angular_resolution預設的角分辨率 每個像素對應的弧度,該值不能大於點雲的密度, | |
| template<typename PointCloudType > | |
| void | createFromPointCloudWithFixedSize (const PointCloudType &point_cloud, int di_width, int di_height, float di_center_x, float di_center_y, float di_focal_length_x, float di_focal_length_y, const Eigen::Affine3f &sensor_pose, CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f) |
| 從已存在的點雲中創建圖像,point_cloud為指向創建深度圖像所需要的點雲對象的引用,di_width視差圖像的寬度di_height視差圖像的高度 di_center_x di_center_y 是照相機投影中心XY的坐標 di_focal_length_x di_focal_length_y是照相機水平 垂直方向上的焦距 sensor_pose是模擬深度照相機的位姿 coordinate_frame為點雲所使用的坐標系 noise_level傳感器的水平噪聲, | |
| virtual void | calculate3DPoint (float image_x, float image_y, float range, Eigen::Vector3f &point) const |
| 根據給定圖像點和深度圖創建3D點,其中image_x iamge_y range 分別為XY 坐標和深度,point為生成的3D點 | |
| virtual void | getImagePoint (const Eigen::Vector3f &point, float &image_x, float &image_y, float &range) const |
| 從給定的3D點point中計算圖像點(X Y)和深度值 | |
等等具體看官網
(3)應用實例
如何從點雲創建深度圖,如何從點雲和給定的傳感器的位置來創建深度圖像,此程序是生成一個矩形的點雲,然后基於該點雲創建深度圖像
新建文件range_image_creation.cpp:
#include <pcl/range_image/range_image.h> //深度圖像的頭文件 int main (int argc, char** argv) { pcl::PointCloud<pcl::PointXYZ> pointCloud; //定義點雲的對象 // 循環產生點雲的數據 for (float y=-0.5f; y<=0.5f; y+=0.01f) { for (float z=-0.5f; z<=0.5f; z+=0.01f) { pcl::PointXYZ point; point.x = 2.0f - y; point.y = y; point.z = z; pointCloud.points.push_back(point); //循環添加點數據到點雲對象 } } pointCloud.width = (uint32_t) pointCloud.points.size(); pointCloud.height = 1; //設置點雲對象的頭信息 //實現一個呈矩形形狀的點雲 // We now want to create a range image from the above point cloud, with a 1deg angular resolution //angular_resolution為模擬的深度傳感器的角度分辨率,即深度圖像中一個像素對應的角度大小 float angularResolution = (float) ( 1.0f * (M_PI/180.0f)); // 1.0 degree in radians //max_angle_width為模擬的深度傳感器的水平最大采樣角度, float maxAngleWidth = (float) (360.0f * (M_PI/180.0f)); // 360.0 degree in radians //max_angle_height為模擬傳感器的垂直方向最大采樣角度 都轉為弧度 float maxAngleHeight = (float) (180.0f * (M_PI/180.0f)); // 180.0 degree in radians //傳感器的采集位置 Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f); //深度圖像遵循坐標系統 pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME; float noiseLevel=0.00; //noise_level獲取深度圖像深度時,近鄰點對查詢點距離值的影響水平 float minRange = 0.0f; //min_range設置最小的獲取距離,小於最小獲取距離的位置為傳感器的盲區 int borderSize = 1; //border_size獲得深度圖像的邊緣的寬度 pcl::RangeImage rangeImage; rangeImage.createFromPointCloud(pointCloud, angularResolution, maxAngleWidth, maxAngleHeight, sensorPose, coordinate_frame, noiseLevel, minRange, borderSize); std::cout << rangeImage << "\n"; }
顯示結果

微信公眾號號可掃描二維碼一起共同學習交流

未完待續******************************88888
