海思hi3516dv300芯片AI圖像模塊學(xué)習(xí)(十一)NNIE_yolov3源碼學(xué)習(xí)
0.yolo模型參數(shù)


0.1 ????static SAMPLE_SVP_NNIE_MODEL_S s_stYolov3Model = {0};
先給這個(gè)結(jié)構(gòu)體賦0,占好內(nèi)存

hiSAMPLE_SVP_NNIE_MODEL_S? 網(wǎng)絡(luò)模型結(jié)構(gòu)體 里含兩個(gè)結(jié)構(gòu)體
SVP_NNIE_MODEL_S和SVP_MEM_INFO_S? 模型信息和內(nèi)存信息

0.1.1 SVP_NNIE_MODEL_S?模型信息


1.u32TmpBufSize??/*臨時(shí)緩沖區(qū)大小*/
2.u32NetSegNum; 網(wǎng)絡(luò)層數(shù)
3.SVP_NNIE_SEG_S? ?astSeg [SVP_NNIE_MAX_NET_SEG_NUM]; 網(wǎng)絡(luò)層級結(jié)構(gòu)

由于NNIE存在不支持層,整個(gè)神經(jīng)網(wǎng)絡(luò)被分為分為很多段,每個(gè)段中包含一些網(wǎng)絡(luò)層
astSrcNode 神經(jīng)網(wǎng)絡(luò)每一段也會(huì)有很多輸入輸出節(jié)點(diǎn),
因此每個(gè)astSeg[i].astSrcNode[j],就是第i段的第j層輸出節(jié)點(diǎn)信息

API參考:


這部分是主體
4.ROI池化的參數(shù),兩步法的網(wǎng)絡(luò)常用,yolo用不上先不管

里面是數(shù)量坐標(biāo)長寬高之類的

0.1.2?SVP_NNIE_MODEL_S 內(nèi)存信息

u64PhyAddr????? 物理內(nèi)存地址
u64VirAddr????????虛擬內(nèi)存地址
u32Size???????????? 內(nèi)存大小
0.2? s_stYolov3NnieParam:?NNIE中運(yùn)行網(wǎng)絡(luò)的輸入輸出控制參數(shù)

SAMPLE_SVP_NNIE_PARAM_S 結(jié)構(gòu)體——/*NNIE執(zhí)行參數(shù)*/

0.2.1 網(wǎng)絡(luò)模型信息
SVP_NNIE_MODEL_S* ? ?pstModel; 網(wǎng)絡(luò)模型參數(shù) 由?hiSAMPLE_SVP_NNIE_MODEL_S? 從wk文件中獲取,再輸入進(jìn)來
0.2.2 內(nèi)存索引信息
u32TmpBufSize;
au32TaskBufSize[SVP_NNIE_MAX_NET_SEG_NUM];
stTaskBuf;
stTmpBuf;
stStepBuf;//存儲(chǔ)Lstm步驟信息
0.2.3 網(wǎng)絡(luò)模型中各層的控制參數(shù)
1.astSegData[SVP_NNIE_MAX_NET_SEG_NUM];//分段的輸入和輸出blob
blob內(nèi)存塊,用來存放網(wǎng)絡(luò)段輸入輸出的結(jié)果,里面包含多個(gè)輸入輸出節(jié)點(diǎn)層


2.astForwardCtrl[SVP_NNIE_MAX_NET_SEG_NUM];將模型的各層分配到NNIE執(zhí)行


3.astForwardWithBboxCtrl[SVP_NNIE_MAX_NET_SEG_NUM];
這個(gè)是當(dāng)網(wǎng)絡(luò)包含不支持層,分段后執(zhí)行完自定義層,執(zhí)行支持的后續(xù)推理用到的



0.3?SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S??
? s_stYolov3SoftwareParam

YOLOv3軟件參數(shù)結(jié)構(gòu)體

輸入圖分辨率
? ? HI_U32 u32OriImHeight;
? ? HI_U32 u32OriImWidth;
每個(gè)格子框數(shù)量?HI_U32 u32BboxNumEachGrid;
檢測種類數(shù)量??HI_U32 u32ClassNum;
網(wǎng)格大小
? ? HI_U32 au32GridNumHeight[3];
? ? HI_U32 au32GridNumWidth[3];
非極大值抑制閾值?值越小預(yù)測框與標(biāo)注框重疊度越高
????HI_U32 u32NmsThresh;
conf_thresh?網(wǎng)格包含物體的概率或分?jǐn)?shù)閾值,值越高濾除的不含物體的網(wǎng)格越多
????HI_U32 u32ConfThresh;
每張圖中框的最大數(shù)量
????HI_U32 u32MaxRoiNum;
聚類先驗(yàn)anchor框的數(shù)值
????HI_FLOAT af32Bias[3][6];
結(jié)果等信息存儲(chǔ)位置
? ? SVP_MEM_INFO_S stGetResultTmpBuf;
? ? SVP_DST_BLOB_S stClassRoiNum;
? ? SVP_DST_BLOB_S stDstRoi;
? ? SVP_DST_BLOB_S stDstScore;
分?jǐn)?shù)
????HI_FLOAT af32ScoreThr[SAMPLE_SVP_NNIE_MAX_CLASS_NUM];
畫框信息



