YOLOV3 模型训练及模型部署(YOLO动态链接库的封装和调用)

YOLOV3 模型训练及模型部署(YOLO动态链接库的封装和调用)

一、 配置环境

  • windows10 + VS2017 community
  • cuda10.0.130_411.31
  • cunn-10.0-v7.6.5.32
  • opencv3.2

二、制作COCO数据集

参考链接:yolov3 训练自己的数据(coco数据制作篇)

1.准备工作

2.制作样本

(1)labelme制作样本,生成对应图像的json文件
(2)将生成的json文件和原始图像jpg,放入同一个文件夹中如:(D:\labelme-master\examples\instance_segmentation\data_annotated)
(3)下载labelme压缩包解压后,会产生D:\labelme-master\examples\文件夹里面有如下几个文件夹:

bbox_detection
classification
instance_segmentation 实例检测
primitives
semantic_segmentation 语义分割
tutorial
video_annotation

(4)进入instance_segmentation文件夹,instance_segmentation包含:

data_annotated 原始图像(将所需转换的原始图像放入该文件夹中,放入前清空文件夹)
data_dataset_coco 生成的coco数据集
data_dataset_voc 生成的voc数据集
labelme2coco.py
labelme2voc.py
labels.txt 标签类别

将labels.txt进行修改,本例是二分类front、behind两类别,加上背景类_background,还需要加上__ignore__类别,否则会报错,在labme2coco.py中有定义。即将labels.txt修改为:

__ignore__
_background_
front
behind

(5)打开终端并切换路径至instance_segmentation文件夹处,运行如下代码(运行之前先删除data_dataset_coco文件夹或者将其改名均可):

python labelme2coco.py data_annotated data_dataset_coco --labels labels.txt

(6)运行后,会将生成新的data_dataset_coco文件夹,此文件夹内包含JPEGImages文件夹(包含了原始图像)、Visulaization文件夹以及annotations.json。运行coco_txt.py将生成对象图片的txt图像信息保存至JPEGImages文件夹。

from __future__ import print_function
import os, sys, zipfile
import json


def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = box[0] + box[2] / 2.0
y = box[1] + box[3] / 2.0
w = box[2]
h = box[3]

x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)


json_file = 'annotations.json'  # # Object Instance 类型的标注

data = json.load(open(json_file, 'r'))

ana_txt_save_path = "data/coco/"  # 保存的路径
if not os.path.exists(ana_txt_save_path):
os.makedirs(ana_txt_save_path)

for img in data['images']:
# print(img["file_name"])
filename = img["file_name"]
img_width = img["width"]
img_height = img["height"]
# print(img["height"])
# print(img["width"])
img_id = img["id"]
ana_txt_name = filename.split(".")[0] + ".txt"  # 对应的txt名字,与jpg一致
print(ana_txt_name.replace('\\', '/'))
with open(os.path.join(ana_txt_save_path, ana_txt_name).replace('\\', '/'), 'w') as f_txt:
#   f_txt = open()
for ann in data['annotations']:
if ann['image_id'] == img_id:
# annotation.append(ann)
# print(ann["category_id"], ann["bbox"])
box = convert((img_width, img_height), ann["bbox"])
f_txt.write("%s %s %s %s %s\n" % (ann["category_id"], box[0], box[1], box[2], box[3]))
f_txt.close()

(7)使用train_val_txt.py生成train和val的绝对路径,该文件只是生成了train.txt,需要将train.txt中的txt改为jpg,因为针对的是image,这个是根据网上教程来的,其实是可以直接一步到位的。再在train.txt中选取部分作为val.txt的内容。新建labels文件夹,并将JPEGImages文件夹中的txt文件导入其中。到此coco数据集制作完毕

# -*- coding: utf-8 -*-
import time
import os
import shutil
import string


def readFilename(path, allfile):
filelist = os.listdir(path)

