C++调用yolov5 onnx模型的初步探索

yolov5-dnn-cpp-python
https://github.com/hpc203/yolov5-dnn-cpp-python

转onnx:

用opencv的dnn模块做yolov5目标检测的程序,包含两个步骤:(1).把pytorch的训练模型.pth文件转换到.onnx文件。(2).opencv的dnn模块读取.onnx文件做前向计算。

SiLU其实就是swish激活函数,而在onnx模型里是不直接支持swish算子的,因此在转换生成onnx文件时,SiLU激活函数不能直接使用nn.Module里提供的接口,而需要自定义实现它。
修改Focus类,替换切片操作。
把Detect类里面的1x1卷积定义在紧邻着Detect类之前的外面,然后去掉Detect类,组成新的model,作为torch.onnx.export的输入。
torch.onnx.export(model, inputs, output_onnx, verbose=False, opset_version=12, input_names=['images'], output_names=['out0', 'out1', 'out2'])
最后生成的onnx文件,opencv的dnn模块就能成功读取了,接下来对照Detect类里的forward函数,用python或者C++编写计算预测框的中心坐标和高宽的功能。

在转换生成onnx文件,你需要执行两个步骤,
第一步把原始训练模型.pt文件里的参数保存到新的.pth文件里,
第二步编写yolov5.py文件,把yolov5的网络结构定义在.py文件里,此时需要注意网络结构里不能包含切片对象赋值操作,F.interpolate里的size参数需要加int强制转换。
在执行完这两步之后才能生成一个opencv能成功读取并且做前向推理的onnx文件。

不过,最近我发现在yolov5-pytorch程序里,其实可以直接把原始训练模型.pt文件转换生成onnx文件的,而且我在一个yolov5检测人脸+关键点的程序里实验成功了。
https://blog.csdn.net/nihate/article/details/112731327

作者用的模型
https://github.com/hpc203/yolov5-dnn-cpp-python/issues/21
https://github.com/ultralytics/yolov5/releases/tag/v4.0

问题:
warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
https://blog.csdn.net/lcb_coconut/article/details/76136725

ModuleNotFoundError: No module named ‘models‘解决torch.load问题【天坑】
https://blog.csdn.net/weixin_42815846/article/details/115289861

抽取模型参数
 

转onnx成功,会打印如下信息
 

==============================================================================================================
yolov5-opencv-dnn-cpp
https://github.com/UNeedCryDear/yolov5-opencv-dnn-cpp  (保存图片没有框)

opencv YOLO DNNs
https://docs.opencv.org/4.x/da/d9d/tutorial_dnn_yolo.html

cv::dnn::DetectionModel

void cv::dnn::DetectionModel::detect(
InputArray frame, // 输入图像
std::vector< int > & classIds, // 输出类别index
std::vector< float > & confidences, // 得分
std::vector< Rect > & boxes, // 目标框
float confThreshold = 0.5f, // 阈值
float nmsThreshold = 0.0f  // NMS
)
https://cloud.tencent.com/developer/article/1536443


C++ 动态batch onnx推理

多个batch

    //将image1和image2合并到images
    vector<Mat> images;
    images.push_back(image1);
    images.push_back(image2);
    vector<String> labels = readClassNames();

    Mat inputBlob = blobFromImages(images, 1.0, Size(w, h), Scalar(0, 0, 0), false, true);

    // 执行图像分类
    net.setInput(inputBlob);
    cv::Mat prob = net.forward();     // 推理出结果
    cout << prob.cols<< endl;

    for (int n = 0; n < prob.rows; n++) {
        Point classNumber;
        double classProb;
        Mat probMat = prob(Rect(0, n, 1000, 1)).clone();
        Mat result = probMat.reshape(1, 1);
        minMaxLoc(result, NULL, &classProb, NULL, &classNumber);
        int classidx = classNumber.x;
        printf("\n current image classification : %s, possible : %.2f\n", labels.at(classidx).c_str(), classProb);
    }
https://blog.csdn.net/qq_44747572/article/details/121467657

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WX Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值