【2023 · CANN訓練營第一季】數據預處理-JPEG數據解碼
文檔參考:CANN文檔社區版: 6.0.RC1.alpha001
我們的模型輸入是固定的圖片格式、大小,但是實際上我們的想要進行推理的圖片是各種各樣的,在應用中,我們常使用NV12的圖片作為模型的輸入。如果輸入是僅有Y分量的灰度圖,我們便可以通過將UV分量的部分補充為灰色而滿足我們的使用,但是如果我們的輸入為JPEG圖片,我們需要使用到ACL提供的媒體數據處理了相關API,對我們的圖片進行預處理,把jpg圖片進行解碼成YUV格式的內容,并且獲得其圖片信息。
一、媒體數據處理API的V1
note:媒體數據處理V1版本與媒體數據處理V2版本的接口功能范圍相同,都是描述處理媒體數據的接口,用于實現摳圖、圖片縮放、格式轉換等功能,但兩套接口不能混用
(資料圖片)
在Device側,我們對要進行媒體數據處理的相關數據的內存的申請和釋放,就不可以簡單的使用malloc,new或者aclrtmalloc等申請的內存了,我們需要使用dvpp接口。并且,從性能角度,為了減少拷貝,媒體數據處理的輸出作為模型推理的輸入,實現內存復用。我們盡量申請足夠大的內存進行反復使用,盡可能避免反復使用dvpp的接口申請內存和釋放,造成一定的性能損耗。
1.dvpp內存和通道
(1)內存申請與釋放
note:調用該接口申請大頁內存失敗,僅表示系統內的大頁內存不夠
(2)通道的創建與釋放
2.JPEGD相關接口
性能指標:
JPEGD性能指標是基于硬件解碼的性能,JPEGD硬件解碼不支持3個SOS的圖片解碼,對于硬件不支持的格式,會使用軟件解碼,軟件解碼性能參考為1080P 15fps。JPEGD解碼的輸出圖片如果涉及旋轉,則性能指標低于軟件解碼的參考值,例如對于1080P的圖片,性能指標低于15fps。
以下性能數據,是基于一個stream上下發1個異步媒體數據處理任務后,執行一次aclrtSynchronizeStream接口。
在我們代碼使用的過程中,其實最先需要了解的是我們所用的接口的性能,這直接影響到我們的使用方案,可以防止我們的代碼設計直接超越了模塊處理的性能。實際和官方標量有的時候會有一點實測的出入,不過最好還是按照手冊中的描述進行預先規劃,以下為手冊中的指標:
功能說明:
JPEGD在解碼圖片時,支持對圖片進行旋轉。
JPEGD在解碼圖片時,支持按源圖片格式解碼。
圖片分辨率約束:
輸入圖片分辨率:最大分辨率:8192x8192,最小分辨率:32x32。
輸出圖片分辨率:JPEGD只對圖片解碼,不會改變圖片分辨率,因此輸出與輸入的圖片分辨率保持一致。
輸出的寬高對齊:
這里我僅寫出了我們下方代碼輸出的yuv420SP(NV12 8bit)的情況
寬stride為寬128對齊后的值。
高stride為高16對齊后的值。
內存大小(單位Byte)≥ 寬stride * 高stride * 3/2
接口說明:
二、代碼驗證與學習
代碼思路:
1.初始化好后,讀取一個jpg圖片并獲得其圖像信息,存入aclrtMalloc存入的內存中
2.創建dvpp通道,并將其解碼為獲取到的圖像信息大小的yuv圖片
3.按照次序銷毀相關創建
好啦!讓我們編譯它!
有報錯,查看錯誤代碼,和該處代碼:
發現是銷毀時銷毀順序有問題,把Device和context都銷毀了,才銷毀通道。
所以,一定要注意銷毀順序!!!之前也提到過了,先創建->后銷毀,后創建->先銷毀!!!
修改后:
代碼:
附上調試好的正確的代碼:
runDecode.cpp(主函數文件)
dvpp_decode.cpp(decode處理文件)
dvpp_decode.h
cmakelist可以參考我之前的文章里有。
到這里就結束啦,想要存下來看看結果的同學也可以存成.yuv文件用yuvplayer打開看看哦!
ps:該文僅是為了記錄CANN訓練營的學習過程所用,不參與任何商業用途,有任何代碼問題可以和我一起討論修改
關鍵詞:
責任編輯:Rex_14