for filename in filelist:
    filepath = os.path.join(path, filename)
    if os.path.isdir(filepath):
        readFilename(filepath, allfile)
    else:
        allfile.append(filepath.replace('\\', '/'))
return allfile


if __name__ == '__main__':
    path1 = "data/coco/JPEGImages" #修改为自己的路径
    allfile1 = []
    allfile1 = readFilename(path1, allfile1)
	print("allfile1 = ", allfile1)
	allname1 = []
	txtpath = "data/coco/" + "train.txt" # 修改为自己的路径
	for name in allfile1:
	file_cls = name.split("/")[-1].split(".")[-1]
	if file_cls == 'txt':
	with open(txtpath, 'a+') as fp:
		fp.write("".join(name) + "\n")


三、darknet编译生成可执行exe文件并进行模型训练和预测

参考链接:Windows10+YOLOV3+VisualStudio2017最新版本超详细过程
项目地址

1.darknet.exe生成

(1)git项目,项目目录如下

(2)进入build>darknet文件中,主要有用的文件

如果出现找不到相应的dll文件可以将dll文件复制到×64文件夹中
(3)用VS2017打开darknet.sln文件,生成darknet.exe文件。
在生成操作之前需要配置darknet.sln,release ×64模式,如果是GPU模式还需要在darknet目录下修改Makefile中的前几行参数(GPU=1
CUDNN=1
CUDNN_HALF=1
OPENCV=1)。还需要修改darknet.vcxproj中的相关配置(CUDA版本修改一般就两处,VS版本修改如VS2017需要将对应版本修改为v141)

配置如下(具体还需要根据自己的位置进行配置):
常规:
windows sdk版本 10.0.19041.0(10.0.17763.0)
平台工具集 Visual Studio 2017(V141)

C++ —常规
KaTeX parse error: Undefined control sequence: \include at position 13: (OPENCV_DIR)\̲i̲n̲c̲l̲u̲d̲e̲;..\..\include;…(CudaToolkitIncludeDir);KaTeX parse error: Undefined control sequence: \include at position 8: (CUDNN)\̲i̲n̲c̲l̲u̲d̲e̲;(cudnn)\include

VC++ 目录
----可执行文件目录
D:\opencv\opencv\build\include;D:\opencv\opencv\build\include\opencv;D:\opencv\opencv\build\include\opencv2;$(ExecutablePath)

----包含目录
D:\opencv\opencv\build\include;D:\opencv\opencv\build\include\opencv;D:\opencv\opencv\build\include\opencv2;$(IncludePath)

----库目录
D:\opencv\opencv\build\x64\vc14\lib;$(LibraryPath)

链接器—常规—附加库目录
D:\opencv\opencv\build\x64\vc14\lib;$(CUDA_PATH)\lib$(PlatformName);KaTeX parse error: Undefined control sequence: \lib at position 8: (CUDNN)\̲l̲i̲b̲\x64;(cudnn)\lib\x64;…\3rdparty\pthreads\lib;opencv_world320.lib;%(AdditionalLibraryDirectories)

链接器—输入—附加依赖项

pthreadVC2.lib
cublas.lib
opencv_world320.lib
opencv_world320d.lib
curand.lib
cudart.lib

右键生成后会生成darknet.exe文件。

2.yolov3模型训练

(1).修改coco.data, coco.names为自身对应的类别和路径
(2).需要修改yolov3.cfg 一个是将test注释掉,train注释取消,将classes类别数设置正确,卷积核filter个数设置为3*(类别数+1+4)(只需要将部分filters对应个数修改即可)

darknet.exe detector train data/coco.data cfg/yolov3.cfg darknet53.conv.74 

这里的darknet53.conv.74网络需要另外下载
训练的结果保存在:backup//yolov3_final.weights

3.yolov3模型预测(如果只需要进行测试,需要下载yolov3.weights)

单张图像预测:

