PaddleDetection 是百度飞桨推出的物体检测统一框架。支持现有的RCNN、SSD、YOLO等系列模型、支持 ResNet、ResNet-VD、ResNeXt、ResNeXt-VD、SENet、MobileNet、DarkNet等主干网络。针对不同的业务场景(性能、目标大小、准确率等)可以选择框架中的不同模块组合得到最适合的模型,实现任务。相比于tensorflow的Object_Detection,优势之一就是将YOLOv3这一目标检测的快速算法融合到了框架下。
文章将以一个Yolov3识别水果的例子为说明,详解如何利用PaddleDetection完成一个项目。
1.1 安装PaddlePaddle
1.2 安装COCO-API
pip install Cythonpip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
1.3 选择一个文件夹,下载PaddleDetection
git clone https://github.com/PaddlePaddle/PaddleDetection.git
1.4 安装所需的Python其他依赖库
pip install -r requirements.txt
激活环境,并且 pip install -r requirements.txt
当显示Successfully…… ,基本上表示安装完成了,具体是否成功,下一步的测试验证。
1.5 确认测试通过
set PYTHONPATH=`pwd`:$PYTHONPATHpython ppdet/modeling/tests/test_architectures.py
错误提示发现缺少“ppdet”这个模块,ppdet(其实就是paddle detection的一个缩写),但是我们在项目的路径里面可以发现有这个模块,原因就是,我们的代码所在的路径无法读取到该文件下的代码,因此,我们需要在代码中进行改进一下。
找到 ppdet/modeling/tests/test_architectures.py这个文件,然后添加红框所示的代码。备注,第二个红框里面的路径是我的项目路径。
出现如图所示的代码,表示运行成功。
至此,所有的运行环境已经配置成功。
2.1 数据标注:
https://pan.baidu.com/wap/init?surl=ZO8OlqvWuMk_sqOwlo56rg
标注方式如下:

