c++ 调用yolo4训练后的模型

本文介绍如何使用YOLOv4进行目标检测,包括配置环境、加载模型、读取图片、检测对象并绘制边界框的过程。通过遍历图片文件夹,对每张图片进行检测,统计各类别检测结果及准确率。

搭配数据

1. darknet-master\build\darknet\x64\cfg\my_yolov4.cfg(修改参数的文件)

2. darknet-master\build\darknet\x64\data\myData.names(此为你的存标签类别的文件)

3. darknet-master\build\darknet\x64\backup\my_yolov4_last.weights(训练完成后生成的模型)

 

#include <iostream>
#include <fstream>
#ifdef _WIN32
#define OPENCV
#define GPU
#endif
#include <typeinfo>
#include <sstream>
#include <opencv2/opencv.hpp>
#include "darknet/yolo_v2_class.hpp" //引用动态链接库中的头文件
#include "opencv2/highgui/highgui.hpp"
#include <fstream>

#pragma comment(lib, "yolo_cpp_dll.lib") //引入YOLO动态链接库
//#pragma comment(lib, "opencv_world340d.lib") //引入OpenCV链接库,我在vs中配置过了,如果没配置请对应修改

using namespace cv;
using namespace std;


//以下两段代码来自yolo_console_dll.sln
void draw_boxes(Mat mat_img, vector<bbox_t> result_vec, vector<string> obj_names,
	int current_det_fps = -1, int current_cap_fps = -1)
{
	char destination[10];

	int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } };

	for (auto &i : result_vec) {
		Scalar color = obj_id_to_color(i.obj_id);
		rectangle(mat_img, Rect(i.x, i.y, i.w, i.h), color, 2);
		if (obj_names.size() > i.obj_id) {
			string obj_name = obj_names[i.obj_id];
			if (i.track_id > 0) obj_name += " - " + to_string(i.track_id);
			Size const text_size = getTextSize(obj_name, FONT_HERSHEY_COMPLEX_SMALL, 1.2, 2, 0);
			int const max_width = (text_size.width > i.w + 2) ? text_size.width : (i.w + 2);
			rectangle(mat_img, Point2f(max((int)i.x - 1, 0), max((int)i.y - 30, 0)),
				Point2f(min((int)i.x + max_width, mat_img.cols - 1), min((int)i.y, mat_img.rows - 1)),
				color, -1, 8, 0);
			putText(mat_img, obj_name, Point2f(i.x, i.y - 10), FONT_HERSHEY_COMPLEX_SMALL, 1.2, Scalar(255, 255, 255), 2);
			sprintf(destination, "%.3f", i.prob);
			putText(mat_img, destination, Point2f(i.x, i.y + 20), FONT_HERSHEY_COMPLEX_SMALL, 1.5, Scalar(255, 255, 255), 2);

		}
	}
	if (current_det_fps >= 0 && current_cap_fps >= 0) {
		string fps_str = "FPS detection: " + to_string(current_det_fps) + "   FPS capture: " + to_string(current_cap_fps);
		putText(mat_img, fps_str, Point2f(10, 20), FONT_HERSHEY_COMPLEX_SMALL, 1.2, Scalar(50, 255, 0), 2);

	}
}


vector<string> objects_names_from_file(string const filename) {
	ifstream file(filename);
	vector<string> file_lines;
	if (!file.is_open()) return file_lines;
	for (string line; getline(file, line);) file_lines.push_back(line);
	cout << "object names loaded \n";
	return file_lines;
}

