打开微信,使用扫一扫进入页面后,点击右上角菜单,
点击“发送给朋友”或“分享到朋友圈”完成分享
对yolov3离线模型运行仍然分为预处理、推理、后处理三个部分。由原模型生成的离线模型可以借助cnrt进行推理,从而脱离了深度学习框架。
首先是对cnrt的一些参数进行初始化,而这些参数从yolov3离线模型获得。部分代码如下:
//获取模型输入/输出的数据大小及节点个数
CNRT_CHECK(cnrtGetInputDataSize(&inputSizeS,&inputNum,function));
CNRT_CHECK(cnrtGetOutputDataSize(&outputSizeS,&outputNum,function));
//获取模型输入/输出的数据类型
CNRT_CHECK(cnrtGetInputDataType(&inputTypeS,&inputNum,function));
CNRT_CHECK(cnrtGetOutputDataType(&outputTypeS,&outputNum,function));
//分配 存放CPU端输入/输出地址的 指针数组
inputCpuPtrS = (void **)malloc(sizeof(void *) * inputNum);
outputCpuPtrS = (void **)malloc(sizeof(void *) * outputNum);
outputCpuNchwPtrS = (void **)malloc(sizeof(void *) * outputNum);
//分配 存放MLU端输入/输出地址的 指针数组
outputMluPtrS = (void **)malloc(sizeof(void *) * outputNum);
inputMluPtrS = (void **)malloc(sizeof(void *) * inputNum);
//为输入节点 分配CPU/MLU内存
for (int i = 0; i < inputNum; i++)
{
CNRT_CHECK(cnrtMalloc(&inputMluPtrS[i],inputSizeS[i])); //分配MLU上内存
inputCpuPtrS[i] = (void *)malloc(inputSizeS[i]); //分配CPU上的内存
//获取输入的维度信息 NHWC
CNRT_CHECK(cnrtGetInputDataShape(&dimValues,&dimNum,i,function));
printf("input shape:\n");
for(int y=0;y<dimNum;y++)
{
printf("%d ",dimValues[y]);
}
printf("\n");
input_width=dimValues[2];
input_height=dimValues[1];
batch_size=dimValues[0];
free(dimValues);
}
//为输出节点 分配CPU/MLU内存
for (int i = 0; i < outputNum; i++) {
CNRT_CHECK(cnrtMalloc(&outputMluPtrS[i],outputSizeS[i])); //分配MLU上内存
outputCpuPtrS[i] = (void *)malloc(outputSizeS[i]); //分配CPU上的内存
//获取输出的维度信息 NHWC
CNRT_CHECK(cnrtGetOutputDataShape(&dimValues,&dimNum,i,function));
int count=1;
printf("output shape:\n");
for(int y=0;y<dimNum;y++)
{
printf("%d ",dimValues[y]);
count=count*dimValues[y];
}
printf("\n");
outputCpuNchwPtrS[i] = (void *)malloc(count*sizeof(float)); //将输出转为float32类型,方便用户后处理
output_count.push_back(count);
free(dimValues);
}
//配置MLU输入/输出 地址的指针
param = (void **)malloc(sizeof(void *) * (inputNum + outputNum));
for (int i = 0; i < inputNum; i++) {
param[i] = inputMluPtrS[i];
}
for (int i = 0; i < outputNum; i++) {
param[i + inputNum] = outputMluPtrS[i];
}对输入的数据做预处理,同在线推理数据预处理保持一致。同时需要注意可以从离线模型信息文件*.cambricon_twins中可以得到输入输出类型以及形状等信息,在做预处理时如果使用opencv接口时要使数据类型保持一致,比如此时我们用了CV_8UC4。部分代码如下:
cv::Mat sample_temp; float img_w = input_image.cols; float img_h = input_image.rows; cv::Mat sample_temp_bgr(input_image.cols, input_image.rows, CV_8UC4); float img_scale = img_w < img_h ? (input_height / img_h) : (input_width / img_w); int new_w = std::floor(img_w * img_scale); int new_h = std::floor(img_h * img_scale); cv::cvtColor(input_image, sample_temp_bgr, CV_BGR2BGRA); cv::resize(sample_temp_bgr, sample_temp, cv::Size(new_w, new_h), CV_INTER_LINEAR); cv::Mat net_input_data_rgba(input_height,input_width,CV_8UC4,ptr); sample_temp.copyTo(net_input_data_rgba( cv::Range((static_cast(input_height) - new_h) / 2, (static_cast(input_height) - new_h) / 2 + new_h), cv::Range((static_cast(input_width) - new_w) / 2, (static_cast(input_width) - new_w) / 2 + new_w))); ptr+=(input_height*input_width*4);
调用离线模型进行推理,部分代码如下:
unsigned int affinity=1<<dev_channel; //设置通道亲和性,使用指定的MLU cluster做推理 cnrtInvokeParam_t invokeParam; //invoke参数 invokeParam.invoke_param_type=CNRT_INVOKE_PARAM_TYPE_0; invokeParam.cluster_affinity.affinity=&affinity; CNRT_CHECK(cnrtInvokeRuntimeContext_V2(ctx,nullptr,param,queue,&invokeParam));
对推理后数据做后处理,同在线推理数据后处理保持一致,部分代码如下:
vector<vector<vector>> getResults(float* outputData,
int dimNumm,
int *dimValues) {
vector<vector<vector>> detections;
// BangOp implementation
float max_limit = 1;
float min_limit = 0;
int batchSize = dimValues[0];
int count = dimValues[3];
for (int i = 0; i < batchSize; i++) {
int num_boxes = static_cast(outputData[i * count]);
vector<vector> batch_box;
for (int k = 0; k < num_boxes; k++) {
int index = i * count + 64 + k * 7;
vector single_box;
float bl = std::max(
min_limit, std::min(max_limit, outputData[index + 3])); // x1
float br = std::max(
min_limit, std::min(max_limit, outputData[index + 5])); // x2
float bt = std::max(
min_limit, std::min(max_limit, outputData[index + 4])); // y1
float bb = std::max(
min_limit, std::min(max_limit, outputData[index + 6])); // y2
single_box.push_back(bl);
single_box.push_back(bt);
single_box.push_back(br);
single_box.push_back(bb);
single_box.push_back(outputData[index + 2]);
single_box.push_back(outputData[index + 1]);
if ((br - bl) > 0 && (bb - bt) > 0) {
batch_box.push_back(single_box);
}
}
detections.push_back(batch_box);
}
return detections;
}更多cnrt离线模型示例可以参考:http://www.cambricon.com/docs/cnrt/user_guide_html/example/offline_mode.html
热门帖子
精华帖子