打开微信,使用扫一扫进入页面后,点击右上角菜单,
点击“发送给朋友”或“分享到朋友圈”完成分享
对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
热门帖子
精华帖子