在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

從原理到c++代碼實現 | 通過球面投影將點云轉換為Range圖像

3D視覺工坊 ? 來源:DeepDriving ? 2023-06-21 10:30 ? 次閱讀

前言

將3維激光點云通過球面投影(Spherical Projection)轉換為2維距離圖像(Range Images),是自動駕駛應用場景中一種非常常見的點云處理方式。點云轉換為距離圖像后,通常會被輸入給一個2維卷積神經網絡去實現目標檢測、語義分割等任務。目前采用這種點云處理方式的典型目標檢測算法RangeDet,語義分割算法有SqueezeSegRangeNet++SalsaNext等。在這些文章中,都只給出一個通過球面投影轉換到距離圖像的最終公式,至于這個公式是怎么來的卻沒有詳細的推導,初看論文的讀者可能會比較困惑。本文將對這個投影公式做一定的推導,可能本人理解的也不是很對,歡迎大家批評指正。

52fc95ac-0fbf-11ee-962d-dac502259ad0.png

圖片來源于RangeDet論文

球面投影推導過程

假設有一個m線的旋轉掃描式激光雷達,它的垂直視場角FOV被分為上下兩個部分:FOV_upFOV_down,通常以FOV_up的數值為正數而FOV_down數值為負數,所以FOV = FOV_up + abs(FOV_down)。激光雷達旋轉掃描一周得到的點云相當于是以其自身為中心的空心圓柱體,如果把這個圓柱體展開的話,那么就可以把點云投影到一個圖像平面中去,這個圖像平面就是距離圖像。

530cd84a-0fbf-11ee-962d-dac502259ad0.png

對于一個m線的激光雷達,在掃描的某一時刻會得到m個點,如果旋轉一周掃描了n次,那么得到的點云就可以用一個的矩陣來表示。那么怎么把3維的點云投影到2維的距離圖像平面呢?這就需要用到球面坐標。

531bcd0a-0fbf-11ee-962d-dac502259ad0.png

圖片來源于RangeDet論文

球面坐標用3個參數來表示:距離,方位角(Azimuth),天頂角(Zenith)。通常使用的激光雷達點云中的每個由3維笛卡爾坐標表示的點實際上是從球面坐標系轉換而來:

讓我們再通過下圖來理解一下3維笛卡爾坐標系和球面坐標系之間的關系。

5327b066-0fbf-11ee-962d-dac502259ad0.png

假設3維笛卡爾坐標系下的點坐標為,那么用球面坐標系可以這樣表示該點:

如果以x軸方向為前視圖的方向把激光雷達旋轉掃描一周得到的圓柱體展開后,可以得到一副這樣的圖像:坐標原點在圖像的中心,圖像中像素的縱坐標由pitch角投影得到(范圍為[FOV_down,FOV_up]),橫坐標由yaw角投影得到(范圍為)。

5335f04a-0fbf-11ee-962d-dac502259ad0.png

由于圖像坐標系是以左上角作為坐標原點,所以上面得到的前視圖還需要做一下坐標轉換,把坐標原點移到左上角去:

把3維點云投影為2維圖像,這種降維操作必然會帶來信息損失。為了盡可能減少投影帶來的信息損失,我們需要選擇合適大小的投影圖像。對于一個64線的激光雷達,一般會設置投影圖像的高為64,那么圖像的寬該如何設置呢?假設激光雷達的水平分辨率為0.35度,那么旋轉一周一個激光器最多產生的點數為。在卷積神經網絡中,一般會對輸入特征圖做多次2倍下采樣,所以圖像的寬度需要設置為2的次冪,這里可設置為1024

由于不同類型激光雷達的視場角、水平分辨率不同,投影圖像的尺寸也會根據需要設置為不同的值,為了適應這些變化,yawpitch還需要進行規范化:

規范化后,再乘以投影圖像的寬高,就得到了這個點投影到距離圖像的坐標:

上式中的第二步是將代入得到的。

代碼實現

理解了原理后,我們再用代碼來把這個投影過程實現一遍。在RangeNet++中,點云被轉換為5個通道的距離圖像,這5個通道分別代表點云的這5個屬性。下面的代碼將展示如何通過球面投影將點云轉換為需要的距離圖像,使用的點云數據來源于SemanticKITTI數據集。

#include
#include

#include
#include
#include
#include
#include
#include

intmain(intargc,char**argv){
if(argc2){
std::cout<"Usage:"<0]<"
";
return-1;
}

conststd::stringpcd_file(argv[1]);
pcl::PointCloud::Ptrpoint_cloud(
newpcl::PointCloud);

