yolo v4源码是开源的,在github上可以下载,并且有很详细的使用说明,本文只是针对windows下环境的安装进行介绍。
一、环境搭建
本节将进行windows下环境的搭建,我们将需要安装下面各个软件,并且需要注意安装的软件是有版本要求的:
Requirements for Windows, Linux and macOS
CMake >= 3.18: https://cmake.org/download/
Powershell (already installed on windows): https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell
CUDA >= 10.2: https://developer.nvidia.com/cuda-toolkit-archive (on Linux do Post-installation Actions)
OpenCV >= 2.4: use your preferred package manager (brew, apt), build from source using vcpkg or download from OpenCV official site (on Windows set system variable OpenCV_DIR = C:\opencv\build - where are the include and x64 folders image)
cuDNN >= 8.0.2 https://developer.nvidia.com/rdp/cudnn-archive (on Linux follow steps described here https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installlinux-tar , on Windows follow steps described here https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installwindows)
GPU with CC >= 3.0: https://en.wikipedia.org/wiki/CUDA#GPUs_supported
Visual Studio 2017 or 2019
1.1 安装opencv
官网下载地址:https://opencv.org/releases/,下载速度较慢。
国内镜像:https://www.raoyunsoft.com/opencv/
这里我直接下载最新的版本:opencv-4.5.5-vc14_vc15.exe。
下载完成之后,双击直接解压,这里我解压到E:\Program Files路径下:
安装完成后,我们打开E:\Program Files\opencv:
然后我们配置环境变量,【此电脑】->【属性】->【高级系统设置】->【环境变量】:
在系统变量中添加以下数据:
OpenCV_DIR E:\Program Files\opencv\build
再进入系统变量里的Path,添加如下数据:
E:\Program Files\opencv\build\x64\vc15\lib
E:\Program Files\opencv\build\x64\vc15\bin
1.2 安装Visual Studio
官网下载地址:https://visualstudio.microsoft.com/zh-hans/downloads/
安装的组件只需要“使用C++的桌面开发”,如果之前没有安装过,下载社区版本安装即可,这里我们选择Visual Studio 2017或者2019。
由于我之前已经安装了Visual Studio 2019所以就不重复安装了。
1.3 安装cuda
如果你使用的是NVIDIA显卡,cuda安装步骤参考windows和ubuntu下深度学习theano环境搭建 。
NVIDIA驱动版本与CUDA版本对应关系https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html。
1.4 安装cuDNN
如果你使用的是NVIDIA显卡,cuDNN安装步骤参考windows和ubuntu下深度学习theano环境搭建 。
官方安装指导手册:https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html.
1.5 安装cmake
cmake官方下载地址:https://cmake.org/download/,下载速度比较慢;
国内下载镜像:https://cmake.org/files/。
要求cmake>= 3.18,这里我下载cmake-3.23.0-rc4-windows-x86_64.msi。双击直接安装,这里我安装到E:\Program Files\CMake。
下载完成后安装得到以下文件:
进入bin文件夹,这个cmake-gui就是我们要用程序:
二、源码下载
2.1 git下载源码
git是代码版本管理工具,由于yolo v4源码是放在github仓库中的,我们需要从git上下载源码,下载方式有两种:
- 通过git 直接下载代码;
- 到github上手动下载源码;
如果使用git下载,我们需要安装git工具:https://www.git-scm.com/download/。
安装成功后,假设我想将源码下载到路径:G:\人工智能\深度学习\36.目标检测\官方库,进入该路径下,右键:
输入如下命令,开始下载源码:
git clone https://github.com/AlexeyAB/darknet.git
下载完成后,可以在当前路径看到:
2.2 环境变量配置
在系统变量Path中加入下载的darknet的位置:
G:\人工智能\深度学习\36.目标检测\官方库\darknet\build\darknet\x64
2.3 下载权重文件yolov4.weights
链接:https://pan.baidu.com/s/1koPg1amOlqIw5bLwv4Id_Q
提取码:1234
将下载后的yolov4.weights文件放在darknet文件夹下:
将下载后的yolov4.cfg文件放在darknet/cfg文件夹下。
三、编译程序
3.1 使用cmake配置源码
由于cmake不支持中文路径,因此我将下载的yolo v4源码剪切到G盘根路径下。同时记得修改系统环境变量。
打开CMake,配置:
- 源代码路径:G:/darknet;
- 构建目标文件路径:G:/darknet;
点击左下角Configure,然后第一项选择我们安装的 Visual Studio 2019,第二项平台选择x64:
3.2 关闭CUDA
如果没有GPU,第一次编译的时候会出现如下错误:
cuda找不到,只好取消勾选不用GPU:
再次点击Configure,配置成功,会输出如下信息:
Darknet_VERSION: 0.2.5.4
vcpkg not found, toolchain not defined, using integrated libs on win32
Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.18363.
Looking for pthread.h
Looking for pthread.h - not found
Found Threads: TRUE
Found PThreads4W: G:/darknet/3rdparty/pthreads/lib/pthreadVC2.lib
PThreads4W_DLL_DIR: G:/darknet/3rdparty/pthreads/include/../bin
PThreads4W_DEBUG_DLL_DIR: G:/darknet/3rdparty/pthreads/include/../debug/bin
OpenCV ARCH: x64
OpenCV RUNTIME: vc15
OpenCV STATIC: OFF
Found OpenCV: E:/Program Files/opencv/build (found version "4.5.5")
Found OpenCV 4.5.5 in E:/Program Files/opencv/build/x64/vc15/lib
You might need to add E:\Program Files\opencv\build\x64\vc15\bin to your PATH to be able to run your applications.
Found Stb: G:/darknet/3rdparty/stb/include
Found OpenMP_C: -openmp (found version "2.0")
Found OpenMP_CXX: -openmp (found version "2.0")
Found OpenMP: TRUE (found version "2.0")
ZED SDK not enabled, since it requires CUDA
Configuring done
需要注意的是如果没有GPU的话,图片可以识别分类没问题,但是视频识别没有用GPU就特别慢,像播放幻灯片一样。
3.3 编译代码
点击生成和打开项目:
之后会自动打开vs,选择x64和Release,点击生成,这时生成文件即可:
将会输出如下编译信息:
已启动生成…
1>------ 已启动生成: 项目: ZERO_CHECK, 配置: Debug x64 ------
1>Checking Build System
2>------ 已启动生成: 项目: dark, 配置: Debug x64 ------
3>------ 已启动生成: 项目: darknet, 配置: Debug x64 ------
2>Building Custom Rule G:/darknet/CMakeLists.txt
2>用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30037 版
2>版权所有(C) Microsoft Corporation。保留所有权利。
2>cl /c /IG:\darknet\include /IG:\darknet\src /IG:\darknet\3rdparty\stb\include /I"E:\Program Files\opencv\build\include" /IG:\darknet\3rdparty\pthreads\include /Zi /W1 /WX- /diagnostics:column /Od /Ob0 /D _WINDLL /D _MBCS /D WIN32 /D _WINDOWS /D LIB_EXPORTS=1 /D USE_CMAKE_LIBS /D OPENCV /D _CRT_RAND_S /D NOMINMAX /D _USE_MATH_DEFINES /D _CRT_SECURE_NO_WARNINGS /D _TIMESPEC_DEFINED /D "CMAKE_INTDIR=\"Debug\"" /D dark_EXPORTS /Gm- /EHsc /RTC1 /MDd /GS /fp:fast /Zc:wchar_t /Zc:forScope /Zc:inline /GR /openmp /Fo"dark.dir\Debug\\" /Fd"dark.dir\Debug\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W1 /Gd /TP /wd4013 /wd4018 /wd4028 /wd4047 /wd4068 /wd4090 /wd4101 /wd4113 /wd4133 /wd4190 /wd4244 /wd4267 /wd4305 /wd4477 /wd4996 /wd4819 /errorReport:prompt G:\darknet\src\yolo_v2_class.cpp G:\darknet\src\http_stream.cpp G:\darknet\src\image_opencv.cpp
2>yolo_v2_class.cpp
3>Building Custom Rule G:/darknet/CMakeLists.txt
3>用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30037 版
3>版权所有(C) Microsoft Corporation。保留所有权利。
3>cl /c /IG:\darknet\include /IG:\darknet\src /IG:\darknet\3rdparty\stb\include /I"E:\Program Files\opencv\build\include" /IG:\darknet\3rdparty\pthreads\include /Zi /W1 /WX- /diagnostics:column /Od /Ob0 /D _MBCS /D WIN32 /D _WINDOWS /D USE_CMAKE_LIBS /D OPENCV /D _CRT_RAND_S /D NOMINMAX /D _USE_MATH_DEFINES /D _TIMESPEC_DEFINED /D "CMAKE_INTDIR=\"Debug\"" /Gm- /EHsc /RTC1 /MDd /GS /fp:fast /Zc:wchar_t /Zc:forScope /Zc:inline /GR /openmp /Fo"darknet.dir\Debug\\" /Fd"darknet.dir\Debug\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W1 /Gd /TC /wd4013 /wd4018 /wd4028 /wd4047 /wd4068 /wd4090 /wd4101 /wd4113 /wd4133 /wd4190 /wd4244 /wd4267 /wd4305 /wd4477 /wd4996 /wd4819 /errorReport:prompt G:\darknet\src\darknet.c G:\darknet\src\activation_layer.c G:\darknet\src\activations.c G:\darknet\src\art.c G:\darknet\src\avgpool_layer.c G:\darknet\src\batchnorm_layer.c G:\darknet\src\blas.c G:\darknet\src\box.c G:\darknet\src\captcha.c G:\darknet\src\cifar.c G:\darknet\src\classifier.c G:\darknet\src\coco.c G:\darknet\src\col2im.c G:\darknet\src\compare.c G:\darknet\src\connected_layer.c G:\darknet\src\conv_lstm_layer.c G:\darknet\src\convolutional_layer.c G:\darknet\src\cost_layer.c G:\darknet\src\cpu_gemm.c G:\darknet\src\crnn_layer.c G:\darknet\src\crop_layer.c G:\darknet\src\dark_cuda.c G:\darknet\src\data.c G:\darknet\src\deconvolutional_layer.c G:\darknet\src\demo.c G:\darknet\src\detection_layer.c G:\darknet\src\detector.c G:\darknet\src\dice.c G:\darknet\src\dropout_layer.c G:\darknet\src\gaussian_yolo_layer.c G:\darknet\src\gemm.c G:\darknet\src\getopt.c G:\darknet\src\gettimeofday.c G:\darknet\src\go.c G:\darknet\src\gru_layer.c G:\darknet\src\im2col.c G:\darknet\src\image.c G:\darknet\src\layer.c G:\darknet\src\list.c G:\darknet\src\local_layer.c G:\darknet\src\lstm_layer.c G:\darknet\src\matrix.c G:\darknet\src\maxpool_layer.c G:\darknet\src\network.c G:\darknet\src\nightmare.c G:\darknet\src\normalization_layer.c G:\darknet\src\option_list.c G:\darknet\src\parser.c G:\darknet\src\region_layer.c G:\darknet\src\reorg_layer.c G:\darknet\src\reorg_old_layer.c G:\darknet\src\representation_layer.c G:\darknet\src\rnn.c G:\darknet\src\rnn_layer.c G:\darknet\src\rnn_vid.c G:\darknet\src\route_layer.c G:\darknet\src\sam_layer.c G:\darknet\src\scale_channels_layer.c G:\darknet\src\shortcut_layer.c G:\darknet\src\softmax_layer.c G:\darknet\src\super.c G:\darknet\src\swag.c G:\darknet\src\tag.c G:\darknet\src\tree.c G:\darknet\src\upsample_layer.c G:\darknet\src\utils.c G:\darknet\src\voxel.c G:\darknet\src\writing.c G:\darknet\src\yolo.c G:\darknet\src\yolo_layer.c
3>darknet.c
3>activation_layer.c
3>activations.c
3>art.c
3>avgpool_layer.c
2>http_stream.cpp
3>batchnorm_layer.c
3>blas.c
3>box.c
3>captcha.c
3>cifar.c
3>classifier.c
3>coco.c
3>col2im.c
3>compare.c
3>connected_layer.c
3>conv_lstm_layer.c
3>convolutional_layer.c
3>cost_layer.c
3>cpu_gemm.c
3>crnn_layer.c
3>正在生成代码...
3>正在编译...
3>crop_layer.c
3>dark_cuda.c
3>data.c
3>deconvolutional_layer.c
3>demo.c
3>detection_layer.c
3>detector.c
3>dice.c
3>dropout_layer.c
3>gaussian_yolo_layer.c
3>gemm.c
3>getopt.c
3>gettimeofday.c
3>go.c
3>gru_layer.c
3>im2col.c
3>image.c
3>layer.c
3>list.c
3>local_layer.c
3>正在生成代码...
3>正在编译...
3>lstm_layer.c
3>matrix.c
3>maxpool_layer.c
3>network.c
3>nightmare.c
3>normalization_layer.c
2>image_opencv.cpp
3>option_list.c
3>parser.c
3>region_layer.c
3>reorg_layer.c
3>reorg_old_layer.c
3>representation_layer.c
3>rnn.c
3>rnn_layer.c
3>rnn_vid.c
3>route_layer.c
3>sam_layer.c
3>scale_channels_layer.c
3>shortcut_layer.c
3>softmax_layer.c
3>正在生成代码...
3>正在编译...
3>super.c
3>swag.c
3>tag.c
3>tree.c
3>upsample_layer.c
3>utils.c
3>voxel.c
3>writing.c
3>yolo.c
3>yolo_layer.c
2>正在生成代码...
3>正在生成代码...
3>用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30037 版
3>版权所有(C) Microsoft Corporation。保留所有权利。
3>cl /c /IG:\darknet\include /IG:\darknet\src /IG:\darknet\3rdparty\stb\include /I"E:\Program Files\opencv\build\include" /IG:\darknet\3rdparty\pthreads\include /Zi /W1 /WX- /diagnostics:column /Od /Ob0 /D _MBCS /D WIN32 /D _WINDOWS /D USE_CMAKE_LIBS /D OPENCV /D _CRT_RAND_S /D NOMINMAX /D _USE_MATH_DEFINES /D _TIMESPEC_DEFINED /D "CMAKE_INTDIR=\"Debug\"" /Gm- /EHsc /RTC1 /MDd /GS /fp:fast /Zc:wchar_t /Zc:forScope /Zc:inline /GR /openmp /Fo"darknet.dir\Debug\\" /Fd"darknet.dir\Debug\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W1 /Gd /TP /wd4013 /wd4018 /wd4028 /wd4047 /wd4068 /wd4090 /wd4101 /wd4113 /wd4133 /wd4190 /wd4244 /wd4267 /wd4305 /wd4477 /wd4996 /wd4819 /errorReport:prompt G:\darknet\src\http_stream.cpp G:\darknet\src\image_opencv.cpp
3>http_stream.cpp
2>用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30037 版
2>版权所有(C) Microsoft Corporation。保留所有权利。
2>cl /c /IG:\darknet\include /IG:\darknet\src /IG:\darknet\3rdparty\stb\include /I"E:\Program Files\opencv\build\include" /IG:\darknet\3rdparty\pthreads\include /Zi /W1 /WX- /diagnostics:column /Od /Ob0 /D _WINDLL /D _MBCS /D WIN32 /D _WINDOWS /D LIB_EXPORTS=1 /D USE_CMAKE_LIBS /D OPENCV /D _CRT_RAND_S /D NOMINMAX /D _USE_MATH_DEFINES /D _CRT_SECURE_NO_WARNINGS /D _TIMESPEC_DEFINED /D "CMAKE_INTDIR=\"Debug\"" /D dark_EXPORTS /Gm- /EHsc /RTC1 /MDd /GS /fp:fast /Zc:wchar_t /Zc:forScope /Zc:inline /GR /openmp /Fo"dark.dir\Debug\\" /Fd"dark.dir\Debug\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W1 /Gd /TC /wd4013 /wd4018 /wd4028 /wd4047 /wd4068 /wd4090 /wd4101 /wd4113 /wd4133 /wd4190 /wd4244 /wd4267 /wd4305 /wd4477 /wd4996 /wd4819 /errorReport:prompt G:\darknet\src\activation_layer.c G:\darknet\src\activations.c G:\darknet\src\art.c G:\darknet\src\avgpool_layer.c G:\darknet\src\batchnorm_layer.c G:\darknet\src\blas.c G:\darknet\src\box.c G:\darknet\src\captcha.c G:\darknet\src\cifar.c G:\darknet\src\classifier.c G:\darknet\src\coco.c G:\darknet\src\col2im.c G:\darknet\src\compare.c G:\darknet\src\connected_layer.c G:\darknet\src\conv_lstm_layer.c G:\darknet\src\convolutional_layer.c G:\darknet\src\cost_layer.c G:\darknet\src\cpu_gemm.c G:\darknet\src\crnn_layer.c G:\darknet\src\crop_layer.c G:\darknet\src\dark_cuda.c G:\darknet\src\data.c G:\darknet\src\deconvolutional_layer.c G:\darknet\src\demo.c G:\darknet\src\detection_layer.c G:\darknet\src\detector.c G:\darknet\src\dice.c G:\darknet\src\dropout_layer.c G:\darknet\src\gaussian_yolo_layer.c G:\darknet\src\gemm.c G:\darknet\src\getopt.c G:\darknet\src\gettimeofday.c G:\darknet\src\go.c G:\darknet\src\gru_layer.c G:\darknet\src\im2col.c G:\darknet\src\image.c G:\darknet\src\layer.c G:\darknet\src\list.c G:\darknet\src\local_layer.c G:\darknet\src\lstm_layer.c G:\darknet\src\matrix.c G:\darknet\src\maxpool_layer.c G:\darknet\src\network.c G:\darknet\src\nightmare.c G:\darknet\src\normalization_layer.c G:\darknet\src\option_list.c G:\darknet\src\parser.c G:\darknet\src\region_layer.c G:\darknet\src\reorg_layer.c G:\darknet\src\reorg_old_layer.c G:\darknet\src\representation_layer.c G:\darknet\src\rnn.c G:\darknet\src\rnn_layer.c G:\darknet\src\rnn_vid.c G:\darknet\src\route_layer.c G:\darknet\src\sam_layer.c G:\darknet\src\scale_channels_layer.c G:\darknet\src\shortcut_layer.c G:\darknet\src\softmax_layer.c G:\darknet\src\super.c G:\darknet\src\swag.c G:\darknet\src\tag.c G:\darknet\src\tree.c G:\darknet\src\upsample_layer.c G:\darknet\src\utils.c G:\darknet\src\voxel.c G:\darknet\src\writing.c G:\darknet\src\yolo.c G:\darknet\src\yolo_layer.c
2>activation_layer.c
2>activations.c
2>art.c
2>avgpool_layer.c
2>batchnorm_layer.c
2>blas.c
2>box.c
2>captcha.c
2>cifar.c
2>classifier.c
2>coco.c
2>col2im.c
2>compare.c
2>connected_layer.c
2>conv_lstm_layer.c
2>convolutional_layer.c
2>cost_layer.c
2>cpu_gemm.c
2>crnn_layer.c
2>crop_layer.c
2>正在生成代码...
2>正在编译...
2>dark_cuda.c
2>data.c
2>deconvolutional_layer.c
2>demo.c
2>detection_layer.c
2>detector.c
2>dice.c
2>dropout_layer.c
2>gaussian_yolo_layer.c
2>gemm.c
2>getopt.c
2>gettimeofday.c
2>go.c
2>gru_layer.c
2>im2col.c
2>image.c
2>layer.c
3>image_opencv.cpp
2>list.c
2>local_layer.c
2>lstm_layer.c
2>正在生成代码...
2>正在编译...
2>matrix.c
2>maxpool_layer.c
2>network.c
2>nightmare.c
2>normalization_layer.c
2>option_list.c
2>parser.c
2>region_layer.c
2>reorg_layer.c
2>reorg_old_layer.c
2>representation_layer.c
2>rnn.c
2>rnn_layer.c
2>rnn_vid.c
2>route_layer.c
2>sam_layer.c
2>scale_channels_layer.c
2>shortcut_layer.c
2>softmax_layer.c
2>super.c
2>正在生成代码...
2>正在编译...
2>swag.c
3>正在生成代码...
2>tag.c
2>tree.c
2>upsample_layer.c
2>utils.c
2>voxel.c
2>writing.c
2>yolo.c
2>yolo_layer.c
2>正在生成代码...
3>darknet.vcxproj -> G:\darknet\Debug\darknet.exe
2> 正在创建库 G:/darknet/Debug/darknetd.lib 和对象 G:/darknet/Debug/darknetd.exp
2>dark.vcxproj -> G:\darknet\Debug\darknetd.dll
4>------ 已启动生成: 项目: uselib, 配置: Debug x64 ------
4>Building Custom Rule G:/darknet/CMakeLists.txt
4>用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.29.30037 版
4>版权所有(C) Microsoft Corporation。保留所有权利。
4>cl /c /IG:\darknet\include /IG:\darknet\src /IG:\darknet\3rdparty\stb\include /I"E:\Program Files\opencv\build\include" /IG:\darknet\3rdparty\pthreads\include /Zi /W1 /WX- /diagnostics:column /Od /Ob0 /D _MBCS /D WIN32 /D _WINDOWS /D USE_CMAKE_LIBS /D _CRT_RAND_S /D NOMINMAX /D _USE_MATH_DEFINES /D OPENCV /D _CRT_SECURE_NO_WARNINGS /D "CMAKE_INTDIR=\"Debug\"" /Gm- /EHsc /RTC1 /MDd /GS /fp:fast /Zc:wchar_t /Zc:forScope /Zc:inline /GR /openmp /Fo"uselib.dir\Debug\\" /Fd"uselib.dir\Debug\vc142.pdb" /external:env:EXTERNAL_INCLUDE /external:W1 /Gd /TP /wd4013 /wd4018 /wd4028 /wd4047 /wd4068 /wd4090 /wd4101 /wd4113 /wd4133 /wd4190 /wd4244 /wd4267 /wd4305 /wd4477 /wd4996 /wd4819 /errorReport:prompt G:\darknet\src\yolo_console_dll.cpp
4>yolo_console_dll.cpp
4>uselib.vcxproj -> G:\darknet\Debug\uselib.exe
5>------ 已启动生成: 项目: ALL_BUILD, 配置: Debug x64 ------
5>Building Custom Rule G:/darknet/CMakeLists.txt
6>------ 已启动生成: 项目: INSTALL, 配置: Debug x64 ------
6>-- Install configuration: "Debug"
6>-- Installing: G:/darknet/darknetd.lib
6>-- Installing: G:/darknet/darknetd.dll
6>-- Installing: G:/darknet/include/darknet/darknet.h
6>-- Installing: G:/darknet/include/darknet/yolo_v2_class.hpp
6>-- Installing: G:/darknet/uselib.exe
6>-- Installing: G:/darknet/darknet.exe
6>-- Installing: G:/darknet/share/darknet/DarknetTargets.cmake
6>-- Installing: G:/darknet/share/darknet/DarknetTargets-debug.cmake
6>-- Installing: G:/darknet/share/darknet/DarknetConfig.cmake
6>-- Installing: G:/darknet/share/darknet/DarknetConfigVersion.cmake
========== 生成: 成功 6 个,失败 0 个,最新 0 个,跳过 0 个 ==========
View Code
这时我们的目录下会出现这个文件:
四、运行程序
4.1 识别图片
在G:\darknet\data路径下有一个dog.jpg文件:
在G:\darknet路径下,打开cmd控制台运行如下命令:
./darknet.exe detect cfg\yolov4.cfg yolov4.weights data\dog.jpg
输出如下:
4.2 摄像头识别
打开电脑摄像头识别监控画面(需要提前开启摄像头权限):
./darknet.exe detector demo cfg\coco.data cfg\yolov4.cfg yolov4.weights
如果没有使用GPU的话,这里识别会分非常卡顿。
4.3 视频识别
识别视频(视频放到data目录下):
./darknet.exe detector demo cfg\coco.data cfg\yolov4.cfg yolov4.weights .\data\xxx.mp4
五、训练VOC 2012数据集
5.1 数据集下载
这里以下载Pascal VOC 2012数据集为例,VOC 2012是VOC2007数据集的升级版,每张图片都有标注,标注的物体包括人、动物(如猫、狗、鸟等)、交通工具(如车、船飞机等)、家具(如椅子、桌子、沙发等)在内的20个类别。
首先下载数据集,下载地址为:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar。
下载完成后,加压到G:/darknet下,得到一个解压后,得到一个VOCdevkit文件夹:
JPEGImages文件夹中包含了PASCAL VOC提供的所有的就jpg图片,共计17125张,包括了训练和测试图片。
这些图像都以“年份_编号.jpg”格式命名。
图片的像素尺寸大小不一,但是横向图的尺寸大约在500*375左右,纵向图的尺寸大约在375*500左右,长宽均不会超过512。
对于每一张图像,都在Annotations文件夹中存放有对应的xml文件。保存着物体框的标注,包括图片文件名,图片大小,图片边界框等信息。
以2007_000027.xml为例:
<annotation>
#数据所在的文件夹名
<folder>VOC2012</folder>
#图片名称
<filename>2007_000027.jpg</filename>
<source>
<database>The VOC2007 Database</database>
<annotation>PASCAL VOC2007</annotation>
<image>flickr</image>
</source>
#图片的宽和高
<size>
<width>486</width>
<height>500</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
#类别名
<name>person</name>
#物体的姿势
<pose>Unspecified</pose>
#物体是否被部分遮挡
<truncated>0</truncated>
##是否为难以辨识的物体, 主要指要结合背景才能判断出类别的物体。虽有标注, 但一般忽略这类物体 跳过难以识别的?
<difficult>0</difficult>
#边界框
<bndbox>
<xmin>174</xmin>
<ymin>101</ymin>
<xmax>349</xmax>
<ymax>351</ymax>
</bndbox>
#下面的数据是人体各个部位边界框
<part>
<name>head</name>
<bndbox>
<xmin>169</xmin>
<ymin>104</ymin>
<xmax>209</xmax>
<ymax>146</ymax>
</bndbox>
</part>
<part>
<name>hand</name>
<bndbox>
<xmin>278</xmin>
<ymin>210</ymin>
<xmax>297</xmax>
<ymax>233</ymax>
</bndbox>
</part>
<part>
<name>foot</name>
<bndbox>
<xmin>273</xmin>
<ymin>333</ymin>
<xmax>297</xmax>
<ymax>354</ymax>
</bndbox>
</part>
<part>
<name>foot</name>
<bndbox>
<xmin>319</xmin>
<ymin>307</ymin>
<xmax>340</xmax>
<ymax>326</ymax>
</bndbox>
</part>
</object>
</annotation>
View Code
ImageSets文件夹包括Action Layout Main Segmentation四部分:
Action存放的是人的动作(running、jumping等等);
Layout存放人体部位数据(人的head、hand、feet等等);
Main存放的是图像物体识别数据,总共分为20类;
Segmentation:存放的是可用于语义分割的数据:
SegmentationClass保存了分割后的标签图(2913张png图片),标注出了每一个像素属于哪一个类别:
SegmentationObject保存了分割后的标签图(759张png图片),标注出了每一个像素属于哪一个具体的物体:
其中./scripts/voc_label.py代码可以给训练集/验证集/测试集数据集打标签,将voc_label.py放到VOCdevkit文件夹下:
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]
def convert(size, box): # box由实际像素(xmin,xmax,ymin,ymax),转换成归一化的(w,y,w,h)
dw = 1./(size[0]) # 1/width 单位宽像素长度
dh = 1./(size[1]) # 1/heigh 单位高像素长度
x = (box[0] + box[1])/2.0 - 1 #(xmin + xmax)/2-1
y = (box[2] + box[3])/2.0 - 1 #(ymin + ymax)/2-1
w = box[1] - box[0] # box宽所占像素数
h = box[3] - box[2] # box高所占像素数
x = x*dw # 即归一化后的中心坐标x
w = w*dw # 即归一化后的宽
y = y*dh # 即归一化后中心坐标y
h = h*dh # 即归一化后的高
return (x,y,w,h)
def convert_annotation(year, image_id): # 将xml标签文件数据,进行处理后,并写入txt文件中
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
tree=ET.parse(in_file) # 解析xml
root = tree.getroot() # 获取根节点
size = root.find('size') # 获取图片大小 width、height、depth
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'): # 获取图片标注信息
difficult = obj.find('difficult').text # 是否是难以识别的 如果是,跳过
cls = obj.find('name').text # 类别名
if cls not in classes or int(difficult)==1:
continue
cls_id = classes.index(cls) # 类别所对应的id
xmlbox = obj.find('bndbox') # 边界框
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b) # 转换成归一化之后的(x,y,w,h)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') # 写入 class_id x y w h
wd = getcwd() # 获取当前工作路径
for year, image_set in sets:
if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)): # 创建标签文件夹,
os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split() #获取所有的用于训练的图片文件名列表
list_file = open('%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
convert_annotation(year, image_id) #xml标注文件转为txt类型标准文件
list_file.close()
os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt")
os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")
大概介绍一下这段程序:
- 读取VOCdevkit\VOC2012\ImageSets\Main\train.txt,获取用来训练的图片文件的文件名列表 ,一共5717个;
- 遍历这5717个文件名,向./2012_train.txt文件中写入文件全路径;同时获取每个文件的xml标注信息,并进行处理,获取目标类别,以及归一化后的边界框信息,写入lebal下的文件名.text文件中;
- 读取VOCdevkit\VOC2012\ImageSets\Main\val.txt,获取用来验证的图片文件的文件名列表 ,一共5823个;
- 遍历这5823个文件名,向./2012_val.txt文件中写入文件全路径;同时获取每个文件的xml标注信息,并进行处理,获取目标类别,以及归一化后的边界框信息,写入lebal下的文件名.text文件中;
我们需要修改代码sets:
sets=[('2012', 'train'), ('2012', 'val')]
由于我们是windows系统,因此屏蔽掉最后os.system相关代码。
我们运行这个程序,需要注意的是这个文件不可以直接运行,因为如果直接运行那么当前程序运行的目录就是当前文件,此时会找不到VOCdevkit文件夹。因此我们需要在Terminal中运行:
python ./VOCdevkit/voc_label.py
运行完后,在G:\darknet\VOCdevkit\VOC2012\labels下生成11540个文件:
同时在G:\darknet下生成这两个文件:
将这两个文件拷贝到G:\darknet\VOCdevkit:
并将名字修改为train.txt、val.txt。
5. 2 配置文件
在G:\darknet\VOCdevkit下创建data文件夹,复制G:\darknet\cfg文件夹下的voc.data到data文件夹下,并根据实际情况修改文件内容(路径中使用/,不要使用\):
classes= 20
train = G:/darknet/VOCdevkit/train.txt
valid = G:/darknet/VOCdevkit/val.txt
names = G:/darknet/VOCdevkit/data/voc.names
backup = G:/darknet/VOCdevkit/backup
复制G:\darknet\data目录下的voc.name到data文件夹:
aeroplane
bicycle
bird
boat
bottle
bus
car
cat
chair
cow
diningtable
dog
horse
motorbike
person
pottedplant
sheep
sofa
train
tvmonitor
这里存放的是每个标签的名字。
在G:\darknet\VOCdevkit下创建cfg文件夹,从G:\darknet\cfg下复制一个配置文件作为我们的配置文件,这里我选择复制yolov4.cfg到G:\darknet\VOCdevkit\cfg文件夹下,yolov4.cfg里面存放的是网络参数以及网络结构信息,并进行修改:
- 将classes=80 改为你的类别数20(一共三处);
- 改正[filters=255] 为 filters=(classes + 5)x3 =75(位置为查找yolo,每个yolo前的[convolutional]里,注意只修改最接近yolo的那个filters需要修改,一共应该有三处);
- 修改max_batches=classes*2000,也就是40000;
- 修改steps为80% 到 90% 的max_batches值 比如max_batches=40000,则steps=32000,36000;
5.3 训练
shift+右键,G:\darknet路径下打开 PowerShell 窗口。
当没有预训练模型,执行以下代码:
./darknet.exe detector train VOCdevkit/data/voc.data VOCdevkit/cfg/yolov4.cfg
如果有yolov4预训练权重yolov4.conv.137:下载路径链接:https://pan.baidu.com/s/1N-3h5IuVrwdxHOOA69mg2g,提取码:991m;下载完成复制到G:\darknet:
./darknet.exe detector train VOCdevkit/data/voc.data VOCdevkit/cfg/yolov4.cfg yolov4.conv.137
软件开始执行训练命令,正常会显示Loss表界面和一个不断刷新数据的命令行界面; 这里由于我的电脑没有GPU跑的非常慢,这里我就不演示了。
如果有问题,几分钟内就会报错,一般的错误主要是文件找不到或者内存不够等,请仔细检查以上步骤的所有文件名和路径,如果是内存不够,可以修改cfg配置文件中前几行中的batch(改小,比如32)和subdivisions(改大,比如32)的数字后,再试。
跑完是这样的,每训练 100次会自动保存一次,训练生成的权重文件在G:\darknet\VOCdevkit\backup目录下,名字为yolov4-tiny_last.weights:
5.4 预测
训练结束了,现在可以测试训练结果了,复制一份刚才训练的 yolov4-tiny_last.weights保存到VOCdevkit/weights路径下。
复制yolov4.cfg文件并且重命名为yolov4-test.cfg,修改其中的参数:
batch=1
subdivisions=1
运行以下代码测试:
./darknet.exe detector test VOCdevkit/data/voc.data VOCdevkit/cfg/yolov4-test.cfg VOCdevkit/weights/yolo.voc.weights xxx.jpg
六、训练自己的数据
这里以从网上找到的磁块的缺陷裂缝检测的项目为例,具体数据可以参考博客提供软件环境和工业数据集下载]工业瑕疵缺陷检测实战:Windows下基于YOLOv4和OpenCV4深度学习训练自己的数据集和前端软件,效果意外的好。样本数据大致如下图:
6.1 labelImg工具安装
首先我们要去下载标准工具,labelImg下载链接:https://github.com/tzutalin/lab。labelImg工具适用于图像检测的数据集制作,可以直接生成yolo的标注格式。
我们在我们G:/darknet路径下,使用git下载源码:
git clone https://github.com/tzutalin/labelImg.git
下载完成后,会在当前路径看到:
使用开发工具spyder++或者pycharm打开这个项目,要求python版本3.0+:
安装必要的包,在Terminal下执行如下代码,安装比较慢耐心等待:
pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple/
pyrcc5 -o libs/resources.py resources.qrc
然后在Terminal,运行如下命令,打开labelImg程序(或者直接运行labelImg.py里面的main函数):
python labelImg.py
程序界面如下:
如果想将python代码打包生成exe可执行文件,执行如下命令即可:
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple/
pyinstaller --hidden-import=pyqt5 --hidden-import=lxml -F -n "labelImg" -c labelImg.py -p ./libs -p ./
此时会在dist路径下生成exe文件:
6.2 数据集文件配置
我们在G:\darknet路径下创建一个文件夹Magnet,文件夹格式如下:
Magnet
Annotations #放入所有的xml文件
ImageSets
Main #放入train.txt,val.txt文件
JPEGImages #放入所有的训练图片文件
labels #放入所有的txt文件,会自动生成此文件夹
TESTImages #放入所有的测试图片文件
cfg #yolov4网络配置
data #训练集数据信息
然后把部分样本图片放到G:\darknet\Magnet\JPEGImages路径下,这里我选取了一共116张用于训练和验证图片。
下面我们在G:\darknet\Magnet下创建一个python文件prepare.py,
"""
预处理工作
@author zy
@since 2022/03/26
"""
import os
def generate_train_and_val_txt():
'''
遍历JPEGImages路径下所有文件名,并按照4:1,将数据分成训练集和验证集
并把全路径写入train.txt,val.txt
:return:
'''
# 获取当前工作路径
pwd = os.getcwd()
# 训练集和验证集图片所在路径
source_folder = os.path.join(pwd, 'JPEGImages')
# train.txt文件路径
train_text = os.path.join(pwd, 'ImageSets/Main/train.txt')
# val.txt文件路径
val_test = os.path.join(pwd, 'ImageSets/Main/val.txt')
# 判断文件是否存在,存在删除
if os.path.exists(train_text):
os.remove(train_text)
# 判断文件是否存在,存在删除
if os.path.exists(val_test):
os.remove(val_test)
with open(train_text, 'a') as train_file:
with open(val_test, 'a') as val_file:
count = 0
# 遍历所有图片
for file_name in os.listdir(source_folder):
file_path = os.path.join(source_folder, file_name)
count = count + 1
# 每隔4张选取一张验证集
if count % 5 == 0:
val_file.write(file_path + '\n')
else:
train_file.write(file_path + '\n')
if __name__ == '__main__':
generate_train_and_val_txt()
然后运行该程序,会在ImageSets/Main文件夹下生成如下文件:
Main文件夹中的文件分别表示train.txt是训练集,val.txt是验证集。
然后将这两个文件复制到G:\darknet\Magnet路径下。
在G:\darknet\Magnet\data下新建magnet.data,内容如下:
classes= 3
train = G:/darknet/Magnet/train.txt
valid = G:/darknet/Magnet/val.txt
names = G:/darknet/Magnet/data/magnet.names
backup = G:/darknet/Magnet/backup
在G:\darknet\Magnet\data下新建magnet.names,内容如下:
rip
gap
label
这里我们定义三类标签,名字分别为rip、gap、label。
从G:\darknet\cfg下复制一个配置文件作为我们的配置文件,由于我们的样本和缺陷类别都比较少,所以这里我选择tiny yolov4,tiny yolov4是简化版本的yolov4,主要是为了满足计算能力紧张的开发者使用和学习。tiny yolov4在准确度上会有相当的下降,但是在运算时间上,也会有相当大的提升。
这里我选择复制yolov4-tiny.cfg到G:\darknet\Magnet\cfg文件夹下,yolov4-tiny.cfg里面存放的是网络参数以及网络结构信息,并进行修改:
- 将classes=80 改为你的类别数3(一共2处);
- 改正[filters=255] 为 filters=(classes + 5)x3 =24(位置为查找yolo,每个yolo前的[convolutional]里,注意只修改最接近yolo的那个filters需要修改,一共应该有2处);
- 修改max_batches=classes*2000,也就是6000;
- 修改steps为80% 到 90% 的max_batches值 比如max_batches=6000,则steps=4800,5400;
- 修改batch=32,subdivisions=8;
6.3 数据打标签
给图片标记缺陷位置和类型:打开labelImg软件,在labelImg中点击“打开目录”打开数据集图片所在的文件夹为G:\darknet\Magnet\JPEGImages,如下图:
在labelImg中点击“改变存放目录”按钮,选择保存标签数据的路径为G:\darknet\Magnet\Annotations,如下图
配置好路径后,就可以开始标记了,软件的右下角会目录下的图片列表,点击软件左侧的左右箭头可以切换下一张图片查看标记,软件左下角按钮可以添加编辑标记。
标签名字暂时只能用英文,标签的名字要记住,后面还要用,本项目定义了三类标签,名字分别为rip、gap、label。
有缺陷的要标记,没有缺陷的图片或者不想训练的图片,不用标记,每标记完一个图片,Ctrl + S保存后,会在G:\darknet\Magnet\Annotations下生成相应的标签文件,吗,默认是PascalVOC格式,这里以0001.xml为例:
<annotation>
<folder>JPEGImages</folder>
<filename>0001.jpg</filename>
<path>G:\darknet\Magnet\JPEGImages\0001.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>1280</width>
<height>960</height>
<depth>1</depth>
</size>
<segmented>0</segmented>
<object>
<name>gap</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>883</xmin>
<ymin>401</ymin>
<xmax>917</xmax>
<ymax>450</ymax>
</bndbox>
</object>
<object>
<name>gap</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>879</xmin>
<ymin>491</ymin>
<xmax>914</xmax>
<ymax>540</ymax>
</bndbox>
</object>
</annotation>
我们可以通过修改格式将标签数据直接转换成YOLO训练所需要的格式:
这里我们标记完一共生成116个txt文件:
比如0001.txt:
0 0.703125 0.443229 0.026562 0.051042
0 0.700391 0.536979 0.027344 0.051042
然后我们将这些文件直接复制到G:\darknet\Magnet\labels路径下。
6.4 训练
shift+右键,G:\darknet路径下打开 PowerShell 窗口。
当没有预训练模型,执行以下代码:
./darknet.exe detector train Magnet/data/magnet.data Magnet/cfg/yolov4-tiny.cfg
如果有tiny yolov4预训练权重yolov4-tiny.conv.29:下载路径链接:https://pan.baidu.com/s/16b7GpOU50B2YkjriVQl1UQ,提取码:xbqc;下载完成复制到G:\darknet:
./darknet.exe detector train Magnet/data/magnet.data Magnet/cfg/yolov4-tiny.cfg yolov4-tiny.conv.29
跑完是这样的,每训练 100次会自动保存一次,训练生成的权重文件在G:\darknet\Magnet\backup目录下,名字为yolov4-tiny_last.weights。
6.5 预测
训练结束了,现在可以测试训练结果了,复制一份刚才训练的yolov4-tiny_last.weights保存到Magnet/weights路径下。
复制yolov4-tiny.cfg文件并且重命名为yolov4-tiny-test.cfg,修改其中的参数:
batch=1
subdivisions=1
运行以下代码测试:
./darknet.exe detector test ./Magnet/data/magnet.data ./Magnet/cfg/yolov4-tiny-test.cfg ./Magnet/weights/yolov4-tiny_last.weights ./Magnet/TESTImages/2002.jpg
参考文章
[2]【机器视觉】YOLOv4 手把手实操:制作数据集、训练权重、测试
[3]fox1986487 / YOLOV4_YOLOV4_TINY
[4]https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#install-zlib-windows