darknet.exe detector test data/coco.data cfg/yolov3.cfg backup/yolov3_final.weights test.jpg

视频预测:

darknet.exe detector demo data/coco.data cfg/yolov3.cfg backup/yolov3_final.weights  "test.mp4"

也可以使用如下命令:

yolo_console_dll.exe  data/coco.names cfg/yolov3.cfg backup/yolov3.weights  "test.mp4"

如果需要将测试视频结果保存可以在预测命令行后面添加

-out_filename output_filename.mp4

注:yolov3.cfg需要将训练部分给注释,留下test部分,同样在训练时需要将test部分注释掉(如下是测试用的yolov3.cfg,将Testing部分给注释解开,并将Training部分注释掉,训练时相反)

[net]
# Testing
batch=1
subdivisions=1
# Training
#batch=64
#subdivisions=16

四、yolov3模型部署

参考链接:Windows系统下YOLO动态链接库的封装和调用(Windows10+VS2015+OpenCV3.4.0+CUDA9.0+cuDNN7.0)
参考链接:YOLO动态链接库的编译和使用

1.编译动态链接库:
打开yolo_cpp_dll.sln进行配置后release ×64进行生成,生成成功后会生成yolo_cpp_dll.lib和yolo_cpp_dll.dll两个文件

2.调用动态链接库

    1、动态链接库(均在darknet-master\build\darknet\x64目录下)
    (1)yolo_cpp_dll.lib
    (2)yolo_cpp_dll.dll
    (3)pthreadGC2.dll
    (4)pthreadVC2.dll
    2、OpenCV库(取决于使用debug还是release模式)
    (1)opencv_world340d.dll
    (2)opencv_world340.dll
    3、YOLO模型文件(第一个文件在darknet-master\build\darknet\x64\data目录下,第二个文件在darknet-master\build\darknet\x64目录下,第三个文件需要自己下载,下载链接见前一篇文章)
    (1)coco.names
    (2)yolov3.cfg
    (3)yolov3.weights
    4、头文件
    (1)yolo_v2_class.hpp
    头文件包含了动态链接库中具体的类的定义,调用时需要引用,这个文件在darknet-master\build\darknet目录下的yolo_console_dll.sln中,将其复制到记事本保存成.hpp文件即可。

3.在VS2017中新建空项目添加yolov3.cpp,修改相应代码后进行生成,会生成yolov3.exe

#include <iostream>

#ifdef _WIN32
#define OPENCV
#define GPU
#endif

#include "yolo_v2_class.hpp"	// imported functions from DLL
#include <opencv2/opencv.hpp>	// C++
#include "opencv2/highgui/highgui.hpp"  

#pragma comment(lib, "opencv_world320.lib")//引入链接库

#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 current_det_fps = -1, int current_cap_fps = -1)
{
	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];
			if (i.track_id > 0) obj_name += " - " + std::to_string(i.track_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);
		}
	}
	if (current_det_fps >= 0 && current_cap_fps >= 0) {
		std::string fps_str = "FPS detection: " + std::to_string(current_det_fps) + "   FPS capture: " + std::to_string(current_cap_fps);
		putText(mat_img, fps_str, cv::Point2f(10, 20), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(50, 255, 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 = "yolov3.cfg";
	std::string  weights_file = "yolov3_final.weights";
	Detector detector(cfg_file, weights_file);//初始化检测器
	//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(0);
	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("test", CV_WINDOW_NORMAL);
		cv::imshow("test", frame);
		cv::waitKey(3);
	}
	return 0;
}

4.直接运行yolov3.exe会报错,找不到dll文件,需要将所有的文件导入yolov3.exe所在文件夹中
5.可以调整yolo_v2_class.hpp内的std::vector<bbox_t> detect(cv::Mat mat, float thresh = 0.5, bool use_mean = false)某些参数来选取合适的thresh
6.进行编译后直接运行yolov3.exe即可

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值