int main()
{
	void getFiles(const string & path, vector<string> & files);
	string names_file = "D:/Q/c++/Project1/yolov4/myData.names";
	string cfg_file = "D:/Q/c++/Project1/yolov4/7/my_yolov4.cfg";
	string weights_file = "D:/Q/c++/Project1/yolov4/7/my_yolov4_last.weights";
	Detector detector(cfg_file, weights_file, 0); //初始化检测器
	vector<string> obj_names;
	ifstream ifs(names_file.c_str());
	//cout << ifs.size() << "__________" << endl;
	string line;
	while (getline(ifs, line)) obj_names.push_back(line);

	/*cout << "______________________________" << endl;
	cout << detector.cur_gpu_id << endl;
	cout << "______________________________" << endl;*/
	const string path = "D:/a";
	vector<string> files;
	getFiles(path, files);
	float unprint = 0.0;
	float stain = 0.0;
	float hole = 0.0;
	int unprint_count = 0;
	int stain_count = 0;
	int hole_count = 0;
	for (int i = 0; i < files.size(); i++)
	{
		//namedWindow("test", WINDOW_NORMAL);
		Mat frame = imread(files[i], -1);
		vector<bbox_t> result_vec = detector.detect(frame);
		draw_boxes(frame, result_vec, obj_names);
		for(int j = 0; j < result_vec.size(); j++)
		{ 
			if (obj_names[result_vec[j].obj_id] == "unprint")
			{
				unprint = unprint + result_vec[j].prob;
				unprint_count = unprint_count + 1;
				//cout << "unprint+++  " << unprint << endl;
				//cout << result_vec[j].prob << "***" << obj_names[result_vec[j].obj_id] << endl;
			}
			else if (obj_names[result_vec[j].obj_id] == "stain")
			{
				stain = stain + result_vec[j].prob;
				stain_count = stain_count + 1;
				cout << "stain+++  " << stain << endl;
				//cout << result_vec[j].prob << "***" << obj_names[result_vec[j].obj_id] << endl;
			}
			else {
				hole = hole + result_vec[j].prob;
				hole_count = hole_count + 1;
				cout << "hole+++  " << hole << endl;
				//cout << result_vec[j].prob << "***" << obj_names[result_vec[j].obj_id] << endl;
			}

			//cout << "______________________  " << endl;
			
			//cout << result_vec[j].prob << "***" << obj_names[result_vec[j].obj_id] << endl;
		}
		/*imshow("test", frame);
		waitKey();
		destroyAllWindows();*/
	}

	float unprint_accuracy = unprint / (float)unprint_count;
	float stain_accuracy = stain / (float)stain_count;
	float hole_accuracy = hole / (float)hole_count;
	cout << "unprint_accuracy: " << unprint_accuracy << endl;
	cout << "stain_accuracy: " << stain_accuracy << endl;
	cout << "hole_accuracy: " << hole_accuracy << endl;
	cout << "*****************************************************" << endl;
	return 0;
}

 

