結合sample代碼來分析海思DPU模塊運行原理

前言

海思DPU(Depth Process Unit)的中文翻譯爲深度信息處理單元,主要是來實現雙目測距和三維重建的硬件加速功能從而提高實時性。海思SDK裏面和DPU相關的文檔資料很少,就兩篇:《HiDPU工具使用指南》和《HiDPUAPI參考》。所以這裏有必要結合sample代碼來理清其思路。

基本概念

DPU包括兩個子模塊。一個叫RECT,注意這裏不是矩形框的意思,而是rectify,即校正的意思,後面會進一步解釋其原理。另一個模塊叫Match,即匹配的意思。這些概念需要有些雙目測距/重建的基礎才能比較好理解。

此外,在dpu sample代碼中有兩個獨立的運行case。

一個是走VI和VPSS通道,直接對雙VPSS輸出數據來進行雙目測距以此實現實時雙目視頻流的三維重建。其入口函數爲:

SAMPLE_DPU_VI_VPSS_RECT_MATCH();

另一個是基於雙目拍攝到的圖片來進行雙目測距和重建。 其入口函數爲:

SAMPLE_DPU_FILE_RECT_MATCH();

兩者算法原理都差不多,都是先做校正再做匹配來得到視差圖,爲後面的測距和重建奠定堅實基礎。這裏方便起見,就介紹第二個case。

DPU RECT

RECT校正是用來將雙目同時拍攝到的圖片通過對應攝像頭的映射參數mapx和mapy進行行對齊。而每個攝像頭的映射參數是通過攝像頭標定所得到的內參和外參來獲取得。這兩句話如果沒有標定基礎得話,理解起來會有些困難。換句話說,每個攝像頭都有自己得視角和畸變,它們就是靠各自得映射參數文件mapx,mapy來去畸變並實現行對齊。

在sample代碼中,雙目攝像頭對應得mapx和mapy參數爲:

    HI_CHAR *apcMapFileName[DPU_RECT_MAX_PIPE_NUM] = {"./data/input/lut/1050x560_LeftMap.dat",
        "./data/input/lut/1050x560_RightMap.dat"};

這裏1050x560_LeftMap.dat和1050x560_RightMap.dat分別指左和右攝像頭得映射參數,其分辨率爲1050x560。它把x和y方向得參數融合進一個文件,其裏面得排列格式爲:

可以看到原始得mapx或y每個座標值爲浮點數,佔4個字節,兩者融合起來就變成每個座標值佔8個字節了,如果分辨率爲1050x560得話,那麼融合得到數據文件size爲1050x560*8 bytes。

需要注意的是,代碼裏面得1050x560_LeftMap.dat和1050x560_LeftMap.dat的大小隻爲 1050*560*4bytes,那是因爲使用海思dpu工具dpu_tool_rect.exe(詳見HiDPU工具 開發指南)做了一個內部轉換來節省內存空間。

映射參數文件又叫查找表LUT。  舉個例子,如果想獲取左攝像頭圖片對齊後目標圖像(1,0)的像素值,那麼得先去1050x560_LeftMap.dat查找表中(1,0)出得x和y方向座標值,假如是(3.2, 2.8),那麼就到源圖像中做一個插值,所得結果就賦給目標圖像(1,0)。

當然在海思dpu模塊中,這個查找表過程由硬件來實現,我們只需要把查找表以及源圖像正確得輸入進去即可。

 /************************************************
     step2:  start DPU RECT
     *************************************************/
    for (i = 0; i < DPU_RECT_MAX_PIPE_NUM; i++)
    {
        s32PipeNum = i;
        s32Ret = SAMPLE_COMM_DPU_RECT_LoadLut(apcMapFileName[i],
                &s_stSampleDpuConfig.astDpuRectMemInfo[i], &s_stSampleDpuConfig.s32LutId[i]);
        if(s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("load lut failed for %#x!\n", s32Ret);
            goto END4;
        }
    }
。。。 。。。
    s32Ret = SAMPLE_COMM_DPU_RECT_Start(s_stSampleDpuConfig.DpuRectGrp,
            &s_stSampleDpuConfig.stDpuRectGrpAttr, astChnAttr);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("start dpu rect failed for %#x!\n", s32Ret);
        goto END5;
    }

DPU MATCH 

雙目圖像行對齊後,接下來就是行匹配來找到對應點,找到後,就將該兩點的x座標值相減,所得到差就是所謂視差值。這裏的難點以及計算量大的工作自然是匹配。 

雙目立體視覺匹配算法有SAD, BM以及SGBM等。相較而言,SGBM用的比較多,因爲它是全局算法,其匹配效果肯定好於局部匹配算法BM,而且它還是半全局的,所以速度方面也有所提升。 目前還不清楚海思dpu裏面用的是哪個匹配算法,應該是全局或半全局。

其對應功能啓動的代碼如下:

    s32Ret = SAMPLE_COMM_DPU_MATCH_Start(s_stSampleDpuConfig.DpuMatchGrp,
            &s_stSampleDpuConfig.stDpuMatchGrpAttr, &stChnAttr);

需要注意的是,匹配得到的視差圖大小爲 width*height*2,而不是 width*height*4,這是因爲其每個像素數據格式爲S10Q6((1bit 符號位+9bit 整數部分+6bit 小數部分),換句話來說,用2個byte來表示float32數了。 

小結 

RECT和MATCH無疑是雙目立體視覺中最耗計算資源的部分。所以用硬件來實現這兩步可以大大提高測距和三維重建實時性。得到視差圖後就可以通過公式d = (B*fx) / d來計算得到Z軸方向上的值,進而可以其x,y座標值,這裏就不再贅述。

 

 

 

 

 

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