YOLOv4出来了,程序还是在darknet框架下,参照官网的配置过程记录一下整体的过程。和YOLOv3的配置过程基本一致,v3版本配置可参考前面写的博客。
https://blog.csdn.net/stjuliet/article/details/87731998
https://blog.csdn.net/stjuliet/article/details/87884976
Paper Yolo v4: https://arxiv.org/abs/2004.10934
预训练权重下载:
https://pan.baidu.com/s/1PDuhO9lsBPzMQi_zb3MXhw
提取码:n5ub
链接库文件下载:
https://download.csdn.net/download/stjuliet/12372543
step1 运行环境和前期准备
这些是自己电脑的配置,需要提前安装好,与官网略有不同,但是经过实际测试都能跑通。
1、Windows 10 系统
2、Visual Studio 2015 专业版
3、CUDA 9.0, cuDNN 7.5(cuda和cudnn版本、cuda和VS版本都需要对应)
step2 基础配置及测试
1、下载Darknet源代码和预训练权重yolov4.weights:
https://github.com/AlexeyAB/darknet
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
2、下载解压后,至darknet-master->build->darknet目录,找到darknet.vcxproj文件,右键用notepad打开,修改两处默认的"CUDA 10.0"为自己的版本:
2、打开darknet-master->build->darknet目录下的darknet.sln文件,设置x64 release模式,在对应属性管理器中配置OpenCV3.x和CUDA Device属性:
包含目录、库目录、附加依赖项:
算力:
3、右键项目生成Darknet:
原版配置过程可参考官网,根据自己的硬件环境进行调整:
4、生成成功后,在darknet-master->build->darknet->x64目录下可看到darknet.exe文件,并且将预训练权重文件放入该目录下。打开cmd,切换目录至darknet-master->build->darknet->x64,输入以下命令行运行即可打开摄像头进行目标检测,如果没有摄像头,可输入以下命令行对x64目录下已有的图片dog.jpg进行目标检测:
命令行:
有摄像头:
darknet.exe detector demo cfg/coco.data cfg/yolov4.cfg yolov4.weights -c 0
无摄像头测试图片:
darknet.exe detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights -i 0 -thresh 0.25 -ext_output dog.jpg
step3 编译动态链接库及测试
1、在darknet-master->build->darknet目录下找到yolo_cpp_dll.vcxproj和yolo_cpp_dll.sln文件,重复step2中的1、2、3步骤,此处有一点不同的是,在步骤2中,可将模式根据自己的需要设置为debug或release。
2、生成成功后,会在darknet-master->build->darknet->x64目录下看到以下文件:
3、找出所有需要用到的文件,以便后续测试:
a、动态链接库(均在darknet-master->build->darknet->x64目录下)
(1)yolo_cpp_dll.lib
(2)yolo_cpp_dll.dll
(3)pthreadGC2.dll
(4)pthreadVC2.dll
b、OpenCV库(取决于使用debug还是release模式)
(1)opencv_world343d.dll
(2)opencv_world343.dll
c、YOLO模型文件
(1)coco.names (在darknet-master->build->darknet->x64->data目录下,保存coco数据集类别)
(2)yolov4.cfg (在darknet-master->build->darknet->x64->cfg目录下,为yolov4模型配置文件)
(3)yolov4.weights (下载后放置在darknet-master->build->darknet->x64目录下,为yolov4模型预训练权重文件)
d、头文件
(1)yolo_v2_class.hpp (在darknet-master->include目录下,为调用动态链接库需要引用的yolo头文件)
4、在VS2015中新建一个空项目,在源文件中添加main.cpp,将上一步中所有文件全部放入与main.cpp同路径的文件夹中,并且放入一个目标检测的测试视频test.avi,在main.cpp中添加如下代码:
#include <iostream>
#ifdef _WIN32
#define OPENCV
#define GPU
#endif
#include "yolo_v2_class.hpp" //引用动态链接库中的头文件
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#pragma comment(lib, "opencv_world343d.lib") //引入OpenCV链接库
#pragma comment(lib, "yolo_cpp_dll.lib") //引入YOLO动态链接库
//以下两段代码来自yolo_console_dll.sln,有修改
void draw_boxes(cv::Mat mat_img, std::vector<bbox_t> result_vec, std::vector<std::string> obj_names)
{
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) {
cv::Scalar color = obj_id_to_color(i.obj_id);
cv::rectangle(mat_img, cv::Rect(i.x, i.y, i.w, i.h), color, 2);
if (obj_names.size() > i.obj_id) {
std::string obj_name = obj_names[i.obj_id];
cv::Size const text_size = getTextSize(obj_name, cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, 2, 0);
int const max_width = (text_size.width > i.w + 2) ? text_size.width : (i.w + 2);
cv::rectangle(mat_img, cv::Point2f(std::max((int)i.x - 1, 0), std::max((int)i.y - 30, 0)),
cv::Point2f(std::min((int)i.x + max_width, mat_img.cols-1), std::min((int)i.y, mat_img.rows-1)),
color, CV_FILLED, 8, 0);
putText(mat_img, obj_name, cv::Point2f(i.x, i.y - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(0, 0, 0), 2);
}
}
}
std::vector<std::string> objects_names_from_file(std::string const filename) {
std::ifstream file(filename);
std::vector<std::string> file_lines;
if (!file.is_open()) return file_lines;
for(std::string line; getline(file, line);) file_lines.push_back(line);
std::cout << "object names loaded \n";
return file_lines;
}
int main()
{
std::string names_file = "coco.names";
std::string cfg_file = "yolov4.cfg";
std::string weights_file = "yolov4.weights";
Detector detector(cfg_file, weights_file, 0); //初始化检测器
//std::vector<std::string> obj_names = objects_names_from_file(names_file); //调用获得分类对象名称
//或者使用以下四行代码也可实现读入分类对象文件
std::vector<std::string> obj_names;
std::ifstream ifs(names_file.c_str());
std::string line;
while (getline(ifs, line)) obj_names.push_back(line);
//测试是否成功读入分类对象文件
for (size_t i = 0; i < obj_names.size(); i++)
{
std::cout << obj_names[i] << std::endl;
}
cv::VideoCapture capture;
capture.open("test.avi");
if (!capture.isOpened())
{
printf("文件打开失败");
}
cv::Mat frame;
while (true)
{
capture >> frame;
std::vector<bbox_t> result_vec = detector.detect(frame);
draw_boxes(frame, result_vec, obj_names);
cv::namedWindow("Demo", CV_WINDOW_NORMAL);
cv::imshow("Demo", frame);
cv::waitKey(50);
}
return 0;
}
测试结果:
参考:
https://blog.csdn.net/JianqiuChen/article/details/105729633
https://blog.csdn.net/weixin_39954922/article/details/105785460?fps=1&locationNum=2
http://www.luyixian.cn/news_show_354767.aspx
以上是官网提供的旧版本配置方法,如果你安装的是CUDA 10.0及以上,可参考官网提供的最新方法,使用cmake编译配置。
Juliet 于 2020.4