千家信息网

c++如何实现yolov5转onnx

发表于:2024-12-01 作者:千家信息网编辑
千家信息网最后更新 2024年12月01日,本篇内容介绍了"c++如何实现yolov5转onnx"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!训
千家信息网最后更新 2024年12月01日c++如何实现yolov5转onnx

本篇内容介绍了"c++如何实现yolov5转onnx"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

训练模型.pt转onnx

训练部分根据呼声再决定要不要写一份博客吧!!
注意事项:
1.训练代码一定要选择yolov5 5.0版本
2. 进入models/exprort.py;

3.将红框区域换成你自己的训练完的模型

4.将版本换成12;

5.直接运行即可,会生成出onnx的模型出来。

c++代码解析

博主使用的是opencv4.5.3版本,已经编译好的,需要直接扫码加我发你

main函数部分

读取模型利用的是dnn::readNet,opencv其实挺强大的博主已经读过tf模型,torch模型后续都会出对应博客,这里总共有三点改,输入图片path,输入类别名class_names,net部分改成自己的模型

net.set这些参数都固定就好,有兴趣的同学可以研究研究DNN_TARGET_CPU这个地方,是可以使用gpu和cuda的,但是博主还没复现过

推理部分讲解

void postprocess(cv::Mat& cv_src, std::vector& outs, const std::vector& classes, int net_size){        float confThreshold = 0.1f;        float nmsThreshold = 0.1f;        std::vector classIds;        std::vector confidences;        std::vector boxes;        int strides[] = { 8, 16, 32 };        std::vector > anchors =        {                { 10,13, 16,30, 33,23 },                { 30,61, 62,45, 59,119 },                { 116,90, 156,198, 373,326 }        };        for (size_t k = 0; k < outs.size(); k++)        {                float* data = outs[k].ptr();                int stride = strides[k];                int num_classes = outs[k].size[4] - 5;                for (int i = 0; i < outs[k].size[2]; i++)                {                        for (int j = 0; j < outs[k].size[3]; j++)                        {                                for (int a = 0; a < outs[k].size[1]; ++a)                                {                                        float* record = data + a * outs[k].size[2] * outs[k].size[3] * outs[k].size[4] +                                                i * outs[k].size[3] * outs[k].size[4] + j * outs[k].size[4];                                        float* cls_ptr = record + 5;                                        for (int cls = 0; cls < num_classes; cls++)                                        {                                                float score = sigmoid(cls_ptr[cls]) * sigmoid(record[4]);                                                if (score > confThreshold)                                                {                                                        float cx = (sigmoid(record[0]) * 2.f - 0.5f + (float)j) * (float)stride;                                                        float cy = (sigmoid(record[1]) * 2.f - 0.5f + (float)i) * (float)stride;                                                        float w = pow(sigmoid(record[2]) * 2.f, 2) * anchors[k][2 * a];                                                        float h = pow(sigmoid(record[3]) * 2.f, 2) * anchors[k][2 * a + 1];                                                        float x1 = std::max(0, std::min(cv_src.cols, int((cx - w / 2.f) * (float)cv_src.cols / (float)net_size)));                                                        float y1 = std::max(0, std::min(cv_src.rows, int((cy - h / 2.f) * (float)cv_src.rows / (float)net_size)));                                                        float x2 = std::max(0, std::min(cv_src.cols, int((cx + w / 2.f) * (float)cv_src.cols / (float)net_size)));                                                        float y2 = std::max(0, std::min(cv_src.rows, int((cy + h / 2.f) * (float)cv_src.rows / (float)net_size)));                                                        classIds.push_back(cls);                                                        confidences.push_back(score);                                                        boxes.push_back(cv::Rect(cv::Point(x1, y1), cv::Point(x2, y2)));                                                }                                        }                                }                        }                }        }        std::vector indices;        cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);        for (size_t i = 0; i < indices.size(); i++)        {                int idx = indices[i];                cv::Rect box = boxes[idx];                drawPred(classIds[idx], confidences[idx], box.x, box.y,                        box.x + box.width, box.y + box.height, cv_src, classes);        }}

抬头部分是两大目标检测的阈值设置,然后anchors这些都不建议动,除非你在训练的时候用了你自己生成的anchors的话,就改成你自己的,然后根据训练推理后,会生成我们所对应的坐标框以及分数,将分数和狂送到容器中,dnn中有nms等底层函数哦
cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
对应输入就可以了,然后得到我们的Box,index,和置信度,接下来就到了我们的画图环节。

darpred部分

void drawPred(int classId, float conf, int left, int top, int right, int bottom, cv::Mat& frame,        const std::vector& classes){        cv::rectangle(frame, cv::Point(left, top), cv::Point(right, bottom), cv::Scalar(0, 255, 0), 3);        std::string label = cv::format("%.2f", conf);        if (!classes.empty()) {                CV_Assert(classId < (int)classes.size());                label = classes[classId] + ": " + label;        }        int baseLine;        cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);        top = std::max(top, labelSize.height);        cv::rectangle(frame, cv::Point(left, top - round(1.5 * labelSize.height)), cv::Point(left + round(1.5 * labelSize.width), top + baseLine), cv::Scalar(0, 255, 0), cv::FILLED);        cv::putText(frame, label, cv::Point(left, top), cv::FONT_HERSHEY_SIMPLEX, 0.75, cv::Scalar(), 2);}

sigmod部分

inline float sigmoid(float x){        return 1.f / (1.f + exp(-x));}

"c++如何实现yolov5转onnx"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0