網(wǎng)站首頁 編程語言 正文
介紹
現(xiàn)在很多開發(fā)都是需要用c++做最后一步的移植部署,手寫吧,先不說你會不會浪費時間,網(wǎng)上找吧,問題千奇百怪,所以給大家出這篇文章,做雷鋒教學,話不多說,開始
訓練模型.pt轉(zhuǎn)onnx
訓練部分根據(jù)呼聲再決定要不要寫一份博客吧??!
注意事項:
1.訓練代碼一定要選擇yolov5 5.0版本
2. 進入models/exprort.py;
3.將紅框區(qū)域換成你自己的訓練完的模型
4.將版本換成12;
5.直接運行即可,會生成出onnx的模型出來。
c++代碼解析
博主使用的是opencv4.5.3版本,已經(jīng)編譯好的,需要直接掃碼加我發(fā)你
main函數(shù)部分
讀取模型利用的是dnn::readNet,opencv其實挺強大的博主已經(jīng)讀過tf模型,torch模型后續(xù)都會出對應博客,這里總共有三點改,輸入圖片path,輸入類別名class_names,net部分改成自己的模型
net.set這些參數(shù)都固定就好,有興趣的同學可以研究研究DNN_TARGET_CPU這個地方,是可以使用gpu和cuda的,但是博主還沒復現(xiàn)過
推理部分講解
void postprocess(cv::Mat& cv_src, std::vector<cv::Mat>& outs, const std::vector<std::string>& classes, int net_size) { float confThreshold = 0.1f; float nmsThreshold = 0.1f; std::vector<int> classIds; std::vector<float> confidences; std::vector<cv::Rect> boxes; int strides[] = { 8, 16, 32 }; std::vector<std::vector<int> > 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<float>(); 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<int> 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); } }
抬頭部分是兩大目標檢測的閾值設(shè)置,然后anchors這些都不建議動,除非你在訓練的時候用了你自己生成的anchors的話,就改成你自己的,然后根據(jù)訓練推理后,會生成我們所對應的坐標框以及分數(shù),將分數(shù)和狂送到容器中,dnn中有nms等底層函數(shù)哦
cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
對應輸入就可以了,然后得到我們的Box,index,和置信度,接下來就到了我們的畫圖環(huán)節(jié)。
darpred部分
void drawPred(int classId, float conf, int left, int top, int right, int bottom, cv::Mat& frame, const std::vector<std::string>& 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)); }
結(jié)尾
原文鏈接:https://blog.csdn.net/xiaojunjun200211/article/details/121784214
相關(guān)推薦
- 2022-09-07 詳解C語言結(jié)構(gòu)體,枚舉,聯(lián)合體的使用_C 語言
- 2022-12-21 Python?threading中l(wèi)ock的使用詳解_python
- 2022-03-26 Linux快速部署Redis_Redis
- 2022-10-28 keepalived對nginx進行高可用搭建及原理詳解_nginx
- 2022-03-19 詳解C語言結(jié)構(gòu)體的定義和使用_C 語言
- 2022-06-15 C++詳細講解繼承與虛繼承實現(xiàn)_C 語言
- 2022-03-27 Android?Studio實現(xiàn)井字游戲_Android
- 2023-03-13 React之虛擬DOM的實現(xiàn)原理_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支