Windows系统下YOLOv4的配置及动态链接库封装调用(Windows10+VS2015+OpenCV3.x+CUDA9.0+cuDNN7.5)

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

猜你喜欢

转载自blog.csdn.net/stjuliet/article/details/105825056