if(pcl::loadPCDFile(pcd_file,*point_cloud)==-1){
std::cout<"Couldn'treadpcdfile!
";
return-1;
}

constexprintwidth=2048;
constexprintheight=64;
constexprfloatfov_up=3*M_PI/180.0;
constexprfloatfov_down=-25*M_PI/180.0;
constexprfloatfov=std::abs(fov_up)+std::abs(fov_down);
conststd::vector<float>image_means{12.12,10.88,0.23,-1.04,0.21};
conststd::vector<float>image_stds{12.32,11.47,6.91,0.86,0.16};
float*range_images=newfloat[5*width*height]();

for(constauto&point:point_cloud->points){
constauto&x=point.x;
constauto&y=point.y;
constauto&z=point.z;
constauto&intensity=point.intensity;
constfloatrange=std::sqrt(x*x+y*y+z*z);
constfloatyaw=-std::atan2(y,x);
constfloatpitch=std::asin(z/range);

floatproj_x=0.5f*(yaw/M_PI+1.0f)*width;
floatproj_y=(1.0f-(pitch+std::abs(fov_down))/fov)*height;
proj_x=std::floor(proj_x);
proj_y=std::floor(proj_y);

constintu=std::clamp<int>(static_cast<int>(proj_x),0,width-1);
constintv=std::clamp<int>(static_cast<int>(proj_y),0,height-1);

range_images[0*width*height+v*width+u]=
(range-image_means.at(0))/image_stds.at(0);
range_images[1*width*height+v*width+u]=
(x-image_means.at(1))/image_stds.at(1);
range_images[2*width*height+v*width+u]=
(y-image_means.at(2))/image_stds.at(2);
range_images[3*width*height+v*width+u]=
(z-image_means.at(3))/image_stds.at(3);
range_images[4*width*height+v*width+u]=
(intensity-image_means.at(4))/image_stds.at(4);
}

//對range通道進行可視化
cv::Matrange=
cv::Mat(height,width,CV_32FC1,static_cast<void*>(range_images));
cv::Matnormalized_range,u8_range,color_map;
cv::normalize(range,normalized_range,255,0,cv::NORM_MINMAX);
normalized_range.convertTo(u8_range,CV_8UC1);
cv::applyColorMap(u8_range,color_map,cv::COLORMAP_JET);
cv::imwrite("range_color_map.jpg",color_map);
cv::imshow("RangeImage",color_map);
cv::waitKey(0);

delete[]range_images;

return0;
}

range通道可視化的結果如下圖所示:

53403df2-0fbf-11ee-962d-dac502259ad0.jpg

上面的代碼有幾個需要說明的地方:

  • fov_upfov_downimage_meansimage_stds這幾個參數來源于RangeNet++預訓練模型中的arch_cfg.yaml文件。
  • std::clamp需要c++17支持,編譯的時候請使用-std=c++17編譯選項。
  • 實際使用中width * height的值只需要計算一次,沒必要在循環里面反復計算,這里這么寫只是為了方便理解。

參考資料

  • RangeDet: In Defense of Range View for LiDAR-based 3D Object Detection
  • https://towardsdatascience.com/spherical-projection-for-point-clouds-56a2fc258e6c

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2114

    瀏覽量

    73859
  • 代碼
    +關注

    關注

    30

    文章

    4828

    瀏覽量

    69055
  • 編譯
    +關注

    關注

    0

    文章

    661

    瀏覽量

    33046
  • 自動駕駛
    +關注

    關注

    785

    文章

    13932

    瀏覽量

    167014

原文標題:從原理到c++代碼實現 | 通過球面投影將點云轉換為Range圖像