1.變量




?HI_CHAR *pcModelName =?模型地址
"./data/nnie_model/detection/yolov3_inst_bgr.wk";
? ?






數(shù)據(jù)類型在hi_type里面,引用頭文件


2.結(jié)構(gòu)體
引用結(jié)構(gòu)體定義文件 sample_comm_nnie.h


?2.1 hiSAMPLE_SVP_NNIE_CFG_S——NNIE配置參數(shù)
typedef struct hiSAMPLE_SVP_NNIE_CFG_S ,深度學(xué)習(xí)中cfg一般放網(wǎng)絡(luò)模型

SAMPLE_SVP_NNIE_CFG_S ? stNnieCfg = {0};??
將stNnieCfg?定義成這種形式的結(jié)構(gòu)體,初始化參數(shù)
輸入圖片地址*pcSrcFile,每個(gè)batch同時(shí)處理的圖片數(shù)量u32PicNum//max input image num in each batch

aenNnieCoreId指調(diào)用的NNIE設(shè)備編號

u32MaxRoiNum = 0;? //大概是yolo的坐標(biāo)roi配置

/*此結(jié)構(gòu)體用于指示來自seg的輸入或報(bào)告節(jié)點(diǎn)的輸入數(shù)據(jù)*/

2.2 /*NNIE輸入或輸出數(shù)據(jù)索引*/
INDEX=idx?
stInputDataIdx==seg的輸入或報(bào)告節(jié)點(diǎn)的輸入數(shù)據(jù)索引


這部分參數(shù)在SAMPLE_SVP_NNIE_FillSrcData?在填充數(shù)據(jù)時(shí)配置
2.3?/*此結(jié)構(gòu)體用于指示將執(zhí)行哪個(gè)seg */? ——?stProcSegIdx



在推理前,對不支持層分段時(shí)配置

3.配置NNIE網(wǎng)絡(luò)初始化參數(shù)

4.初始化媒體系統(tǒng)MPP

引用函數(shù)

位置

調(diào)用的是mpp的初始化系統(tǒng)和內(nèi)存 ——MPI函數(shù)

3.將wk文件中的參數(shù)導(dǎo)入到y(tǒng)olo模型參數(shù)s_stYolov3Model中

“&”是c語言的取地址運(yùn)算符。在程序中定義變量時(shí),變量x只要一聲明,就會(huì)給他分配一塊內(nèi)存來保存這個(gè)變量,而“&”就是保存這個(gè)變量的內(nèi)存的地址(相當(dāng)于給內(nèi)存編號)。C語言可以直接操作內(nèi)存,所以當(dāng) C 語言開發(fā)中,函數(shù)需要對原變量進(jìn)行修改時(shí),可以給該參數(shù)添加 &。這樣函數(shù)中對參數(shù)的修改,就是對原變量的修改。
在這里模型地址pcModelName不修改,是輸入。要修改的是之前定義(分配內(nèi)存)的yolo網(wǎng)絡(luò)模型結(jié)構(gòu)體:s_stYolov3Model

3.1 s32ret被設(shè)為-1,之前是0。s32ret應(yīng)該是表示程序運(yùn)行狀態(tài)的標(biāo)記

3.2 API參考:
加載模型函數(shù)在庫文件里 :include\mpi_nnie.h,不方便看源代碼

從用戶事先加載到 內(nèi)存 中的模型中解析出網(wǎng)絡(luò)模型。
這個(gè)函數(shù)可以將內(nèi)存里面的模型解析,將參數(shù)送到pstModel結(jié)構(gòu)體里面。
因此函數(shù)外部需要將wk文件填到內(nèi)存:pstModelBuf里面:
3.3?初始化地址和size,分配內(nèi)存給地址和大小變量


3.4 打開wk地址里的文件,獲得wk文件的大小slFileSize

3.5?根據(jù)上述大小,動(dòng)態(tài)分配一段內(nèi)存給u64PhyAddr和pu8VirAddr

3.6 根據(jù)新獲得的內(nèi)存地址和大小,更新模型的索引變量pstNnieModel

3.7 把fp中的wk文件讀取到內(nèi)存里,地址在pstNnieModel中

fread函數(shù):

3.8 通過HI_MPI_SVP_NNIE_LoadModel函數(shù)從內(nèi)存中的wk模型中解析出網(wǎng)絡(luò)模型參數(shù)導(dǎo)入到&pstNnieModel->stModel結(jié)構(gòu)體中,更新該結(jié)構(gòu)體。

加載模型完成,更新了模型結(jié)構(gòu)體:s_stYolov3Model
4.Yolov3參數(shù)初始化:?SAMPLE_SVP_NNIE_Yolov3_ParamInit

4.1輸入?yún)?shù):幾乎包含所有參數(shù)
1.cfg配置參數(shù)?:SAMPLE_SVP_NNIE_CFG_S ? stNnieCfg?
里面有:輸入圖片的地址,每次batch輸入圖數(shù)量,調(diào)用核心號NNIE core,最多框數(shù)量u32MaxRoiNum

2.NNIE-yolo3硬件參數(shù):SAMPLE_SVP_NNIE_PARAM_S? ?s_stYolov3NnieParam
網(wǎng)絡(luò)模型,NNIE執(zhí)行網(wǎng)絡(luò)、存儲(chǔ)結(jié)果參數(shù)
3.NNIE-yolo3軟件參數(shù):SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S? ?s_stYolov3SoftwareParam
網(wǎng)絡(luò)分辨率、grid網(wǎng)格劃分、anchor框設(shè)置、nms閾值、畫框數(shù)量和坐標(biāo)
這部分參數(shù)沒有在該函數(shù)里設(shè)置,是調(diào)用SAMPLE_SVP_NNIE_Yolov3_SoftwareInit輸出的參數(shù)。提示:
/*在SAMPLE_SVP_NNIE_Yolov3_SoftwareInit中設(shè)置Yolov3軟件參數(shù)
如果用戶改變了網(wǎng)絡(luò)結(jié)構(gòu),請確保參數(shù)設(shè)置在
SAMPLE_SVP_NNIE_Yolov3_SoftwareInit函數(shù)正確*/
4.2 函數(shù)本體:

4.2.1 硬件參數(shù)配置

配置內(nèi)存

配置運(yùn)算核心

配置各層輸入輸出結(jié)果的存貯塊

?4.2.2?軟件參數(shù)配置
grid網(wǎng)格和anchor框設(shè)置

Malloc輔助緩沖內(nèi)存 從硬件位置取出結(jié)果數(shù)據(jù),分配軟件的內(nèi)存大小

具體分配內(nèi)存地址和大小

Yolov3參數(shù)初始化的結(jié)果就是把執(zhí)行需要內(nèi)存分配好了。
5.讀取數(shù)據(jù)源

5.1 輸入?yún)?shù):cfg輸入配置,網(wǎng)絡(luò)硬件配置、輸入圖片索引的結(jié)構(gòu)體
5.2 函數(shù)主體
5.2.1.根據(jù)輸入索引結(jié)構(gòu)體,創(chuàng)建內(nèi)存索引變量Idx

由于是初始輸入層,數(shù)據(jù)填充的對象是網(wǎng)絡(luò)的第0層的第0個(gè)節(jié)點(diǎn)

5.2.2 cfg傳參,fp打開圖片

5.2.3?根據(jù)網(wǎng)絡(luò)硬件參數(shù),獲取數(shù)據(jù)大小

5.2.4 把數(shù)據(jù)填入內(nèi)存
網(wǎng)絡(luò)硬件參數(shù)獲取數(shù)據(jù)的索引信息,通過fread將 打開的圖片fp放進(jìn)硬件配置的內(nèi)存地址

不同圖片格式方法略有不同

圖片已經(jīng)放進(jìn)s_stYolov3NnieParam硬件配置中設(shè)置的內(nèi)存地址
6.模型推理


6.1 輸入:s_stYolov3NnieParam,NNIE執(zhí)行yolo配置。stInputDataId,層數(shù)據(jù)索引。stProcSegIdx,分段數(shù)據(jù)索引。
stProcSegIdx.stProcSegIdx是推理過程中因?yàn)椴恢С謱舆M(jìn)行的分段,是大段索引
stInputDataIdx.stSegIdx 是大段索引
stInputDataIdx.NodeIdx 是網(wǎng)絡(luò)大段中的網(wǎng)絡(luò)層節(jié)點(diǎn)索引

6.2 函數(shù)本體

6.2.1 逐層逐幀配置內(nèi)存

segdata是整段數(shù)據(jù)

astSrc/astDst 是每層的輸入/輸出信息

每層信息的內(nèi)部是多幀u32num(多個(gè)卷積和輸出的結(jié)果),二維WH,多通道chn的結(jié)構(gòu)
6.2.2 連接殘差網(wǎng)絡(luò)


yolov3包含殘差網(wǎng)絡(luò),通過strncmp函數(shù)比較各輸入層和輸出層的的標(biāo)記名,把標(biāo)記名字相同的第j層輸出和第i層輸入連接起來,實(shí)現(xiàn)殘差網(wǎng)絡(luò)鏈接
6.2.3 YOLOV3網(wǎng)絡(luò)推理

函數(shù)

輸入:
1.Handle返回值
????&hSvpNnieHandle
2.所有輸入層 W*H*CHN*NUM
????pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astSrc?
3.wk模型網(wǎng)絡(luò)信息
????pstNnieParam->pstModel,
4.所有輸出層?W*H*CHN*NUM
????pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst,
5.網(wǎng)絡(luò)模型各層與NNIE設(shè)備綁定信息
????&pstNnieParam->astForwardCtrl [pstProcSegIdx->u32SegIdx]