前言
本文主要的参考资料和github
项目如下:
Could not find the Qt platform plugin windows
错误解决方法:
https://blog.csdn.net/DonetRen/article/details/106437538
pytorch
版yolov3
训练自己数据集:
https://www.cnblogs.com/pprp/p/10863496.html
https://blog.csdn.net/qq_38587510/article/details/106019905
https://blog.csdn.net/qq_39056987/article/details/104327638
github
项目:
labelImg:https://github.com/tzutalin/labelImg
yolov3:https://github.com/ultralytics/yolov3(master是`yolov5`,archive是`yolov3`)
labelImg
安装PyQt5
和lxml
就可以运行了,运行可能会需要配置环境变量
具体参考文章:https://blog.csdn.net/DonetRen/article/details/106437538
数据标注的方式和数据集分割的方式(划分为训练集、验证集和测试集)与keras-yolov3
项目是一样的,但是数据格式转换的操作有所不同,pytorch-yolov3
项目中没有keras
项目中的voc_annotation.py
用来转换数据格式,需要使用以下代码来完成操作。
1 | # -*- coding: utf-8 -*- |
list_file.write(f'data/VOCdevkit/VOC{year}/JPEGImages/{image_id}.jpg\n')
这里对写入的文件路径做了调整,前面加了data/VOCdevkit
,这样就可以直接把VOCdevkit
整个项目复制到pytorch-yolov3
项目的data目录下。
使用以上脚本生成的
MiniConda
实际上就是可以创建虚拟环境和包管理,但是不得不说使用conda
安装包很麻烦,使用国内镜像源下载很多包依然很慢很慢,而且想换源还要不断的改配置,相比较pip是真的好用,使用哪个镜像直接一个-i就可以,而且安装包快的飞起,这次算是对miniconda
的一次尝试吧,后面如果再做项目,没有特殊的环境需求,我可能还是倾向于使用统一环境,使用pip来安装包。
补充一个使用pycharm
配置conda
虚拟环境的方式。
Pytorch YoloV3
apex
apex
混合精度加速,无显卡不能加速。若想要使用,需要单独从github拉相关的项目。
修改配置文件
在data
目录下新建*.data文件,文件内容和说明如下:
1 | classes = 1 # 改成你的数据集的类别个数 |
backup=backup/
、eval=coco
这两项根据自身实际情况添加即可:
backup=backup/
指的是会在backup文件夹下存放训练得到的checkpoint;
eval=coco
指的是在测试和评判模型时采用coco数据集中的评判标准,倘若加了这一项,还需要对之前生成的.xml
文件做转换,将其由VOC
格式转换为coco格式的json
文件。
特别注意:文件真正的内容不要包含后面的注释,否则运行时会报错
修改yolov3.cfg
文件:
1 | [convolutional] |
只需要更改每个[yolo]
层前边卷积层的filter个数和[yolo]
层的classes数量即可,也就是上面代码注释部分标注的内容,一共三组6处地方需要修改;同样地,实际内容要去掉注释,否则会报错。
在Windows下运行该项目,可能会有多个地方出现打开文件时编码不正确的情况,因为Windows下默认编码为gbk
,所以要么将文件编码改为gbk
,要么在打开文件的地方设置encoding='utf-8'
。
预训练权重文件
我们在训练数据的时候,一般使用预训练权重,即yolov3.weights
,但是因为其是darket
版的权重文件,需要通过一定的方式转换成pytorch
版的;另外,除了最初的yolov3
模型,还有在此基础上改写的tiny模型和spp
模型。
这几个预训练权重文件(Darket
版)在weights
目录下的download_yolov3_weights.sh
文件中给出了说明
文件权重模型转换:
1 | $ git clone https://github.com/ultralytics/yolov3 && cd yolov3 |
实际上就是使用models.py
脚本中的convert方法来转化,并且支持双向转换。不过需要搭配cfg
文件夹下的.cfg
文件来完成转换,会生成对应名称的.pt
文件,反之亦然。
入口train.py
这个yolov3.pt
文件在train.py
的main函数的weights
配置中使用,如果我们是使用命令行运行,那就在命令行中指定--weights
参数就好了,如果是在类似pycharm
的软件中直接执行,可以直接修改这个值,类似需要修改的还有--cfg, --data
等。
命令行运行示例:
python train.py --data data/coco.data --cfg cfg/yolov3.cfg --weights yolov3.pt
另外,按照我这里训练数据存放的形式,还需要在修改datasets.py
文件中的这个地方:
replace('images', 'labels')
– > replace('JPEGImages', 'labels')
(共两处)
因为这里在读取标签时,是直接将文件路径中的images替换为labels,后缀由jpg
改为txt
,而我并没有把图片放到指定的images文件下,所以这里需要改一下。
当一些必要的调整做完之后,如果不着急进度,我的建议是可以从train.py
开始逐步调试,搞清楚整个项目运行的流程,具体细节一开始不用搞的很清楚,只要大概知道哪些方法都是做什么用的就行了,而且,因为一些特殊原因,可能会遇到一些报错,基本一直调试下去,就可以把所有的错误都自己独立的解决掉。
比如上面遇到的编码问题、weights
参数报错(pt文件不存在)、修改配置文件不能加注释、改VOC
数据生成路径、修改datasets.py
等问题,均是在调试过程中发现并解决的。
模型加载
上一次研究yolov3
一直不清楚yolov3.cfg
这个文件的作用,只是单纯的按照要求修改文件,这次研究了下,发现这个就是yolov3
模型的核心配置文件,就是从这个文件加载的神经网络模型,经过对比里面的内容发现与网络结构图一一对应:
1 | [convolutional] |
比如这里截取的部分,对应着Darknet53
最开始的地方。
相应的还有yolov3-spp.cfg
和yolov3-tiny.cfg
,对应着稍有不同的模型,使用的时候,要搭配yolov3-spp.weights
和yolov3-tiny.weights
使用,不过要先转换为.pt
文件才能通过pytorch
使用。
训练过程
训练过程的输出(上面是输出的代码):
1 | s = ('%10s' * 2 + '%10.3g' * 6) % ('%g/%g' % (epoch, epochs - 1), mem, *mloss, len(targets), img_size) |
1 | Epoch gpu_mem GIoU obj cls total targets img_size |
Epoch:当前轮次
gpu_mem
:推测大概是GPU
占的内存吧,如果没有GPU
,那就是0
GIoU
:一种类似IoU
(交并比)的算法,使用其作为目标损失函数;
obj
:objectness(置信度);
cls
:classification
*/16表示共16个批次,当前训练到第几批,因为这里总共244张图片,batch_size=16,所以总共16个batch,最后一个batch的size只有4。
验证过程的输出:
1 | Class Images Targets P R mAP@0.5 F1: 100%|██████████| 3/3 [00:24<00:00, 8.18s/it] |
Class
Images:表示有多少张图片
Targets:表示有多少个要检测的目标
P
:Precision准确率
R
:Recall召回率
mAP
:Mean Average Precision 的缩写,即均值平均精度。
作为 object dection
中衡量检测精度的指标。
计算公式为: 所有类别的平均精度求和除以所有类别。
F1
模型保存
训练的过程中,会在weights文件夹下生成best.pt
和last.pt
两个权重文件,last.pt
随着训练轮次不断更新,best.pt
则保留截止当前训练过程中最好的权重。
测试
测试使用detect.py
脚本,与train.py
类似,运行时通过很多命令行参数来配置,如果是直接在pycharm
中运行,那么直接修改相应的参数值就好了,比如这几个参数
1 | parser.add_argument('--cfg', type=str, default='cfg/yolov3.cfg', help='*.cfg path') |
cfg
、names
这两个和train.py
保持一致,weights
这里改成我们训练过程中保存下来的最好的模型权重;
source
这里需要注意,这里默认的是读取data/samples
目录下的图片来测试,后面的注释还写了如果设置为0,他会测试视频;因为我上面说了我是直接把数据集都放在了data/VOCdevkit
下,samples里没有图片,如果要测试的话,我还需要把测试集的图片复制过去,所以我想是不是可以把这里的source值改成我的测试目录,所以就改成了data/VOCdevkit/2007_test.txt
(这个文件里保存了所有测试图片的路径,但是不是实际的测试图片)我也不确定这个source这样设置是否可行,所以我就去调试了,调试发现
1 | webcam = source == '0' or source.startswith('rtsp') or source.startswith('http') or source.endswith('.txt') |
因为我这里source设置的值满足后缀是.txt
,所以webcam=True
,然后接下来走了视频测试的流程;
然后我就把webcam
主动设置为False,让程序去走图片检测的流程,最终发现source的值要求该路径下必须是实打实的图片,所以只好把测试图片全部放到samples
路径下,经过下面简单的代码移动就可以了:
1 | with open(r'data/VOCdevkit/2007_test.txt', 'r', encoding='utf-8') as fr: |
预测完成之后,会在output文件夹下,生成检测结果——带有检测框的图片,直接打开查看框是否准确即可。
项目实践过程:
1、切分图片并从CAD导出数据集
2、标注数据
3、训练数据,无效果–>怀疑是尺寸问题
4、resize图片和标注好的xml
文件
5、利用k-means算法重新生成anchor box的大小,有初步的效果。