STATUS SampleDetector::InitModel(const std::string &strModelName)
{
SDKLOG(INFO) << "load model " << strModelName;
auto ret = aclmdlQuerySize(strModelName.c_str(), &mModelMSize, &mModelWSize);
ret = aclrtMalloc(&mModelMptr, mModelMSize, ACL_MEM_MALLOC_HUGE_FIRST);
ret = aclrtMalloc(&mModelWptr, mModelWSize, ACL_MEM_MALLOC_HUGE_FIRST);
ret = aclmdlLoadFromFileWithMem(strModelName.c_str(), &mModelID, mModelMptr,mModelMSize, mModelWptr, mModelWSize);
mModelDescPtr = aclmdlCreateDesc();
ret = aclmdlGetDesc(mModelDescPtr, mModelID);
// 创建模型输出的数据集结构
mInputDatasetPtr = aclmdlCreateDataset();
mOutputDatasetPtr = aclmdlCreateDataset();
//获取模型的输入个数,为输入分配内存并创建输出数据集
int iModelInputNum = aclmdlGetNumInputs(mModelDescPtr);
SDKLOG(INFO) << "num of inputs " << iModelInputNum;
{
aclmdlGetInputDims(mModelDescPtr, 0, &m_input_dims);
SDKLOG(INFO) << "input dim is : "<< m_input_dims.dims[0] << " " << m_input_dims.dims[1] << " " << m_input_dims.dims[2] << " " << m_input_dims.dims[3];
size_t buffer_size = aclmdlGetInputSizeByIndex(mModelDescPtr, 0);
mModelInputSize.width = m_input_dims.dims[2];
mModelInputSize.height = m_input_dims.dims[3];
ret = aclrtMalloc(&m_input_buffer, aclmdlGetInputSizeByIndex(mModelDescPtr, 0), ACL_MEM_MALLOC_NORMAL_ONLY);
m_input_data_buffer = aclCreateDataBuffer(m_input_buffer, buffer_size);
ret = aclmdlAddDatasetBuffer(mInputDatasetPtr, m_input_data_buffer);
}
//获取模型的输出个数,为输出分配内存并创建输出数据集
mModelOutputNums = aclmdlGetNumOutputs(mModelDescPtr);
SDKLOG(INFO) << "num of outputs " << mModelOutputNums;
{
size_t buffer_size = aclmdlGetOutputSizeByIndex(mModelDescPtr, 0);
aclmdlGetOutputDims(mModelDescPtr, 0, &m_output_dims);
SDKLOG(INFO) << "output dims is : " << m_output_dims.dims[0] << " " << m_output_dims.dims[1] << " " << m_output_dims.dims[2] << " " << m_output_dims.dims[3];
if(mAclRunMode == ACL_HOST) m_output_buffer_host= new char[aclmdlGetOutputSizeByIndex(mModelDescPtr, 0)]();
ret = aclrtMalloc(&m_output_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
m_output_data_buffer = aclCreateDataBuffer(m_output_buffer, buffer_size);
ret = aclmdlAddDatasetBuffer(mOutputDatasetPtr, m_output_data_buffer);
}
aclrtGetRunMode(&mAclRunMode);
if(mAclRunMode == ACL_DEVICE)
{
SDKLOG(INFO) << "run in device mode";
}
else
{
SDKLOG(INFO) << "run in host mode";
}
//预处理功能
if(mAclRunMode == ACL_DEVICE)
{
size_t single_chn_size = m_input_dims.dims[0] * m_input_dims.dims[2] * m_input_dims.dims[3] * sizeof(float);
m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer);
m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer + single_chn_size);
m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer + 2 * single_chn_size);
}
return STATUS_SUCCESS;
}
STATUS SampleDetector::Detect(const cv::Mat &inFrame, std::vector<BoxInfo> &result, float thresh)
{
// set current context
auto ret = aclrtSetCurrentContext(mAclContext);
if (ret != ACL_ERROR_NONE)
{
SDKLOG(ERROR) << "acl set context failed! aclError= " << ret;
return ERROR_INITACL;
}
mThresh = thresh;
mInputHeight = inFrame.cols;
mInputWidth = inFrame.rows;
//预处理
cv::Mat in_mat = inFrame.clone();
//等比例缩放
float r = std::min(mModelInputSize.width / static_cast<float>(in_mat.rows), mModelInputSize.height / static_cast<float>(in_mat.cols));
cv::Size new_size = cv::Size{static_cast<int>(in_mat.cols * r), static_cast<int>(in_mat.rows * r)};
SDKLOG(INFO) << "model input: "<< mModelInputSize.width << mModelInputSize.height;
SDKLOG(INFO) << "cv::Size " << new_size.width << new_size.height << r;
SDKLOG(INFO) << "cv::Size inMat " << in_mat.rows << in_mat.cols ;
cv::Mat resized_mat;
cv::resize(in_mat, resized_mat, new_size);
if(m_board.empty())
{
m_board = cv::Mat(mModelInputSize, CV_8UC3, cv::Scalar(114, 114, 114));
}
resized_mat.copyTo(m_board(cv::Rect{0, 0, resized_mat.cols, resized_mat.rows}));
//色阈转换BGR2RGB
cv::cvtColor(m_board, m_board, cv::COLOR_BGR2RGB);
//转浮点型归一化,hwc2chw
m_board.convertTo(m_normalized_mat, CV_32FC3, 1/255.);
// std::vector<cv::Mat> m_chw_wrappers;
cv::split(m_normalized_mat, m_chw_wrappers);
if(mAclRunMode == ACL_HOST)
{
size_t single_chn_size = m_chw_wrappers[0].rows * m_chw_wrappers[0].cols * sizeof(float);
aclrtMemcpy(m_input_buffer, single_chn_size, m_chw_wrappers[0].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE);
aclrtMemcpy((char*)m_input_buffer + single_chn_size, single_chn_size, m_chw_wrappers[1].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE);
aclrtMemcpy((char*)m_input_buffer + 2 * single_chn_size, single_chn_size, m_chw_wrappers[2].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE);
}
SDKLOG(INFO) << "before inference";
//运行模型推理
STATUS status = doInference();
SDKLOG(INFO) << "after inference";
//解析yolo层的输出
float scale = std::min(m_input_dims.dims[3] / (in_mat.cols * 1.0), m_input_dims.dims[2] / (in_mat.rows * 1.0));
std::vector<BoxInfo> detBoxes{};
void* obuf = nullptr;
if(mAclRunMode == ACL_HOST)
{
size_t cp_size = m_output_dims.dims[0] * m_output_dims.dims[1] * m_output_dims.dims[2] * sizeof(float);
aclrtMemcpy(m_output_buffer_host, cp_size, m_output_buffer, cp_size, ACL_MEMCPY_DEVICE_TO_HOST);
obuf = m_output_buffer_host;
}
else
{
obuf = m_output_buffer;
}
decode_outputs((float*)obuf, detBoxes, scale, in_mat.cols, in_mat.rows);
runNms(detBoxes);
result = detBoxes;
return STATUS_SUCCESS;
}
本文验证的模型是yolov5s模型,训练好对应的best.pt后,通过yolov5 对应的export.py文件将模型转换成onnx格式:
python export.py --weights best.pt --include ONNX硬件平台是昇腾-310,host模式,通过atc工具将best.onnx转换成指定的格式:
atc --model best.onnx --framework 5 --output best.om --soc_version Ascend310模型初始化推理:
STATUS SampleDetector::InitModel(const std::string &strModelName) { SDKLOG(INFO) << "load model " << strModelName; auto ret = aclmdlQuerySize(strModelName.c_str(), &mModelMSize, &mModelWSize); ret = aclrtMalloc(&mModelMptr, mModelMSize, ACL_MEM_MALLOC_HUGE_FIRST); ret = aclrtMalloc(&mModelWptr, mModelWSize, ACL_MEM_MALLOC_HUGE_FIRST); ret = aclmdlLoadFromFileWithMem(strModelName.c_str(), &mModelID, mModelMptr,mModelMSize, mModelWptr, mModelWSize); mModelDescPtr = aclmdlCreateDesc(); ret = aclmdlGetDesc(mModelDescPtr, mModelID); // 创建模型输出的数据集结构 mInputDatasetPtr = aclmdlCreateDataset(); mOutputDatasetPtr = aclmdlCreateDataset(); //获取模型的输入个数,为输入分配内存并创建输出数据集 int iModelInputNum = aclmdlGetNumInputs(mModelDescPtr); SDKLOG(INFO) << "num of inputs " << iModelInputNum; { aclmdlGetInputDims(mModelDescPtr, 0, &m_input_dims); SDKLOG(INFO) << "input dim is : "<< m_input_dims.dims[0] << " " << m_input_dims.dims[1] << " " << m_input_dims.dims[2] << " " << m_input_dims.dims[3]; size_t buffer_size = aclmdlGetInputSizeByIndex(mModelDescPtr, 0); mModelInputSize.width = m_input_dims.dims[2]; mModelInputSize.height = m_input_dims.dims[3]; ret = aclrtMalloc(&m_input_buffer, aclmdlGetInputSizeByIndex(mModelDescPtr, 0), ACL_MEM_MALLOC_NORMAL_ONLY); m_input_data_buffer = aclCreateDataBuffer(m_input_buffer, buffer_size); ret = aclmdlAddDatasetBuffer(mInputDatasetPtr, m_input_data_buffer); } //获取模型的输出个数,为输出分配内存并创建输出数据集 mModelOutputNums = aclmdlGetNumOutputs(mModelDescPtr); SDKLOG(INFO) << "num of outputs " << mModelOutputNums; { size_t buffer_size = aclmdlGetOutputSizeByIndex(mModelDescPtr, 0); aclmdlGetOutputDims(mModelDescPtr, 0, &m_output_dims); SDKLOG(INFO) << "output dims is : " << m_output_dims.dims[0] << " " << m_output_dims.dims[1] << " " << m_output_dims.dims[2] << " " << m_output_dims.dims[3]; if(mAclRunMode == ACL_HOST) m_output_buffer_host= new char[aclmdlGetOutputSizeByIndex(mModelDescPtr, 0)](); ret = aclrtMalloc(&m_output_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY); m_output_data_buffer = aclCreateDataBuffer(m_output_buffer, buffer_size); ret = aclmdlAddDatasetBuffer(mOutputDatasetPtr, m_output_data_buffer); } aclrtGetRunMode(&mAclRunMode); if(mAclRunMode == ACL_DEVICE) { SDKLOG(INFO) << "run in device mode"; } else { SDKLOG(INFO) << "run in host mode"; } //预处理功能 if(mAclRunMode == ACL_DEVICE) { size_t single_chn_size = m_input_dims.dims[0] * m_input_dims.dims[2] * m_input_dims.dims[3] * sizeof(float); m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer); m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer + single_chn_size); m_chw_wrappers.emplace_back(m_input_dims.dims[2], m_input_dims.dims[3], CV_32FC1, m_input_buffer + 2 * single_chn_size); } return STATUS_SUCCESS; } STATUS SampleDetector::Detect(const cv::Mat &inFrame, std::vector<BoxInfo> &result, float thresh) { // set current context auto ret = aclrtSetCurrentContext(mAclContext); if (ret != ACL_ERROR_NONE) { SDKLOG(ERROR) << "acl set context failed! aclError= " << ret; return ERROR_INITACL; } mThresh = thresh; mInputHeight = inFrame.cols; mInputWidth = inFrame.rows; //预处理 cv::Mat in_mat = inFrame.clone(); //等比例缩放 float r = std::min(mModelInputSize.width / static_cast<float>(in_mat.rows), mModelInputSize.height / static_cast<float>(in_mat.cols)); cv::Size new_size = cv::Size{static_cast<int>(in_mat.cols * r), static_cast<int>(in_mat.rows * r)}; SDKLOG(INFO) << "model input: "<< mModelInputSize.width << mModelInputSize.height; SDKLOG(INFO) << "cv::Size " << new_size.width << new_size.height << r; SDKLOG(INFO) << "cv::Size inMat " << in_mat.rows << in_mat.cols ; cv::Mat resized_mat; cv::resize(in_mat, resized_mat, new_size); if(m_board.empty()) { m_board = cv::Mat(mModelInputSize, CV_8UC3, cv::Scalar(114, 114, 114)); } resized_mat.copyTo(m_board(cv::Rect{0, 0, resized_mat.cols, resized_mat.rows})); //色阈转换BGR2RGB cv::cvtColor(m_board, m_board, cv::COLOR_BGR2RGB); //转浮点型归一化,hwc2chw m_board.convertTo(m_normalized_mat, CV_32FC3, 1/255.); // std::vector<cv::Mat> m_chw_wrappers; cv::split(m_normalized_mat, m_chw_wrappers); if(mAclRunMode == ACL_HOST) { size_t single_chn_size = m_chw_wrappers[0].rows * m_chw_wrappers[0].cols * sizeof(float); aclrtMemcpy(m_input_buffer, single_chn_size, m_chw_wrappers[0].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy((char*)m_input_buffer + single_chn_size, single_chn_size, m_chw_wrappers[1].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy((char*)m_input_buffer + 2 * single_chn_size, single_chn_size, m_chw_wrappers[2].data, single_chn_size, ACL_MEMCPY_HOST_TO_DEVICE); } SDKLOG(INFO) << "before inference"; //运行模型推理 STATUS status = doInference(); SDKLOG(INFO) << "after inference"; //解析yolo层的输出 float scale = std::min(m_input_dims.dims[3] / (in_mat.cols * 1.0), m_input_dims.dims[2] / (in_mat.rows * 1.0)); std::vector<BoxInfo> detBoxes{}; void* obuf = nullptr; if(mAclRunMode == ACL_HOST) { size_t cp_size = m_output_dims.dims[0] * m_output_dims.dims[1] * m_output_dims.dims[2] * sizeof(float); aclrtMemcpy(m_output_buffer_host, cp_size, m_output_buffer, cp_size, ACL_MEMCPY_DEVICE_TO_HOST); obuf = m_output_buffer_host; } else { obuf = m_output_buffer; } decode_outputs((float*)obuf, detBoxes, scale, in_mat.cols, in_mat.rows); runNms(detBoxes); result = detBoxes; return STATUS_SUCCESS; }