基于Yolov5的烟火检测——模型训练与C++实现部署
前言
1.系統環境是win10,顯卡RTX3080;cuda10.2,cudnn7.1;OpenCV4.5;yolov5用的是5s的模型,2020年8月13日的發布v3.0這個版本; ncnn版本是20210525;C++ IDE vs2019.
2.使用NCNN作模型推理加速庫,能更容易的使用GPU進行加速,代碼不需要改動很大就可以移植到邊緣設備或者移動端上。
一、數據集
1.數據集是使用網上收集的數據,大概2000多張左右。
2.標注工具用的是labelimg,標注了濃煙和火焰的位置。
3.手工標注是很費時費力的一件事情,如果是數據集一大這就很麻煩,但我一般的處理是先標注一批小的數據集之后,用yolov5l去訓練一個初始模型用來標注,之后用初始模型去自動標注,按標注工具的格式來就可以了。
4.標注好的數據分xml和jpg兩個目錄。
5.標注好的數據集下載地址:https://download.csdn.net/download/matt45m/84044933 。這里只標注了2000多張,還有兩萬多張樣本沒有標注,所以就沒有上傳,如果想把模型用于項目上,可以私聊我要沒有標注的數據集進行標注訓練。
二、模型訓練
1.我這里用的yolov5是2020年8月13日的發布v3.0這個版本,現在的yolov5已經到了m6了,但我的生產的環境一直是舊的版本,就沒有改,模型的步驟可以參考我之前寫的:https://blog.csdn.net/matt45m/article/details/118674051?spm=1001.2014.3001.5501 。
2.yolov5 v3的github地址:https://github.com/ultralytics/yolov5/tree/v3.0 。
三.模型轉換
1.pt模型轉onnx模型
# --weights: 訓練得到的模型 python models/export.py --weights runs/exp/weights/best.pt運行后,onnx模型保存為了runs/exp/weights/best.onnx,這個模型可以用OpenCV DNN理或者是onnxruntime推理。
但如果用DNN推理就要改下export.py源碼,可參考之前我之前寫的:https://blog.csdn.net/matt45m/article/details/118674207?spm=1001.2014.3001.5502
2.轉ncnn模型可以參考nihui大佬的知乎文章 《詳細記錄u版YOLOv5目標檢測ncnn實現》 。
3.但文章給出添加層的方式不適用于iOS系統,如果模型想在iOS上使用,則參考 https://github.com/Tencent/ncnn/wiki/add-custom-layer.zh 。
四.模型部署
1.如果要使用GPU加速,要安裝Vulkan,步驟如下:
1.1.安裝CMake,并把xxx\xxx\CMake\bin添加系統環境變量。
1.2.安裝Vulkan各它的依賴庫。
2.C++代碼:
void drawObjectsYolo(const cv::Mat& bgr, cv::Mat& cv_dst, std::vector<ObjectFlag>& objects) {static const char* class_names[] = {"fire", "smoke"};cv_dst = bgr.clone();for (size_t i = 0; i < objects.size(); i++){const ObjectFlag& obj = objects[i];std::cout << "Object name: " << class_names[obj.label] << " Proba = " << obj.prob * 100 << std::endl;cv::rectangle(cv_dst, obj.rect, cv::Scalar(255, 0, 0));char text[256];sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);int baseLine = 0;cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 1, 2, &baseLine);int x = obj.rect.x;int y = obj.rect.y - label_size.height - baseLine;if (y < 0)y = 0;if (x + label_size.width > cv_dst.cols)x = cv_dst.cols - label_size.width;cv::putText(cv_dst, text, cv::Point(x, y + label_size.height),cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255));} }int initDetectionNet(std::string param_path,std::string model_path, ncnn::Net& td_net, bool use_gpu) {bool has_gpu = false;#if NCNN_VULKANncnn::create_gpu_instance();has_gpu = ncnn::get_gpu_count() > 0; #endifbool to_use_gpu = has_gpu && use_gpu;td_net.opt.use_vulkan_compute = to_use_gpu;int rp = -1;int rm = -1;td_net.opt.use_fp16_arithmetic = true;rp = td_net.load_param(param_path.c_str());rm = td_net.load_model(model_path.c_str());if (rp < 0 || rm < 0){return -70;}if (to_use_gpu){return 1;}return 0; }std::string param_path = "models/fire_smoke.param"; std::string model_path = "models/fire_smoke.bin";//path 圖像目錄 void detectionImages(std::string path = "fire_test_images") {std::vector<std::string> filenames;cv::glob(path, filenames, false);ncnn::Net td_net;int rn = initDetectionNet(param_path, model_path, td_net, true);for (auto name : filenames){cv::Mat cv_src = cv::imread(name);if (cv_src.empty()){continue;}std::vector<ObjectFlag> objects;double start = static_cast<double>(cv::getTickCount());detectYolov5(cv_src, td_net, objects, 4, 640, 0.25f, 0.45f);double time = ((double)cv::getTickCount() - start) / cv::getTickFrequency();std::cout << "Target detection time: " << time << "(s)" << std::endl;cv::Mat cv_dst;drawObjectsYolo(cv_src, cv_dst, objects);cv::imshow("cv_dst", cv_dst);cv::waitKey();} }void detectionVideo(std::string path = "fire.mp4") {ncnn::Net td_net;int rn = initDetectionNet(param_path, model_path, td_net, true);cv::VideoCapture cap;//如果想要打開攝像頭//cap.open(0);//攝像頭索引cap.open(path);if (!cap.isOpened()){return;}cv::Mat cv_src;while (1){cap >> cv_src;if (cv_src.empty()){break;}std::vector<ObjectFlag> objects;cv::Mat cv_dst;double start = static_cast<double>(cv::getTickCount());detectYolov5(cv_src, td_net, objects, 4, 640, 0.25f, 0.45f);double time = ((double)cv::getTickCount() - start) / cv::getTickFrequency();std::cout << "Target detection time: " << time << "(s)" << std::endl;drawObjectsYolo(cv_src, cv_dst, objects);cv::imshow("cv_dst", cv_dst);cv::waitKey(24);}cap.release(); }int main(void) {detectionVideo(); }2.圖像測試效果
3.視頻檢測:
4.源碼: https://download.csdn.net/download/matt45m/84050225
五、備注
1.當前訓練的圖像只有2000多張,如果想要提高精度可以加數據樣本,我這里還有幾萬張沒有標注的數據,有興趣的小伙伴可以問我要沒有標注的數據集。
2.yolov5s的NCNN模型是可以部署到安卓或iOS上的。
總結
以上是生活随笔為你收集整理的基于Yolov5的烟火检测——模型训练与C++实现部署的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Rus入门到放弃——HashMap和BT
- 下一篇: 基于深度学习的人脸检测与静默活体检测——