<think> 首先,用户的问题是关于查找使用C++训练YOLO模型的方法。用户指定了参考站内引用,这些引用提供了相关信息。我需要回顾这些引用: - 引用[1]: 讨论在C++中使用YOLO模型进行目标检测,使用OpenCV。[^1] - 引用[2]: 提到使用OpenCV DNN模块调用YOLO模型,适用于YOLOv3和YOLOv5。[^2] - 引用[3]: 描述C++调用yolo模型的方法,包括使用自定义C++代码。[^3] - 引用[4]: 分享使用C++训练yolo模型的经历的博客。[^4] - 引用[5]: 讨论YOLO模型训练中使用CUDA加速的性能。[^5] 用户的具体问题是:“我想查找使用C++训练yolo模型的方法 请问使用C++训练yolo模型的方法”。重点是训练YOLO模型,而不是推理。 从引用中: - 引用[4] 直接提到作者使用C++训练yolo模型的经历,涉及使用darknet框架。[^4] - 引用[5] 讨论了训练中的GPU加速,但没有指定语言。[^5] 其他引用是关于推理的(使用模型进行检测),而不是训练。 系统指令要求: - 所有行内数学表达式使用$...$格式(可能不适用于此问题)。 - 独立公式使用$$...$$格式(可能不适用)。 - LaTeX语法正确(确保数学表达式正确,但这里可能很少)。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 用户上次的问题和我的回答:用户之前的查询是关于使用C++训练YOLO模型的方法,我需要参考我的历史回答。但在这个对话中,这是第一次交互,所以没有历史回答。系统提示说“参考用户上一次的问题和你的回答”,但既然是开始,我应该基于当前查询。 构建回答: 1. **确认问题**:用户想了解使用C++训练YOLO模型的方法。 2. **提取关键信息**:从引用中,引用[4] 是最相关的,因为它描述使用darknet框架在C++训练YOLO模型。[^4] 提到作者编译了darknet文件和dll,并封装了工具脚本。 3. **其他引用**:引用[5] 强调了GPU加速的重要性,这是训练中的关键。[^5] 引用[1][2][3] 是关于推理的,但可能间接相关。 4. **核心方法**:训练YOLO模型通常使用框架如Darknet(原始框架),并且C++实现可以通过Darknet库。引用[4] 暗示使用darknet框架进行训练。 5. **步骤概述**: - 使用Darknet框架:Darknet是用C和CUDA编写的,原生支持C++接口或可直接编译。 - 步骤包括:安装Darknet,准备数据集,配置模型,编译和运行训练。 - 引用[4] 提到编译darknet文件和封装工具。[^4] - 引用[5] 强调使用CUDA加速训练。[^5] 6. **添加引用**:自然地添加引用标识在相关段落末尾。 7. **生成相关问题**:在回答末尾,生成相关问题,如优化训练、迁移学习等。 回答结构: - 引言:总结方法。 - 逐步解释:详细描述如何使用C++训练YOLO模型。 - 基于引用:整合信息。 - 结尾:相关问题。 确保使用中文。 </think> 以下是关于使用C++训练YOLO模型的方法的详细解答。基于您提供的引用信息(特别是引用[4]和[5],它们直接相关),我将逐步解释核心方法。YOLO(You Only Look Once)是一种流行的目标检测模型训练通常在框架如Darknet(原生支持C++)中进行,涉及数据集准备、模型配置、编译和GPU加速等步骤。训练过程在C++中相对复杂,因为它需要手动处理底层实现或依赖专用库,不像Python那样有高层API(如PyTorch或TensorFlow)。下面我将以清晰结构为您分解整个过程。 ### 步骤1: 准备环境与框架 要使用C++训练YOLO模型,首选框架是Darknet(YOLO作者的官方实现),因为它原生用C和CUDA编写,支持C++接口。您可以从GitHub克隆Darknet源码,并根据您的系统编译: - 安装依赖:确保安装了CUDA(用于GPU加速)、CuDNN(优化深度学习操作)和OpenCV(用于图像处理)。引用[5]强调,CUDA和CuDNN能显著加速训练,例如卷积运算速度可提升数十倍,这对于处理大型数据集至关重要[^5]。 - 编译Darknet:修改Darknet的Makefile文件(启用GPU和OpenCV支持),然后使用g++或CMake编译。编译后,您会得到可执行的darknet文件和相关的DLL(动态链接库)。引用[4]提到,作者封装了整个训练流程的工具脚本和依赖程序,包括编译好的darknet文件,这简化了后续步骤[^4]。 ### 步骤2: 准备数据集与配置文件 训练需要标注的数据集和模型配置: - **数据集准备**:收集图像数据,并使用工具(如LabelImg)标注边界框。数据集通常分为训练集和验证集。确保数据格式兼容Darknet(例如,YOLO格式的.txt文件和对应的图像)。 - **模型配置**:创建或修改.cfg文件(定义网络架构)。例如,对于YOLOv3,您需要指定卷积层、激活函数(如Leaky ReLU)和损失函数。引用[3]指出,自定义C++代码可以实现更灵活的配置,但这需要手动编写网络层,容易出错且耗时[^3]。建议初学者从预定义的.cfg文件开始(如YOLOv3-tiny或YOLOv4)。 ### 步骤3: 启动训练过程 使用编译好的darknet工具直接在C++中运行训练: - **命令行训练**:在终端执行命令,指定配置文件、权重初始文件(.weights)和数据集路径。例如: ```bash ./darknet detector train data/obj.data cfg/yolov3.cfg yolov3.weights -gpus 0 ``` 这里,`-gpus`参数启用GPU加速。引用[5]说明,CUDA并行计算能将训练速度提升数十倍,即使是大型模型(如YOLOv5)也能在几天内完成,而非数周[^5]。 - **自定义C++代码集成**:如果您需要更高级的控制(如在SLAM系统中集成训练),可以编写C++代码调用Darknet API。引用[4]描述了作者如何封装训练脚本和依赖程序,创建一个可复用的C++项目结构,这避免了Python转换的麻烦[^4]。但在实践中,这种方法仅适用于经验丰富的开发者,因为涉及底层操作(如导入权重文件和处理内存管理)。 ### 关键挑战与优化建议 - **GPU加速的重要性**:引用[5]强调,训练YOLO模型涉及大量卷积和反向传播计算,若不使用CUDA,训练时间会急剧增加(CPU训练可能慢100倍以上)。务必确保您的硬件支持NVIDIA GPU并正确配置CUDA环境[^5]。 - **常见问题**:C++训练缺乏像Ultralytics库那样的用户友好性(引用[1]对比了推理的简易性),因此您可能需要处理错误如权重文件不兼容(引用[4]提到从Python迁移时需要额外转换工具)[^1][^4]。 - **替代方法**:如果您优先考虑易用性,可以先用Python训练模型(如使用PyTorch),然后导出为.onnx或.weights文件,在C++中加载用于推理(引用[2]描述OpenCV DNN模块可用于此)[^2]。但对于纯C++训练,Darknet是主流选择。 ### 总结 总而言之, 使用C++训练YOLO模型的核心方法是:基于Darknet框架,通过编译源码、准备数据集和配置文件,并利用GPU加速执行训练命令。这适合需要高性能或嵌入式集成的场景(如自动驾驶或机器人SLAM),但开发门槛较高。建议参考Darknet官方文档和社区资源(如GitHub示例)来降低风险。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值