2022.09.29更新 c++下面部署yolov5实例分割模型(六)

零、写在最前面:

2023.01.11 更新:

新增加onnxruntime的1.13.x版本支持。

由于onnxruntime从1.12升级到1.13之后,GetOutputName()这个API变成了GetOutputNameAllocated(),坑就出现在这里,新版api的返回值是一个unique_ptr指针,这就意味着他使用一次时候就失效了,所以在循环跑模型的时候基本的第二次都报错了。目前能想到的解决方法就是将其使用std::move()转成shared_ptr,这样可以在类生命周期之内都能存在,不会出现跑第一次就挂掉的情况。

2022.12.19更新:

新增onnxruntime推理实例分割模型,支持动态推理和批次推理,避免opencv不支持动态推理的尴尬境地。

2022.11.10更新:

上次的版本更新中,抠图是在最后的mask中抠图,而如果目标多并且目标小的话,特征图中的大部分区域都是无效数据,但是却参与了特征掩码与特征图计算mask图像的过程,在最后的步骤中才抠图去掉多余的无效数据。所以新版本我做了改变,直接从特征图中抠出有效区域进行计算,可以节省一大部分的时间,特别是检测框多,并且检测框都比较小的情况下效果更明显。

2022.10.13更新:

yolov5的实例分割结果mask从原来的整张图片的mask改成检测结果框内mask,节省内存空间和计算的速度,特别是计算crop区域和分割结果大于阈值的速度,这里用整张图的话,图片越大,检测结果越多,速度下降的厉害,也就是作者讲的计算分割结果需要的资源昂贵。贴个领带的mask结果示意图就明显看出来改动了:左边是整张图的mask,可以看到大部分黑色区域都是无效区域。

yolov5-seg分割模型目前已经发布了,而yolov7-mask目前由于opencv无法正确的读取问题,加上这个分支本身需要facebook的第三方库(这个库win下不好弄),所以一直没搞,opencv或者onnxruntime部署还在研究中,先开个贴占坑。

详细信息请移步:

yolov5-seg:https://github.com/ultralytics/yolov5

yolov7-mask:GitHub - WongKinYiu/yolov7 at mask

一、yolov5-seg

需要注意的是,有些人使用的是最新的torch1.12.x版本,在导出onnx的时候需要将do_constant_folding=True,这句换成false,否者dnn读取不了onnx文件,而onnxrutime可以,具体原因未知。

torch.onnx.export(
    model.cpu() if dynamic else model,  # --dynamic only compatible with cpu
    im.cpu() if dynamic else im,
    f,
    verbose=False,
    opset_version=opset,
    do_constant_folding=False,
    input_names=['images'],
    output_names=output_names,
    dynamic_axes=dynamic or None)

需要运行自己模型的小伙伴,需要跟你你自己的onnx导出情况,修改一些参数,包括,其中_segWidth和_segWidth和_segChannels可以通过https://netron.app/

	const int _netWidth = 640;   //ONNX图片输入宽度
	const int _netHeight = 640;  //ONNX图片输入高度
	const int _segWidth = 160;
	const int _segHeight = 160;
	const int _segChannels = 32;
	const int _strideSize = 3;   //stride size

其中,output0为目标检测的输出口+32通道mask的候选特征,与ouput1的mask图像proto叉乘之后得到缩小的mask图,再根据缩放情况进行缩放得到最终的mask图。

最后贴一张结果图:

 yolov5的实例分割模型目前已经更新,详细地址在:GitHub - UNeedCryDear/yolov5-seg-opencv-dnn-cpp: 使用opencv-dnn部署yolov5实例分割模型

测试模型可以自己导出或者用我导出的测试,建议跑自己模型的小伙伴先将demo跑通再去修改成自己的模型。

测试模型:https://download.csdn.net/download/qq_34124780/86745135

  • 9
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
抱歉,作为AI语言模型,我无法为您提供完整的代码。不过,我可以为您提供基于ONNX Runtime进行YOLOv5实例分割模型的推理的步骤介绍: 1. 安装ONNX Runtime。您可以参考官方文档进行安装,也可以使用以下命令: ``` pip install onnxruntime ``` 2. 加载模型。使用ONNX Runtime的API将导出的YOLOv5实例分割模型加载到内存中。 ``` const OrtApi* g_ort = OrtGetApiBase()->GetApi(ORT_API_VERSION); OrtEnv* env; g_ort->CreateEnv(ORT_LOGGING_LEVEL_WARNING, "test", &env); OrtSession* session; OrtSessionOptions* session_options; g_ort->CreateSessionOptions(&session_options); g_ort->SetIntraOpNumThreads(session_options, 1); g_ort->SetSessionGraphOptimizationLevel(session_options, ORT_ENABLE_ALL); g_ort->CreateSession(env, "yolov5s_instance_segmentation.onnx", session_options, &session); ``` 3. 准备输入数据。读取待处理的图像数据,并将其格式转换为模型可以接受的形式。 ``` std::vector<float> input_data(input_size); for (int i = 0; i < input_size; i++) { input_data[i] = image_data[i] / 255.0f; } // Create a tensor from the input data std::vector<int64_t> input_shape{1, 3, input_height, input_width}; OrtValue* input_tensor; g_ort->CreateTensorWithDataAsOrtValue(env, input_shape.data(), input_shape.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, input_data.data(), input_size * sizeof(float), ORT_DEVICE_CPU, &input_tensor); ``` 4. 进行推理。将输入数据送入模型进行推理,并得到输出结果。 ``` OrtRunOptions* run_options; g_ort->CreateRunOptions(&run_options); const char* input_name = "input"; const char* output_name = "output"; OrtValue* output_tensor = nullptr; g_ort->Run(session, run_options, input_name, input_tensor, 1, output_name, &output_tensor); // Get the output tensor shape and data const OrtTensorTypeAndShapeInfo* output_info = g_ort->GetTensorTypeAndShape(output_tensor); std::vector<int64_t> output_shape(output_info->GetShape(), output_info->GetShape() + output_info->GetDimensionsCount()); float* output_data = nullptr; g_ort->GetTensorMutableData(output_tensor, (void**)&output_data); ``` 5. 处理输出数据。将得到的输出结果进行后处理,得到实例分割的结果。 ``` // Postprocessing code // ... // cleanup g_ort->ReleaseRunOptions(run_options); g_ort->ReleaseTensor(input_tensor); g_ort->ReleaseTensor(output_tensor); g_ort->ReleaseSession(session); g_ort->ReleaseEnv(env); ``` 需要注意的是,这只是简要的步骤介绍,并且代码中需要替换的部分(如模型路径、输入输出节点名、输入数据格式、后处理代码等)也没有提供。完整的代码需要根据具体的模型和数据进行编写。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值