写在前面
前段时间参加了Kaggle的一个目标检测竞赛,比赛后期因为工作较繁忙就搁置了,但仍然获得了铜牌(前10%)。因此在这里想跟大家分享下自己的方案,希望能帮助大家更好的了解目标检测这一经典的计算机视觉领域。
这篇教程的主要代码来源于这个git仓库(https://github.com/ultralytics/yolov5),是国外一个公司开源的。选择这个项目一是因为性能好,最新mAP达到了50.8/25.5ms,太强大了;二是因为该项目是用pytorch实现的,使用门槛低,很适合初学者。下面开始我们的实战教程。
数据分析
这里需要重点说明下,CV任务的第一步绝对不是搭模型,而是观察数据,只有了解的数据的组成和分布,才能搭出性能更好好的模型。首先看下比赛数据,看下面9张图片,可以看出小麦品种不一,风格差异很大,所以很明显Domain Gap是这个比赛的难点。
再来看下标注框,每张图有几十个目标,分布非常密集,所以这个任务其实属于密集小目标检测问题,因此像FPN这种金字塔模型肯定是必不可少的。
数据处理
目标检测任务跟分类不同,数据的格式有很多种,比较常用的是COCO和VOC格式,YoloV5使用的是YOLO自己的格式。Kaggle的数据标签是用csv格式保存的,需要转换成YOLO的标注格式。格式转换可以参考下面这段代码。
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import os
df = pd.read_csv('../input/global-wheat-detection/train.csv')
bboxs = np.stack(df['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))
for i, column in enumerate(['x', 'y', 'w', 'h']):
df[column] = bboxs[:,i]
df.drop(columns=['bbox'], inplace=True)
df['x_center'] = df['x'] + df['w']/2
df['y_center'] = df['y'] + df['h']/2
df['classes'] = 0
from tqdm.auto import tqdm
import shutil as sh
df = df[['image_id','x', 'y', 'w', 'h','x_center','y_center','classes']]
index = list(set(df.image_id))
index = list(set(df.image_id))
source = 'train'
if True:
for fold in [0]:
val_index = index[len(index)*fold//5:len(index)*(fold+1)//5]
for name,mini in tqdm(df.groupby('image_id')):
if name in val_index:
path2save = 'val2017/'
else:
path2save = 'train2017/'
if not os.path.exists('convertor/fold{}/labels/'.format(fold)+path2save):
os.makedirs('convertor/fold{}/labels/'.format(fold)+path2save)
with open('convertor/fold{}/labels/'.format(fold)+path2save+name+".txt", 'w+') as f:
row = mini[['classes','x_center','y_center','w','h']].astype(float).values
row = row/1024
row = row.astype(str)
for j in range(len(row)):
text = ' '.join(row[j])
f.write(text)
f.write("\n")
if not os.path.exists('convertor/fold{}/images/{}'.format(fold,path2save)):
os.makedirs('convertor/fold{}/images/{}'.format(fold,path2save))
sh.copy("../input/global-wheat-detection/{}/{}.jpg".format(source,name),'convertor/fold{}/images/{}/{}.jpg'.format(fold,path2save,name))
模型训练
先看下YoloV5长啥样,毕竟从YoloV1发展到V5,模型也确实复杂了很多,不过其实核心结构没有变,只是增加了大量的trick,每一个trick都需要大量的调参,这也是YoloV5作者的一个非常大的贡献。不过我建议刚上手不用了解的这么深入,先跑起来再说。
数据处理完毕后,下载YoloV5的源代码,在data文件下配置自己的数据路径,例如下面的wheat0.yaml,主要是训练和验证集的路径,类别数量和类别名这4个参数。
# train and val datasets (image directory or *.txt file with image paths)
train: ./convertor/fold0/images/train2017/
val: ./convertor/fold0/images/val2017/
# number of classes
nc: 1
# class names
names: ['wheat']
配置文件更改完成后就可以直接训练了,需要训练100个epoch才能得到一个较好的模型。使用如下的训练脚本开始训练。
python train.py --img 1024 --batch 2 --epochs 100 --data ../input/configyolo5/wheat0.yaml --cfg ../input/configyolo5/yolov5x.yaml --name yolov5x_fold0
下面是我训练模型的可视化结果,可以看出来效果还是不错的,基本没有漏标或误判。
写在后面
以上就是YoloV5的实战训练教程,其实跑起来还是很简单的。大家可以先试下,把训练流程跑通,下篇文章我会把我的测试流程和kaggle的提交代码也分享出来,欢迎大家关注和转发。有任何问题可以在文章下面评论,我会及时回复。
本文暂时没有评论,来添加一个吧(●'◡'●)