在我们前面的系列博文中,关于田间作物场景下的作物、杂草检测已经有过相关的开发实践了,结合智能化的设备可以实现只能除草等操作,玉米作物场景下的杂草检测我们则少有涉及,这里本文的主要目的就是想要基于DETR模型来开发构建玉米田间作物场景下的玉米苗和杂草检测识别系统。
春节前后我们已经基于YOLO系列最新的YOLOv8模型开发构建了相应的项目,感兴趣可以自行移步阅读:
《助力智能化农田作物除草,基于轻量级YOLOv8n开发构建农田作物场景下玉米苗、杂草检测识别分析系统》
《助力智能化农田作物除草,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建农田作物场景下玉米苗、杂草检测识别分析系统》
随后我们基于首个端到端的目标检测模型DETR开发构建了相应的检测模型,如下:
《助力智能化农田作物除草,基于DETR(DEtection TRansformer)模型开发构建农田作物场景下玉米苗、杂草检测识别分析系统》
完成上述开发之后,我们想尝试基于早期开山的YOLOv3模型来开发构建对应的检测模型,如下所示:
《助力智能化农田作物除草,基于YOLOv3全系列【yolov3tiny/yolov3/yolov3spp】参数模型开发构建农田作物场景下玉米苗、杂草检测识别分析系统》
之后我们基于最为经典的YOLOv5全系列五款不同参数量级的模型来发构建了玉米田杂草检测系统,进行了整体的对比分析实验,本文主要是想应用美团最新提出的YOLOv6来构建同样的检测模型,为线上推理提供对比数据,首先看下实例效果:
简单看下实例数据情况:
本文选择的是YOLOv6这一算法模型,Yolov6是美团开发的轻量级检测算法,截至目前为止该算法已经迭代到了4.0版本,每一个版本都包含了当时最优秀的检测技巧和最最先进的技术,YOLOv6的Backbone不再使用Cspdarknet,而是转为比Rep更高效的EfficientRep;它的Neck也是基于Rep和PAN搭建了Rep-PAN;而Head则和YOLOX一样,进行了解耦,并且加入了更为高效的结构。YOLOv6也是沿用anchor-free的方式,抛弃了以前基于anchor的方法。除了模型的结构之外,它的数据增强和YOLOv5的保持一致;而标签分配上则是和YOLOX一样,采用了simOTA;并且引入了新的边框回归损失:SIOU。
YOLOv5和YOLOX都是采用多分支的残差结构CSPNet,但是这种结构对于硬件来说并不是很友好。所以为了更加适应GPU设备,在backbone上就引入了ReVGG的结构,并且基于硬件又进行了改良,提出了效率更高的EfficientRep。RepVGG为每一个3×3的卷积添加平行了一个1x1的卷积分支和恒等映射的分支。这种结构就构成了构成一个RepVGG Block。和ResNet不同的是,RepVGG是每一层都添加这种结构,而ResNet是每隔两层或者三层才添加。RepVGG介绍称,通过融合而成的3x3卷积结构,对计算密集型的硬件设备很友好。
这里我们依次开发构建了n、s、m和l四款不同参数量级的模型,模型文件如下:
训练数据配置文件如下所示:
# Please insure that your custom_dataset are put in same parent dir with YOLOv6_DIR
train: ./dataset/images/train # train images
val: ./dataset/images/test # val images
test: ./dataset/images/test # test images (optional)
# whether it is coco dataset, only coco dataset should be set to True.
is_coco: False
# Classes
nc: 3 # number of classes
# class names
names: ['maize', 'weedhe', 'weedkuo']
这里以s系列模型为例详细看下模型详情:
# YOLOv6s model
model = dict(
type='YOLOv6s',
pretrained='weights/yolov6s.pt',
depth_multiple=0.33,
width_multiple=0.50,
backbone=dict(
type='EfficientRep',
num_repeats=[1, 6, 12, 18, 6],
out_channels=[64, 128, 256, 512, 1024],
fuse_P2=True,
cspsppf=True,
),
neck=dict(
type='RepBiFPANNeck',
num_repeats=[12, 12, 12, 12],
out_channels=[256, 128, 128, 256, 256, 512],
),
head=dict(
type='EffiDeHead',
in_channels=[128, 256, 512],
num_layers=3,
begin_indices=24,
anchors=3,
anchors_init=[[10,13, 19,19, 33,23],
[30,61, 59,59, 59,119],
[116,90, 185,185, 373,326]],
out_indices=[17, 20, 23],
strides=[8, 16, 32],
atss_warmup_epoch=0,
iou_type='giou',
use_dfl=False, # set to True if you want to further train with distillation
reg_max=0, # set to 16 if you want to further train with distillation
distill_weight={
'class': 1.0,
'dfl': 1.0,
},
)
)
solver = dict(
optim='SGD',
lr_scheduler='Cosine',
lr0=0.0032,
lrf=0.12,
momentum=0.843,
weight_decay=0.00036,
warmup_epochs=2.0,
warmup_momentum=0.5,
warmup_bias_lr=0.05
)
data_aug = dict(
hsv_h=0.0138,
hsv_s=0.664,
hsv_v=0.464,
degrees=0.373,
translate=0.245,
scale=0.898,
shear=0.602,
flipud=0.00856,
fliplr=0.5,
mosaic=1.0,
mixup=0.243,
)
不同参数系列模型训练命令如下:
#yolov6n
python3 tools/train.py --batch-size 16 --conf configs/yolov6n_finetune.py --data data/self.yaml --fuse_ab --device 0 --name yolov6n --epochs 100 --workers 2
#yolov6s
python3 tools/train.py --batch-size 16 --conf configs/yolov6s_finetune.py --data data/self.yaml --fuse_ab --device 0 --name yolov6s --epochs 100 --workers 2
#yolov6m
python3 tools/train.py --batch-size 16 --conf configs/yolov6m_finetune.py --data data/self.yaml --fuse_ab --device 0 --name yolov6m --epochs 100 --workers 2
#yolov6l
python3 tools/train.py --batch-size 16 --conf configs/yolov6l_finetune.py --data data/self.yaml --fuse_ab --device 0 --name yolov6l --epochs 100 --workers 2
这里我们在训练阶段保持完全相同的参数设置,均基于官方权重进行微调开发。
训练完成结果详情如下:
【yolov6n】
【yolov6s】
【yolov6m】
【yolov6l】
一直都觉得yolov6不够火跟他的结果文件过于单一有很大的关系。
离线推理实例如下:
感兴趣的话也可以动手尝试下!
如果自己不具备开发训练的资源条件或者是没有时间自己去训练的话这里我提供出来对应的训练结果可供自行按需索取。