PaddleDetection使用详解(包括常见报错及修复方法)

暴才俊
2023-12-01

一、PaddleDetection的安装
前言:PaddleDetection依赖paddlepaddle,需要先安装paddlepaddle
1.从github/gitee获取PaddleDetection完整资源
github

git clone https://github.com/PaddlePaddle/PaddleDetection.git

gitee

git clone https://gitee.com/paddlepaddle/PaddleDetection

2.安装相关依赖
解压后进入PaddleDetection文件夹,在此目录下打开cmd并在cmd中执行

pip install -r requirements.txt

3.检验是否安装完成
PaddleDetection目录下执行

python ppdet/modeling/tests/test_architectures.py

如果安装成功则提示

..........
----------------------------------------------------------------------
Ran 12 tests in 2.480s
OK (skipped=2)

如果出现报错

No module named ‘ppdet‘

找到报错文件ppdet/modeling/tests/test_architectures.py
在文件中添加两行代码

import sys
sys.path.append(r"/home/aistudio/PaddleDetection")#这个路径具体值根据你的项目修改
import ppdet #一定要保证import ppdet在这两行代码后面

二、使用过程详解
PaddleDetection是百度优化过的目标检测框架,包含当前流行的目标检测模型。例如,faster-rnn,yolo系列。
PaddeDetection各文件目录功能详解
使用PaddleDetection的第一步是准备训练数据,目标检测数据集常见格式有COCO格式以及VOC格式。我这里采用了VOC格式。
VOC格式数据包括三个部分,训练图片,训练图片的标签以及图片与标签对应关系描述文件。
对于训练图片,训练图片的标签以及图片与标签对应关系描述文件这三部分应该分别放在三个不同的文件夹下;
目录结构应为:

VOCdevkit
├──VOC2007(或VOC2012)
│   ├── Annotations
│       ├── xxx.xml
│   ├── JPEGImages
│       ├── xxx.jpg
│   ├── ImageSets
│       ├── Main
│           ├── trainval.txt
│           ├── test.txt

Annotations文件存放xml文件,xml文件是对一张图片中标准训练数据的记录,包括矩形框大小(用四个值表示分别是左上角坐标、右下角坐标)、矩形框标签名(给这个矩形框标注的标签),一个xml文件示例如下:

<?xml version="1.0" ?>
<annotation>
<folder>img</folder>
<filename>img0.png</filename>
<path>E:\标准化文本\img\img0.png</path>
<source>
    <database>Unknown</database>
</source>
<size>
    <width>1190</width>
    <height>1684</height>
    <depth>3</depth>
</size>

<segmented>0</segmented>
    <object>
    <name>text</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>//矩形框
        <xmin>68</xmin>
        <ymin>280</ymin>
        <xmax>1084</xmax>
        <ymax>1048</ymax>
    </bndbox>
</object>
    <object>
    <name>title</name>//name就是标签名,其值title表示这个矩形框标签;一个xml文件可以有多个矩形框,表示一张图中标记了多处
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
        <xmin>372</xmin>
        <ymin>176</ymin>
        <xmax>788</xmax>
        <ymax>272</ymax>
    </bndbox>
</object>
</annotation>

JPEGImages文件夹放训练图片;ImageSets集合存放训练图片文件与xml格式标注文件对应关系,ImageSets一个示例为:

VOCdevkit/VOC2012/JPEGImages/img388.png VOCdevkit/VOC2012/Annotations/img388.xml
VOCdevkit/VOC2012/JPEGImages/img152.png VOCdevkit/VOC2012/Annotations/img152.xml
VOCdevkit/VOC2012/JPEGImages/img380.png VOCdevkit/VOC2012/Annotations/img380.xml
VOCdevkit/VOC2012/JPEGImages/img294.png VOCdevkit/VOC2012/Annotations/img294.xml
VOCdevkit/VOC2012/JPEGImages/img281.png VOCdevkit/VOC2012/Annotations/img281.xml

这个对应关系文件有一个写好的python程序直接生成,文件名为create_list.py
使用方法是在PaddleDetection根目录下执行下面命令:

python dataset/voc/create_list.py -d path/to/dataset

但是使用这个程序发现生成效果并不好,主要有1.内容空白,没生成任何内容2.目录分隔斜线错误,这个错误解决简单在记事本中全局将\替换为/
对于错误1.解决方法是打开create_list.py使用下面代码替换原程序

# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
import os.path as osp
import logging
import re
import random
import os

# add python path of PadleDetection to sys.path
parent_path = osp.abspath(osp.join(__file__, *(['..'] * 3)))
if parent_path not in sys.path:
    sys.path.append(parent_path)



logging.basicConfig(level=logging.INFO)

voc_path = osp.split(osp.realpath(sys.argv[0]))[0]
def _get_voc_dir(devkit_dir, year, type):
    return osp.join(devkit_dir, 'VOC' + year, type)

