软件视频地址:视频地址
代码开源地址
- 之前用Python配合YOLOV11开发一个了分类训练软件,软件只要准备好数据,然后导入就可以训练数据,训练完成后还可以验证,测试,但是要真正落地,还是有点欠缺。
- 配合YOLOV11训练后导出的onnx模型,再开发一个Qt软件,主要是调用onnx模型。
- 软件界面
4. 软件运行效果
5. 核心代码
/***创建一个环境****/_env=Ort::Env(ORT_LOGGING_LEVEL_ERROR, "OnnxModel");/***初始化Session选项 使用10个线程执行op,若想提升速度,增加线程数***/_session_options.SetInterOpNumThreads(1);/***ORT_ENABLE_ALL: 启用所有可能的优化***///session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);_session_options.SetGraphOptimizationLevel( GraphOptimizationLevel::ORT_ENABLE_ALL);
/***获取QString的UTF-16表示****/const ushort* utf16Data = model_path_.utf16();int length = model_path_.length();/***分配足够的空间来存储wchar_t字符串(包括空字符)***/std::vector<wchar_t> wcharArray(length + 1);/***复制数据到新的wchar_t数组****/std::copy(utf16Data, utf16Data + length, wcharArray.begin());wcharArray[length] = L'\0';ORTCHAR_T* session_model_path=wcharArray.data();/***创建一个回话***/_session=new Ort::Session(_env,session_model_path,_session_options);/***获取输入输出的批量节点***/_num_input_nodes = _session->GetInputCount();_num_output_nodes = _session->GetOutputCount();Ort::AllocatorWithDefaultOptions allocator_;/***确定输入的维度,和输入的入口名****///_input_node_names={"input"};_input_node_names.resize(_num_input_nodes);_input_node_name_strings.resize(_num_input_nodes);for (int i = 0; i < _num_input_nodes; i++){Ort::TypeInfo type_info = _session->GetInputTypeInfo(i);auto tensor_info = type_info.GetTensorTypeAndShapeInfo();ONNXTensorElementDataType type = tensor_info.GetElementType();std::vector<int64_t> in_node_shape = tensor_info.GetShape();int shape_index = 0;for (auto& shape: in_node_shape){_input_node_dims[shape_index++] = shape;}_input_node_name_strings[i]=_session->GetInputNameAllocated(i, allocator_).get();_input_node_names[i]=_input_node_name_strings[i].c_str();}/***确定输出的维度,和输出的出口名称****///_output_node_names={"output"};_output_node_names.resize(_num_output_nodes);_output_node_name_strings.resize(_num_output_nodes);for (int i = 0; i < _num_output_nodes; i++){Ort::TypeInfo type_info = _session->GetOutputTypeInfo(i);auto tensor_info = type_info.GetTensorTypeAndShapeInfo();std::vector<int64_t> out_node_shape = tensor_info.GetShape();int shape_index = 0;for (auto& shape : out_node_shape){_output_node_dims[shape_index++] = shape;}_output_node_name_strings[i]=_session->GetOutputNameAllocated(i,allocator_).get();_output_node_names[i]=_output_node_name_strings[i].c_str();}
/***创建内存信息***/Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeCPU);vector<Ort::Value> input_tensors;input_tensors.push_back(Ort::Value::CreateTensor<float>(memory_info,/***处理内存的地方***/input_tensor_values.data(),/***数据***/input_tensor_values.size(),/****数据大小****/_input_node_dims.data(),/****维度数据****/_input_node_dims.size()));_output_tensor.clear();/***创建一个运行的选项***/Ort::RunOptions r_op;_output_tensor = _session->Run(r_op,/****运行*****/_input_node_names.data(),/*****输入的名称******/input_tensors.data(),/****输入的数据******/_input_node_names.size(),/****输入的量******/_output_node_names.data(),/***输出的名*****/_output_node_names.size());/***输出的维度大小*****//***获取反馈的结构***/auto info_=_output_tensor.front().GetTensorTypeAndShapeInfo();std::vector<int64_t> shape_=info_.GetShape();int batch_size_=shape_[0];//识别的批次int class_count_=shape_[1];//识别到的类int out_size= _output_tensor.size();float const *output_tensor_=_output_tensor[0].GetTensorData<float>();float ng_sorce_=output_tensor_[0];float ok_sorce_=output_tensor_[1];if(ng_sorce_>ok_sorce_){_class_str="ng:"+QString::number(ng_sorce_);_class_id=0;}else{_class_str="ok:"+QString::number(ok_sorce_);_class_id=1;}