选取标注文件的保存路径:
点击Change Save Dir ,然后将标注文件保存在某一个路径下。
所有标注完成以后会生成很多的xml文件。
打开一个xml文件:
具体信息如下:
其中Annotations存放标注生成的xml文件,JPEGImage存放图片,ImageSets存放对训练集和数据集的划分。
ImageSet下有Main文件,Mian下需要建立一个label_list.txt。label_list.txt是指标注的目标的名称。其内容如下:
备注:train.txt、val.txt是根据下文中代码(该代码会命名为:get_list.py,放置在了数据集链接的文件里面)生成,分别是对训练集和验证集的划分:
import osimport random
train_precent=0.7xml="C:/Users/zhili/Desktop/fruit-detection/Annotations"save="C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main"total_xml=os.listdir(xml)
num=len(total_xml)tr=int(num*train_precent)train=range(0,tr)
ftrain=open("C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main/train.txt","w")ftest=open("C:/Users/zhili/Desktop/fruit-detection/ImageSets/Main/test.txt","w")
for i in range(num): name=total_xml[i][:-4]+"\n" if i in train: ftrain.write(name) else: ftest.write(name)ftrain.close()ftest.close()
如下图是生成的train文件:
备注:在Main文件夹中生成的train.txt文件和val.txt文件仅仅是对数据集的划分,还需要进一步的利用如下代码(create_list.py,该代码是paddle提供的)生成含有路径信息以及图像和xml文件一一对应的文件。
import osimport os.path as ospimport reimport random
devkit_dir = './'years = ['2007', '2012']
def get_dir(devkit_dir, type): return osp.join(devkit_dir, type)
def walk_dir(devkit_dir): filelist_dir = get_dir(devkit_dir, 'ImageSets/Main') annotation_dir = get_dir(devkit_dir, 'Annotations') img_dir = get_dir(devkit_dir, 'JPEGImages') trainval_list = [] test_list = [] added = set()
for _, _, files in os.walk(filelist_dir): for fname in files: img_ann_list = [] if re.match('train\.txt', fname): img_ann_list = trainval_list elif re.match('val\.txt', fname): img_ann_list = test_list else: continue fpath = osp.join(filelist_dir, fname) for line in open(fpath): name_prefix = line.strip().split()[0] if name_prefix in added: continue added.add(name_prefix) ann_path = osp.join(annotation_dir, name_prefix + '.xml') img_path = osp.join(img_dir, name_prefix + '.jpg') assert os.path.isfile(ann_path), 'file %s not found.' % ann_path assert os.path.isfile(img_path), 'file %s not found.' % img_path img_ann_list.append((img_path, ann_path))
return trainval_list, test_list
def prepare_filelist(devkit_dir, output_dir): trainval_list = [] test_list = [] trainval, test = walk_dir(devkit_dir) trainval_list.extend(trainval) test_list.extend(test) random.shuffle(trainval_list) with open(osp.join(output_dir, 'train.txt'), 'w') as ftrainval: for item in trainval_list: ftrainval.write(item[0] + ' ' + item[1] + '\n')
with open(osp.join(output_dir, 'val.txt'), 'w') as ftest: for item in test_list: ftest.write(item[0] + ' ' + item[1] + '\n')
if __name__ == '__main__': prepare_filelist(devkit_dir, '.')
最终生成如下所示的数据集格式如下,其中label_list.txt和Mian中的label_list.txt一致。train.txt文件和val.txt是新生成的图像-xml的名称路径对应文件。
该完成后的数据集作者放置在了项目文件夹下:dataset/fruit下,并命名为该文件夹为fruit-detection如下图所示。
数据集生成后就可以根据如下的命令进行训练。
如图下图就是我们选取的深度学习的配置文件,我们选取yolov3_mobilenet_v1_fruit.yml做为
本项目的训练配置文件。该配置文件是使用YOLO v3的模型结构,同时主干网络为 Mobilenrt V1。这些参数可以根据我们自己的数据情况进行设计。
如设置:最大迭代步数:max_iters
需要着重关注点如下:需要根据自己的不同数据集进行训练。
在将config文件配置好了以后,就可以进行训练:
set PYTHONPATH=$PYTHONPATH:.set CUDA_VISIBLE_DEVICES=0(默认只有一个GPU) python -u tools/train.py -c configs/yolov3_mobilenet_v1_fruit.yml --use_tb=True --tb_log_dir=tb_fruit_dir/scalar --eval
出现如下图所示现象,可以表示为训练正常,可等待训练结束。
-c configs/yolov3_mobilenet_v1_fruit.yml 用来指定配置文件
--use_tb 是否使用tb-paddle记录数据,进而在TensorBoard中显示,默认值是False
--tb_log_dir 指定 tb-paddle 记录数据的存储路径
--eval 是否边训练边测试
备注:
训练过程出现的一个错误:
作者使用的电脑是笔记本,显卡型号是RTX2060 显存为6G。在训练过程中出现如下错误。
通过命令提示符中发现,竟然出现了(7184, 7184, 3)这样大的图片,而本身数据像素多数为1000*1000左右。
解决改问题的方式有两个:
第一个是修改配置文件中的bufsize这个参数,将该值由128改成64(备注,PaddleDetection新更新的配置文件文档中,已经将该值设置成为32),即可正常运行。在这里解释一下:PaddleDetection YOLOv3系列模型训练时,由于图像增强等预处理方式较多,默认会开启多进程加速,子进程完成图像读取,图像增强等预处理后,会将输出结果放到一个队列里面等待模型训练时获取,bufsize这个参数即为该队列的最大长度,该队列存储在内存中,若机器内存较小并且队列长度bufsize设置得较大,就会有上述报错,报错内容为内存不够,无法给队列继续分配内存。这个时候只要把bufsize调小一些保存内存足够放下队列即可。
训练期间可以通过tensorboard实时观察loss和精度值,启动命令如下:
tensorboard --logdir tb_fruit_dir/scalar
执行如下命令:
python tools/export_model.py -c configs/yolov3_mobilenet_v1_fruit.yml --output_dir=./inference_model -o weights=output/yolov3_mobilenet_v1_fruit/best_model
特别备注:目前导出的模型使用是为了后面C++预测的,python预测目前不支持加载导出的模型。
6.1 使用单张图片进行预测
python -u tools/infer.py -c configs/yolov3_mobilenet_v1_fruit.yml -o weights= output/yolov3_mobilenet_v1_fruit/best_model --infer_img=demo/orange_71.jpg --output_dir=infer_output
特别注意:类似这种在命令提示符下输入时候,一定注意自己输入过程中的出现的多余空格问题:如下图所示,weights=后面出现了一个多的空格,导致模型文件读不到。
6.2 使用一个文件夹中图片进行预测
测试的结果保存在infer_output这个文件夹中:
python -u tools/infer.py -c configs/yolov3_mobilenet_v1_fruit.yml -o weights=output/yolov3_mobilenet_v1_fruit/best_model --infer_img=demo/test --output_dir=infer_output/testout



说明: