文章目录
前言
通俗的讲就是在一张图像里边找感兴趣的物体,并且标出物体在图像上的位置,在后续很多应用中,都需要目标检测做初步识别结构后做处理,比如目标跟踪,检测数量,检测有无等。
本次YoloV3是实验模型,后续没有更新,只写了训练代码。
一、数据集的准备
首先我是用的是halcon数据集里边的药片,去了前边的100张做标注,后面的300张做测试,其中100张里边选择90张做训练集,10张做验证集。
1.标注工具的安装
pip install labelimg
进入cmd,输入labelimg,会出现如图的标注工具:
2.数据集的准备
首先我们先创建3个文件夹,如图:
DataImage:100张需要标注的图像
DataLabel:空文件夹,主要是存放标注文件,这个在labelimg中生成标注文件
test:存放剩下的300张图片,不需要标注
DataImage目录下和test目录的存放样子是这样的(以DataImage为例):
3.标注数据
首先我们需要在labelimg中设置图像路径和标签存放路径,如图:
然后先记住快捷键:w:开始编辑,a:上一张,d:下一张。这个工具只需要这三个快捷键即可完成工作。
开始标注工作,首先按下键盘w,这个时候进入编辑框框的模式,然后在图像上绘制框框,输入标签(框框属于什么类别),即可完成物体1的标注,一张物体可以多个标注和多个类别,但是切记不可摸棱两可,比如这张图像对于某物体标注了,另一张图像如果出现同样的就需要标注,或者标签类别不可多个,比如这个图象A物体标注为A标签,下张图的A物体标出成了B标签,最终的效果如图:
最后标注完成会在DataLabel中看到标注文件,json格式:
4.解释xml文件的内容
xml标签文件如图,我们用到的就只有object对象,对其进行解析即可。
二、基于chainer的目标检测构建-YoloV3
1.引入第三方标准库
import sys,os,warnings,json,time,cv2,random,base64
sys.path.append('.')
os.environ["CHAINER_TYPE_CHECK"] = "0"
warnings.filterwarnings("ignore")
from PIL import Image,ImageFont,ImageDraw
import numpy as np
import chainer
import chainer.functions as F
from chainer import optimizers
from chainer.training import StandardUpdater, extensions
from chainer.datasets import TransformDataset
2.数据加载器
读取数据文件夹,这里为的是加载每一张图像以及对应的xml文件,并且解析成自定义格式即可,如图:
这里解释一下,IMGDir代表存放图像文件的路径,XMLDir代表存放标签文件的路径,train_split=0.9代表训练集和验证集9:1
数据进入网络有两种格式,分别是VOC版本和coco版本,这里都做了实现:
VOC:
COCO:
这里的输入data_list是前边CreateDataList_Detection函数的返回,分为训练和验证集合,这里是一个迭代器
3.模型构建
本次使用的YOLOV3目标检测算法,我们先看一张图:
我们这里的YoloV3目标检测,所使用的主干网络是DarkNet53,因此我们根据这个结构对目标检测YoloV3进行构建,从图像上可知,YoloV3经过darknet53对图像进行压缩5次之后,取压缩了3次,4次,5次的特征层从下网上做卷积标准化激活函数等操作,同时也做了上采样,与上一层卷积层进行融合也作为一个输出;
其次就是用先验框对下边进行检测,如:
从131375,其实就是1313(20+4+1)*3的结果,这里代表位置和类别以及先验框。
下面NMS极大值抑制,可以最终取得物体。
4.模型代码
主干网络结构:
首先Yolo主体,如图:
5.整体代码构建
1.chainer初始化
self.image_size = image_size
if USEGPU =='-1':
self.gpu_devices = -1
else:
self.gpu_devices = int(USEGPU)
chainer.cuda.get_device_from_id(self.gpu_devices).use()
2.数据集以及模型构建
train = VOCBboxDataset(data_list=train_data_list,classes_names=self.classes_names)
test = VOCBboxDataset(data_list=val_data_list,classes_names=self.classes_names)
train = YOLOVOCDataset(train, classifier=False, jitter=0.3, hue=0.1, sat=1.5, val=1.5)
test = YOLOVOCDataset(test, classifier=False)
self.train_iter = chainer.iterators.SerialIterator(train, self.batch_size)
self.test_iter = chainer.iterators.SerialIterator(test, self.batch_size, repeat=False, shuffle=False)
3.模型训练
这里与分类网络一样需要先理解chainer的工作原理:
从图中我们可以了解到,首先我们需要设置一个Trainer,这个可以理解为一个大大的训练板块,然后做一个Updater,这个从图中可以看出是把训练的数据迭代器和优化器链接到更新器中,实现对模型的正向反向传播,更新模型参数。然后还有就是Extensions,此处的功能是在训练的中途进行操作可以随时做一些回调(描述可能不太对),比如做一些模型评估,修改学习率,可视化验证集等操作。
因此我们只需要严格按照此图建设训练步骤基本上没有什么大问题,下面一步一步设置
设置优化器:
optimizer = optimizers.MomentumSGD(lr=learning_rate, momentum=0.9)
optimizer.setup(self.train_chain)
optimizer.add_hook(chainer.optimizer.WeightDecay(rate=0.0005))
设置update和trainer:
updater = StandardUpdater(self.train_iter, optimizer, device=self.gpu_devices)
trainer = chainer.training.Trainer(updater, (TrainNum, 'epoch'), out=ModelPath)
Extensions功能设置:
# 修改学习率
trainer.extend(
extensions.ExponentialShift('lr', 0.9, init=learning_rate),
trigger=chainer.training.triggers.ManualScheduleTrigger([50,80,150,200,280,350], 'epoch'))
# 每过一次迭代验证集跑一次
trainer.extend(
DetectionVOCEvaluator(self.test_iter, self.train_chain.model, use_07_metric=True, label_names=self.classes_names),
trigger=chainer.training.triggers.ManualScheduleTrigger([each for each in range(1,TrainNum)], 'epoch'))
# 可视化验证集效果
trainer.extend(Detection_VIS(
self.model,
self.val_data_list,
self.classes_names, image_size=self.image_size,
trigger=chainer.training.triggers.ManualScheduleTrigger([each for each in range(1,TrainNum)], 'epoch'),
device=self.gpu_devices,ModelPath=ModelPath,predict_score=0.5
))
# 模型保存
trainer.extend(
extensions.snapshot_object(self.model, 'Ctu_best_Model.npz'),
trigger=chainer.training.triggers.MaxValueTrigger('validation/main/map',trigger=chainer.training.triggers.ManualScheduleTrigger([each for each in range(1,TrainNum)], 'epoch')),
)
# 日志及文件输出
log_interval = 0.1, 'epoch'
trainer.extend(chainer.training.extensions.LogReport(filename='ctu_log.json',trigger=log_interval))
trainer.extend(chainer.training.extensions.observe_lr(), trigger=log_interval)
trainer.extend(extensions.dump_graph("main/loss", filename='ctu_net.net'))
最后配置完之后只需要一行代码即可开始训练
trainer.run()
三、训练代码
因为本代码是以对象形式编写的,因此调用起来也是很方便的,如下显示:
# 训练代码
ctu = Ctu_YoloV3(USEGPU='0',image_size=416)
ctu.InitModel(r'D:/Ctu/Ctu_Project_DL/DataSet/DataSet_Detection_Color',train_split=0.9,alpha=2,batch_size = 1)
ctu.train(TrainNum=200,learning_rate=0.0001, ModelPath='result_Model')
总结
本文章主要是基于chainer的目标检测YoloV3的基本实现思路和步骤
源码:chainer-yolov3源码