def _walk_voc_dir(devkit_dir, year, output_dir):
    filelist_dir = _get_voc_dir(devkit_dir, year, 'ImageSets/Main')
    annotation_dir = _get_voc_dir(devkit_dir, year, 'Annotations')
    img_dir = _get_voc_dir(devkit_dir, year, 'JPEGImages')
    trainval_list = []
    test_list = []
    added = set()

    for _, _, files in os.walk(filelist_dir):
        for fname in files:
            img_ann_list = []
            if re.match(r'trainval\.txt', fname):
                img_ann_list = trainval_list
            elif re.match(r'test\.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(
                    osp.relpath(annotation_dir, output_dir),
                    name_prefix + '.xml')
                img_path = osp.join(
                    osp.relpath(img_dir, output_dir), name_prefix + '.png')
                img_ann_list.append((img_path, ann_path))

    return trainval_list, test_list

def create_list(devkit_dir, years, output_dir):
    """
    create following list:
        1. trainval.txt
        2. test.txt
    """
    trainval_list = []
    test_list = []
    for year in years:
        trainval, test = _walk_voc_dir(devkit_dir, year, output_dir)
        trainval_list.extend(trainval)
        test_list.extend(test)

    random.shuffle(trainval_list)
    with open(osp.join(output_dir, 'trainval.txt'), 'w') as ftrainval:
        for item in trainval_list:
            ftrainval.write(item[0] + ' ' + item[1] + '\n')

    with open(osp.join(output_dir, 'test.txt'), 'w') as fval:
        ct = 0
        for item in test_list:
            ct += 1
            fval.write(item[0] + ' ' + item[1] + '\n')
def create_voc_list(data_dir, devkit_subdir='VOCdevkit'):
    devkit_dir = osp.join(data_dir, devkit_subdir)
    years = ['2007', '2012']
    print(devkit_dir)
    # NOTE: since using auto download VOC
    # dataset, VOC default label list should be used, 
    # do not generate label_list.txt here. For default
    # label, see ../data/source/voc.py
    create_list(devkit_dir, years, data_dir)
   
create_voc_list(voc_path)

运行完create_list.py后训练集和测试集就生成好了,接下来开始训练。因为我的电脑配置不高,这里我采用Ai Studio云训练平台训练模型。
在Ai studio搭建环境与本地搭建是一样的,但是Ai Studio可能有如下几处报错
1.执行python ppdet/modeling/tests/test_architectures.py时报错: No module named ‘ppdet‘
解决方法:
找到报错文件ppdet/modeling/tests/test_architectures.py
在文件中添加两行代码

import sys
sys.path.append(r"/home/aistudio/PaddleDetection")

2.No module named ‘lap‘
解决方案:
1、官网下载lap压缩包
官网地址:地址

2、解压

3、在解压后的目录下cmd命令行
运行

python setup.py build
python setup.py install

接下来在PaddleDetection根目录执行

python -u tools/train.py -c configs/ppyolo/ppyolov2_r50vd_dcn_voc.yml 

即可开始训练。
但是在这里要详细讲解下ppyolov2_r50vd_dcn_voc.yml 文件是干什么用的。
yml文件本质上就是文本文件,记录了训练模型所需的配置,包括使用的模型、数据集地址、batch_size、backbone等等信息。这里以ppyolov2_r50vd_dcn_voc.yml为例讲解PaddleDetection训练配置

_BASE_: [//_BASE是一个数组,记录了所依赖的其他基础配置
  '../datasets/voc.yml',
  '../runtime.yml',
  './_base_/ppyolov2_r50vd_dcn.yml',
  './_base_/optimizer_365e.yml',
  './_base_/ppyolov2_reader.yml',
]

snapshot_epoch: 83
weights: output/ppyolov2_r50vd_dcn_voc/model_final

TrainReader:
  mixup_epoch: 350
  batch_size: 12//一批包含多少数据,如果显存爆炸可以调低batch_size

# set collate_batch to false because ground-truth info is needed
# on voc dataset and should not collate data in batch when batch size
# is larger than 1.
EvalReader:
  collate_batch: false

epoch: 583//训练轮数

LearningRate://学习率相关配置
  base_lr: 0.00333
  schedulers:
  - !PiecewiseDecay
    gamma: 0.1
    milestones:
    - 466
    - 516
  - !LinearWarmup
    start_factor: 0.
    steps: 4000

OptimizerBuilder://优化器相关配置
  optimizer:
    momentum: 0.9
    type: Momentum
  regularizer:
    factor: 0.0005
    type: L2

特殊yml文件——runtime.yml功能说明记录了训练好的模型保存路径;是否使用GPU等·信息
更多细节请直接看PaddleDetection项目源码,包括train.py、infer.py或者网络架构部分都可以通过源码学习

 类似资料: