海思hi3516dv300芯片AI图像模块学习(十一)NNIE_yolov3源码学习
0.yolo模型参数


0.1 static SAMPLE_SVP_NNIE_MODEL_S s_stYolov3Model = {0};
先给这个结构体赋0,占好内存

hiSAMPLE_SVP_NNIE_MODEL_S 网络模型结构体 里含两个结构体
SVP_NNIE_MODEL_S和SVP_MEM_INFO_S 模型信息和内存信息

0.1.1 SVP_NNIE_MODEL_S 模型信息


1.u32TmpBufSize /*临时缓冲区大小*/
2.u32NetSegNum; 网络层数
3.SVP_NNIE_SEG_S astSeg [SVP_NNIE_MAX_NET_SEG_NUM]; 网络层级结构

由于NNIE存在不支持层,整个神经网络被分为分为很多段,每个段中包含一些网络层
astSrcNode 神经网络每一段也会有很多输入输出节点,
因此每个astSeg[i].astSrcNode[j],就是第i段的第j层输出节点信息

API参考:


这部分是主体
4.ROI池化的参数,两步法的网络常用,yolo用不上先不管

里面是数量坐标长宽高之类的

0.1.2 SVP_NNIE_MODEL_S 内存信息

u64PhyAddr 物理内存地址
u64VirAddr 虚拟内存地址
u32Size 内存大小
0.2 s_stYolov3NnieParam: NNIE中运行网络的输入输出控制参数

SAMPLE_SVP_NNIE_PARAM_S 结构体——/*NNIE执行参数*/

0.2.1 网络模型信息
SVP_NNIE_MODEL_S* pstModel; 网络模型参数 由 hiSAMPLE_SVP_NNIE_MODEL_S 从wk文件中获取,再输入进来
0.2.2 内存索引信息
u32TmpBufSize;
au32TaskBufSize[SVP_NNIE_MAX_NET_SEG_NUM];
stTaskBuf;
stTmpBuf;
stStepBuf;//存储Lstm步骤信息
0.2.3 网络模型中各层的控制参数
1.astSegData[SVP_NNIE_MAX_NET_SEG_NUM];//分段的输入和输出blob
blob内存块,用来存放网络段输入输出的结果,里面包含多个输入输出节点层


2.astForwardCtrl[SVP_NNIE_MAX_NET_SEG_NUM];将模型的各层分配到NNIE执行


3.astForwardWithBboxCtrl[SVP_NNIE_MAX_NET_SEG_NUM];
这个是当网络包含不支持层,分段后执行完自定义层,执行支持的后续推理用到的



0.3 SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S
s_stYolov3SoftwareParam

YOLOv3软件参数结构体

输入图分辨率
HI_U32 u32OriImHeight;
HI_U32 u32OriImWidth;
每个格子框数量 HI_U32 u32BboxNumEachGrid;
检测种类数量 HI_U32 u32ClassNum;
网格大小
HI_U32 au32GridNumHeight[3];
HI_U32 au32GridNumWidth[3];
非极大值抑制阈值 值越小预测框与标注框重叠度越高
HI_U32 u32NmsThresh;
conf_thresh 网格包含物体的概率或分数阈值,值越高滤除的不含物体的网格越多
HI_U32 u32ConfThresh;
每张图中框的最大数量
HI_U32 u32MaxRoiNum;
聚类先验anchor框的数值
HI_FLOAT af32Bias[3][6];
结果等信息存储位置
SVP_MEM_INFO_S stGetResultTmpBuf;
SVP_DST_BLOB_S stClassRoiNum;
SVP_DST_BLOB_S stDstRoi;
SVP_DST_BLOB_S stDstScore;
分数
HI_FLOAT af32ScoreThr[SAMPLE_SVP_NNIE_MAX_CLASS_NUM];
画框信息



1.变量




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






数据类型在hi_type里面,引用头文件


2.结构体
引用结构体定义文件 sample_comm_nnie.h


2.1 hiSAMPLE_SVP_NNIE_CFG_S——NNIE配置参数
typedef struct hiSAMPLE_SVP_NNIE_CFG_S ,深度学习中cfg一般放网络模型

SAMPLE_SVP_NNIE_CFG_S stNnieCfg = {0};
将stNnieCfg 定义成这种形式的结构体,初始化参数
输入图片地址*pcSrcFile,每个batch同时处理的图片数量u32PicNum//max input image num in each batch

aenNnieCoreId指调用的NNIE设备编号

u32MaxRoiNum = 0; //大概是yolo的坐标roi配置

/*此结构体用于指示来自seg的输入或报告节点的输入数据*/

2.2 /*NNIE输入或输出数据索引*/
INDEX=idx
stInputDataIdx==seg的输入或报告节点的输入数据索引


这部分参数在SAMPLE_SVP_NNIE_FillSrcData 在填充数据时配置
2.3 /*此结构体用于指示将执行哪个seg */ —— stProcSegIdx



在推理前,对不支持层分段时配置

3.配置NNIE网络初始化参数

4.初始化媒体系统MPP

引用函数

位置

调用的是mpp的初始化系统和内存 ——MPI函数

3.将wk文件中的参数导入到yolo模型参数s_stYolov3Model中

“&”是c语言的取地址运算符。在程序中定义变量时,变量x只要一声明,就会给他分配一块内存来保存这个变量,而“&”就是保存这个变量的内存的地址(相当于给内存编号)。C语言可以直接操作内存,所以当 C 语言开发中,函数需要对原变量进行修改时,可以给该参数添加 &。这样函数中对参数的修改,就是对原变量的修改。
在这里模型地址pcModelName不修改,是输入。要修改的是之前定义(分配内存)的yolo网络模型结构体:s_stYolov3Model

3.1 s32ret被设为-1,之前是0。s32ret应该是表示程序运行状态的标记

3.2 API参考:
加载模型函数在库文件里 :include\mpi_nnie.h,不方便看源代码

从用户事先加载到 内存 中的模型中解析出网络模型。
这个函数可以将内存里面的模型解析,将参数送到pstModel结构体里面。
因此函数外部需要将wk文件填到内存:pstModelBuf里面:
3.3 初始化地址和size,分配内存给地址和大小变量


3.4 打开wk地址里的文件,获得wk文件的大小slFileSize

3.5 根据上述大小,动态分配一段内存给u64PhyAddr和pu8VirAddr

3.6 根据新获得的内存地址和大小,更新模型的索引变量pstNnieModel

3.7 把fp中的wk文件读取到内存里,地址在pstNnieModel中

fread函数:

3.8 通过HI_MPI_SVP_NNIE_LoadModel函数从内存中的wk模型中解析出网络模型参数导入到&pstNnieModel->stModel结构体中,更新该结构体。

加载模型完成,更新了模型结构体:s_stYolov3Model
4.Yolov3参数初始化: SAMPLE_SVP_NNIE_Yolov3_ParamInit

4.1输入参数:几乎包含所有参数
1.cfg配置参数 :SAMPLE_SVP_NNIE_CFG_S stNnieCfg
里面有:输入图片的地址,每次batch输入图数量,调用核心号NNIE core,最多框数量u32MaxRoiNum

2.NNIE-yolo3硬件参数:SAMPLE_SVP_NNIE_PARAM_S s_stYolov3NnieParam
网络模型,NNIE执行网络、存储结果参数
3.NNIE-yolo3软件参数:SAMPLE_SVP_NNIE_YOLOV3_SOFTWARE_PARAM_S s_stYolov3SoftwareParam
网络分辨率、grid网格划分、anchor框设置、nms阈值、画框数量和坐标
这部分参数没有在该函数里设置,是调用SAMPLE_SVP_NNIE_Yolov3_SoftwareInit输出的参数。提示:
/*在SAMPLE_SVP_NNIE_Yolov3_SoftwareInit中设置Yolov3软件参数
如果用户改变了网络结构,请确保参数设置在
SAMPLE_SVP_NNIE_Yolov3_SoftwareInit函数正确*/
4.2 函数本体:

4.2.1 硬件参数配置

配置内存

配置运算核心

配置各层输入输出结果的存贮块

4.2.2 软件参数配置
grid网格和anchor框设置

Malloc辅助缓冲内存 从硬件位置取出结果数据,分配软件的内存大小

具体分配内存地址和大小

Yolov3参数初始化的结果就是把执行需要内存分配好了。
5.读取数据源

5.1 输入参数:cfg输入配置,网络硬件配置、输入图片索引的结构体
5.2 函数主体
5.2.1.根据输入索引结构体,创建内存索引变量Idx

由于是初始输入层,数据填充的对象是网络的第0层的第0个节点

5.2.2 cfg传参,fp打开图片

5.2.3 根据网络硬件参数,获取数据大小

5.2.4 把数据填入内存
网络硬件参数获取数据的索引信息,通过fread将 打开的图片fp放进硬件配置的内存地址

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

图片已经放进s_stYolov3NnieParam硬件配置中设置的内存地址
6.模型推理


6.1 输入:s_stYolov3NnieParam,NNIE执行yolo配置。stInputDataId,层数据索引。stProcSegIdx,分段数据索引。
stProcSegIdx.stProcSegIdx是推理过程中因为不支持层进行的分段,是大段索引
stInputDataIdx.stSegIdx 是大段索引
stInputDataIdx.NodeIdx 是网络大段中的网络层节点索引

6.2 函数本体

6.2.1 逐层逐帧配置内存

segdata是整段数据

astSrc/astDst 是每层的输入/输出信息

每层信息的内部是多帧u32num(多个卷积和输出的结果),二维WH,多通道chn的结构
6.2.2 连接残差网络


yolov3包含残差网络,通过strncmp函数比较各输入层和输出层的的标记名,把标记名字相同的第j层输出和第i层输入连接起来,实现残差网络链接
6.2.3 YOLOV3网络推理

函数

输入:
1.Handle返回值
&hSvpNnieHandle
2.所有输入层 W*H*CHN*NUM
pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astSrc
3.wk模型网络信息
pstNnieParam->pstModel,
4.所有输出层 W*H*CHN*NUM
pstNnieParam->astSegData[pstProcSegIdx->u32SegIdx].astDst,
5.网络模型各层与NNIE设备绑定信息
&pstNnieParam->astForwardCtrl [pstProcSegIdx->u32SegIdx]