文章出處:【微信號:3D視覺工坊,微信公眾號:3D視覺工坊】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    通過異步獲取的圖像與LiDAR對準的方案

    實現圖像與其重建對象之間的精確2D-3D對應關系對于準確的圖像定位至關重要,一種有前景的方法涉及在圖像和激光雷達平面之間建立對應關系,激光雷達平面可以被視為來自激光雷達
    發表于 12-12 14:46 ?858次閱讀

    如何二維數組轉換為圖像

    如何二維數組轉換為圖像
    發表于 03-10 11:15

    【創龍TMS320C665x申請】圖像中數字及字母的識別

    彩色信息,進行灰度化;2.圖像灰度修正,通過點算法使輸入圖像轉換為每一灰度上都有項目糊涂的像素的輸出
    發表于 03-04 09:38

    阿里SDK再升級,宣布支持C++語言

    C++ 語言開發者更加便捷地使用SDK調用產品API來操作產品,包括二次開發、自動化運維的實現等。此查看原文:http://click.aliyun.com/m/41955/日前,阿里
    發表于 02-08 13:48

    基于FPGA水平垂直投影(字符分割)法的實現

    列向x軸方向投影垂直投影是指二維圖象按行向y軸方向投影投影的結果可以看成是一維圖像.2 matlab實現
    發表于 08-07 10:15

    基于Verilog的垂直投影實現

    `基于Verilog的垂直投影實現微信公眾號:FPGA自習室一、概述投影,在立體幾何中我們學到過,是空間直線在某個方向上的投影,那么圖像處理
    發表于 03-03 17:51

    如何ADC代碼轉換為電壓

    討論如何為各種應用執行這一數學轉換。在第1篇文章中,我解釋如何ADC代碼轉換回相應的電壓。
    發表于 07-23 04:45

    如何利用codermatlab中的程序轉換C/C++

    利用codermatlab中的程序轉換C/C++眾所周知,matlab的功能是非常強大的,簡便易于操作的工具包更是非常的方便。為機器學習,深度學習,
    發表于 08-17 06:56

    如何在新版本中將C項目轉換為C++呢?

    我正在嘗試 C 項目轉換為 C++。在以前的版本中,屬性中有一個“轉換為 C++”選項。我在
    發表于 01-06 08:13

    ONNX模型轉換為中間表示(IR)后,精度下降了怎么解決?

    ONNX 模型轉換為 IR。 與使用 PyTorch 運行 ONNX 模型相比,Ran IR 采用 基準 C++ 工具,其性能準確率降低了 20%。 無法確定如何對圖像進行預處理
    發表于 08-15 08:28

    人臉識別C/C++代碼

    人臉識別C/C++代碼 生物特征識別應用于人臉,實際上是包含兩個方面:第一,圖像或視頻幀
    發表于 02-09 16:05 ?184次下載

    代碼轉換為電壓,如何可以實現

    許多初步了解模數轉換器(ADC)的人想知道如何ADC代碼轉換為電壓。或者,他們的問題是針對特定應用,例如:如何ADC
    的頭像 發表于 10-12 08:30 ?1.2w次閱讀
    <b class='flag-5'>將</b><b class='flag-5'>代碼</b><b class='flag-5'>轉換為</b>電壓,如何可以<b class='flag-5'>實現</b>?

    關于彩色圖像高斯反向投影基于OpenCV的C++代碼

    圖像反向投影的最終目的是獲取ROI然后實現對ROI區域的標注、識別、測量等圖像處理與分析,是計算機視覺與人工智能的常見方法之一。圖像反向
    的頭像 發表于 05-31 10:31 ?1007次閱讀

    C++在Linux內核開發中爭議到成熟

    Linux 內核郵件列表中一篇已有六年歷史的老帖近日再次引發激烈討論 —— 主題是建議 Linux 內核的開發語言 C 轉換為更現代的 C++
    的頭像 發表于 01-31 14:11 ?689次閱讀
    <b class='flag-5'>C++</b>在Linux內核開發中<b class='flag-5'>從</b>爭議到成熟

    OpenCV圖像識別C++代碼

    的頭文件 在您的C++代碼中,包含以下必要的頭文件: # include # include # include # include # include # include # include 讀取圖像
    的頭像 發表于 07-16 10:42 ?2449次閱讀
    主站蜘蛛池模板: 国产妇女在线 | 天天操天天射天天舔 | 欧美性free | 天天操天天干天天 | 国内外精品免费视频 | 天堂网www中文在线资源 | 亚洲成人网在线 | 伊人久久大香线蕉综合爱婷婷 | aa三级动态图无遮无挡 | 涩色综合| 日日噜噜噜噜人人爽亚洲精品 | 日韩一级片免费在线观看 | 91日本在线观看亚洲精品 | 天堂在线免费 | 欧美日韩精品一区二区另类 | 在线天堂网www资源种子 | 免费国产黄网站在线观看视频 | 69女poren18女| 女人张开双腿让男人桶爽免 | 视频一区在线观看 | 成人国产亚洲欧美成人综合网 | 2021成人国产精品 | 黄视频免费在线观看 | 亚洲精品网站日本xxxxxxx | 欧美特黄特色aaa大片免费看 | 美女视频黄a | 手机看片1024免费视频 | 亚洲精品91大神在线观看 | 日韩天天干 | 在线观看免费精品国产 | 四虎影院海外永久 | 免费视频不卡一区二区三区 | 大尺度视频网站久久久久久久久 | 色偷偷综合 | 女人的天堂网站 | 免费免费啪视频视频观看 | 好大好硬好深好爽的视频 | 免费高清在线视频色yeye | 黄色三级视频 | 夜夜爽天天爽 | 国产三级在线免费观看 |