前言
其实年初的时候,我也跟着别人的源码,用 Tensoflow 实现过扑克牌的目标检测。虽然也通过博文的方式记录了,但是那个项目使用的 TF 版本比较旧,自身对 TF 并不熟。后期如果说要升级或修改估计够呛,知道最近看到 YOLO 对目标检测的实现方法,发现这个更方便快捷。
于是决定用 YOLOv5.6 来重新实现一下扑克牌的点数识别,本文章主要是个人记录,也面向刚刚接触 YOLO 的同学阅读。所以以下会从数据标注,归一化处理到模型训练的实战内容,也包括各种踩坑经历和处理方法,最后对 detect.py 的重写,完成目标对象的坐标和识别标记输出。
YOLO 简介
YOLO(You Only Look Once)是一种基于深度神经网络的对象识别和定位算法,其最大的特点是运行速度很快,可以用于实时系统。现在 YOLO 已经发展到 v8 版本,每个版本都在原有基础上改进演化的。选择 V5 是因为后面几个新版发行并不久,v5 相关资料和文章较多,踩坑起来也好搜索。其中每个版本里又有按场景划分几个特定场景版本,比如:
- YOLOv5s:最小版本,速度最快,但检测性能最低。
- YOLOv5m:中等版本,速度比 s 慢一些,但检测性能更好。
- YOLOv5l:大型版本,速度比 m 慢,但检测性能更好。
- YOLOv5x:最大版本,速度最慢,但是检测性能最好。
- YOLOv5n6:中等版本,速度比 m 快一些,但检测性能更好。
总之,根据具体需求和应用场景,可以选择合适的 YOLOv5 版本以满足性能、速度和准确性的要求,我这里以 YOLOv5s 为例。然后在项目开始前呢,我们可以先去github下载 demo 代码和权重文件,比如 yolov5s.pt,下载完后就要准备数据集,也就是标记的图片。
数据集
图片的话,看你要识别的目标是啥,可以拍摄整理或去网上下载。为了让训练的模型稍微有点准确,最好准备一两百张,我这里就直接从原来 TF 项目那里拿过来。一共有 363 张扑克牌图片并且都已经用 VOC 格式标注好了,不过为了大家了解,这里还是会介绍如何标注,以及标注工具 labelImg 的基本使用。
LabelImg 使用
- 操作界面
- 快捷使用
1、W 是进行标注
2、A 是切换到上一张图片
3、D 是切换到下一张图片
- LabelImg 保存格式
1. PascalVOC 默认,xml格式
2. YOLO text可以直接拿来训练不用转换
实战
创建目录
在根目录下新建 datasets 用于放置训练的数据集,由于用同一 yolo 可以创建多个检测目标,所以在 datasets 先创建一个项目名目录。然后再在项目名下可创建 VOC 和 YOLO 两种格式的目录,虽然 labelImg 标注后可以直接保存 YOLO 格式也就是归一化后的 text,但是毕竟三百多张图的标注,我这里依然使用以前 TF 的 VOC 的标注数据。如果需要这些数据集的,可以留言,到时我再放在评论区。
依赖安装
依赖直接安装项目根目录下的 requirements.txt 就可以,但是要严格按照里面的版本。因为我用的是以前 conda 创建的环境,可以包都装过,所以一开始就看到已经有的就没装,导致后面运行的时候很多问题都是包的版本问题。所以最好的方法就是用 conda 创建一个新环境,然后直接pip install -r requirements.txt 是最好的。
归一化和数据集划分
如果 LabelImg 标注后保存的是 YOLO 格式,归一化过程就可以略过了。前面我也说了是用的以前扑克牌的 VOC 格式,所以需要对 xml 里节点数据抽取坐标和标记然后转换成 yolo 的 txt 格式。以下代码是我从其他博主那薅过来的,主要就是归一化和划分训练数据集和校验数据集。特别主要是 classes 部分要修改成自己的目标分类,其他的可以不用改动,当然只是划分的话可以适当删减。
上面代码放在哪个位置看你自己,由于有些目录是相对位置,所以如果不想改也跟我一样放在 datasets 中。执行完上面代码后会在 datasets 下生成 images 和 labels 两个目录,而且特别注意的是这两个目录名最好就是也是这样,比如在上面代码改了生成名,在后面训练的时候,会提示找不到 labels 目录。当然也可以修改 YOLO 提供源码的 dataset.py,看个人选择,而且 images 里的 train 和 val 需要配置到 data 的 yaml 中,这个马上就会说。
配置
- 数据集配置
该默认文件位于项目的 data/coco128.yaml,现在我们进行划分了数据集和自己的目标种类,当然要对其进行重新配置。最好的方法就是复制一份 coco128 然后修改名称,如下面 coco128_pocker.yaml 是我的配置示例。
- 模型配置
该默认文件位于项目的 model 下,然后选择自己的场景,如我用的是 v5s 同样就复制一份重命名。这个文件主要是定义模型的基本机构和参数,比如分类数目 nc,模型深度倍数 depth_multiple,每层通道数倍数 width_multiple,以及目标框的大小和比例的 anchors。在刚使用 YOLO 的话,我们就改个 nc 就可以,后面再研究这些参数的用法,下面是 yolov5s_pocker.yaml 的示例。
- 权重文件
这个就是我们从 yolo 开源那里下载的 yolov5s.pt,这里面有 80 个类目的检测,在基础识别时候可以直接用它。而训练自己的目标也需要基于他的权重再进行训练,所以可以在项目中创建一个 weights,然后再将 yolov5s.pt 放到其中。
训练
- 基础预测
在训练目标模型前,可以先试试以前的基础检测,这里我们可以随便拿一张图放到 data/images 下,然后执行下面命令,根目录下会生成 runs,而 runs 下的 detect 会根据每次执行的次数生成不同次的标注结果。
python detect.py --weights weights/yolov5s.pt --source data/images/zidane.jpg
- 指令介绍
- 开始训练
以下是我踩过坑后执行的命令,因为当时我用 CPU 训练一轮要 7 分钟就改成了 GPU,加了 --device 0 后速度快了 4 倍。batch-size 为 2,这么小是因为我的显卡 750Ti 显存只有 2G,就暂时用了这个数值。而加了 --workers 0,也是因为有坑,这个后面再说。训练完成后,会在根目录的 runs/train 下生成每次运行的权重文件和损失准确示例图等,其中 weights 下的 best.pt 和 last.pt,分别表示本轮训练最好的权重和最新的权重。
python train.py --weights weights/yolov5s.pt --cfg models/yolov5s_pocker.yaml --data data/coco128_pocker.yaml --epochs 1 --batch-size 2 --multi-scale --device 0 --workers 0
开始检测
训练完成后,我们可以把本轮的 best.pt 放到根目录的 weights 下,以下是不同检测方式的命令,可以分别都试一下。
1. 图片
python detect.py --weights weights/best.pt --data data/coco128_pocker.yaml --source data/images/cam_image16.jpg
2. 视频
python detect.py --weights weights/best.pt --data data/coco128_pocker.yaml --source data/images/test.mov
3. 使用cuda测试
python detect.py --device 0 --weights weights/best.pt --data data/coco128_pocker.yaml --source data/images/IMG_2681.JPG
detect.py 重写
因为在实际项目中,我们对图片和视频的目标检测,更多的可能是通过前端传递过来的图片或视频,模型给出的是预测的类目名称和目标的位置,而不是直接生成标注的图片和视频。所以我对 demo 提供的 detect 进行了简单的修改,修改结果就是前面放出的图片,不过还是采用命令方式,当然也可以直接改成接口,最后就是如果需要代码的可以评论区留言哈。
热门跟贴