零.写在最前

该项目源于《百度网盘AI大赛——表格检测

基于飞桨目标检测开发套件PaddleDetection进行快速微调和预测,生成比赛结果文件

通过对数据集图片的观察,发现大多图片都带旋转,因此此项目尝试用旋转框检测(PP-YOLOE-R)解决问题

一.安装PaddleDetection

PP-YOLOE-R是一个高效的单阶段Anchor-free旋转框检测模型。基于PP-YOLOE, PP-YOLOE-R以极少的参数量和计算量为代价,引入了一系列有用的设计来提升检测精度。在DOTA 1.0数据集上,PP-YOLOE-R-l和PP-YOLOE-R-x在单尺度训练和测试的情况下分别达到了78.14和78.27 mAP,这超越了几乎所有的旋转框检测模型。通过多尺度训练和测试,PP-YOLOE-R-l和PP-YOLOE-R-x的检测精度进一步提升至80.02和80.73 mAP。在这种情况下,PP-YOLOE-R-x超越了所有的anchor-free方法并且和最先进的anchor-based的两阶段模型精度几乎相当。此外,PP-YOLOE-R-s和PP-YOLOE-R-m通过多尺度训练和测试可以达到79.42和79.71 mAP。考虑到这两个模型的参数量和计算量,其性能也非常卓越。在保持高精度的同时,PP-YOLOE-R避免使用特殊的算子,例如Deformable Convolution或Rotated RoI Align,以使其能轻松地部署在多种多样的硬件上。在1024x1024的输入分辨率下,PP-YOLOE-R-s/m/l/x在RTX 2080 Ti上使用TensorRT FP16分别能达到69.8/55.1/48.3/37.1 FPS,在Tesla V100上分别能达到114.5/86.8/69.7/50.7 FPS。

# 首先克隆PaddleDetection并切换到Develop分支
%cd /home/aistudio/work

!unzip -o PaddleDetection.zip

%cd /home/aistudio/work/PaddleDetection

#安装PaddleDetection依赖
!pip install -r requirements.txt

#编译旋转框自定义外部算子
!cd ppdet/ext_op && python setup.py install
!python ppdet/ext_op/unittest/test_matched_rbox_iou.py

二.数据预处理

将数据集生成为符合PaddleDetection的格式,这里是COCO格式

格式如下:

# 切换到数据集目录
%cd /home/aistudio/data/data182849/

# 解压训练集和测试集A
!unzip -o train.zip

!unzip -o testA.zip
# 切换工作目录,生成COCO格式数据集
%cd /home/aistudio/work/

!python pre.py
# 数据预处理代码

import random
import json
import cv2
import os
class Pre(object):
    def __init__(self):
        self.categorys = [
            {
                'id':1,
                'name':'all',
                'supercategory':'none'
            }
        ]
        self.trainDataRatio = 0.8
        self.dataPath = "/home/aistudio/data/data182849/train/"

    def labels(self, indexs, contents):
        images = []
        image_id = 1
        annos =[]
        anno_id = 1
        for key in indexs:
            print('image',image_id, key)
            img = cv2.imread(self.dataPath+"imgs/"+key)
            width = img.shape[1]
            height = img.shape[0]
            item = {
                'id':image_id,
                'file_name':key,
                'height':height,
                'width':width
            }
            images.append(item)
            image_id += 1


        for image in images:
            for item in contents[image['file_name']]:
                print('annos',anno_id, image['file_name'])
                x1, y1 = item['lb'][0], item['lb'][1]
                x2, y2 = item['lt'][0], item['lt'][1]
                x3, y3 = item['rt'][0], item['rt'][1]
                x4, y4 = item['rb'][0], item['rb'][1]

                xmin, ymin, xmax, ymax = item['box'][0], item['box'][1], item['box'][2], item['box'][3]

                anno = {
                    'id':anno_id,
                    'category_id':1,
                    'area':(xmax-xmin)*(ymax-ymin),
                    'bbox':[xmin, ymin, xmax-xmin, ymax-ymin],
                    'image_id':image['id'],
                    'ignore':0,
                    'iscrowd':0,
                    'segmentation':[[x1, y1, x2, y2, x3, y3, x4, y4]]}
                annos.append(anno)
                anno_id += 1

        content = {
            'annotations':annos,
            'categories':self.categorys,
            'images':images,
            'info':"info"
        }
        return content

    def run(self):
        print('start run')
        alls = []
        # 读取annos.txt 文件
        annosFile = open(self.dataPath+'annos.txt', 'r')
        contents = annosFile.read()
        contents = json.loads(contents)

        if not os.path.exists(self.dataPath+'annotations'):
            os.makedirs(self.dataPath+'annotations')
        
        # 切分训练集和验证集
        for key, value in contents.items():
            alls.append(key)

        trainNums = int(len(alls)*self.trainDataRatio)
        trainIndexs = random.sample(alls, trainNums)
        vaildIndexs = list(set(alls) ^ set(trainIndexs))

        trainLabels = self.labels(trainIndexs, contents)
        vaildLabels = self.labels(vaildIndexs, contents)

        # 生成train.json和valid.json
        with open(self.dataPath+'train.json', 'w') as f:
            json.dump(trainLabels,f)

        with open(self.dataPath+'valid.json', 'w') as f:
            json.dump(vaildLabels,f)
        
        
# preObj = Pre()
# preObj.run()

三.训练

训练需要配置文件。

1.入口配置文件:

/home/aistudio/work/PaddleDetection/configs/rotate/ppyoloe_r/mine.yml

_BASE_: [
  '../../datasets/coco_mine.yml',
  '../../runtime.yml',
  '_mine_/optimizer_3x.yml',
  '_mine_/ppyoloe_r_reader.yml',
  '_mine_/ppyoloe_r_crn.yml'
]

log_iter: 50
snapshot_epoch: 1
weights: output/mine/model_final

pretrain_weights: https://paddledet.bj.bcebos.com/models/pretrained/CSPResNetb_m_pretrained.pdparams
depth_mult: 0.67
width_mult: 0.75

coco_mine.yml 主要说明了训练数据和验证数据的路径

runtime.yml 主要说明了公共的运行参数,比如说是否使用GPU、每多少个epoch存储checkpoint等

optimizer_3x.yml 主要说明了学习率和优化器的配置。

ppyoloe_r_crn.yml 主要说明模型、和主干网络的情况。

ppyoloe_r_reader.yml 主要说明数据读取器配置,如batch size,并发加载子进程数等,同时包含读取后预处理操作,如resize、数据增强等等

# 单卡GPU 训练
%cd /home/aistudio/work/PaddleDetection/

!export CUDA_VISIBLE_DEVICES=0

# 训练,--eval 边训练边评估
!python tools/train.py -c configs/rotate/ppyoloe_r/mine.yml --use_vdl=true --vdl_log_dir=vdl_dir/scalar --eval -o LearningRate.base_lr=0.002
# 恢复性训练
%cd /home/aistudio/work/PaddleDetection/

!export CUDA_VISIBLE_DEVICES=0

!python tools/train.py -c configs/rotate/ppyoloe_r/mine.yml -r output/mine/best_model --use_vdl=true --vdl_log_dir=vdl_dir/scalar --eval -o LearningRate.base_lr=0.001

模型参数保存在:output/mine 目录下

通过vdl_dir 查看可视化数据

四.评估模型

可以在output/mine 目录下指定某个epoch的参数,或者直接用最终的参数,或者指定最优权重

%cd /home/aistudio/work/PaddleDetection/
!python tools/eval.py -c configs/rotate/ppyoloe_r/mine.yml -o weights=/home/aistudio/work/PaddleDetection/output/mine/best_model.pdparams

分别评估了mAP(0.5) = 90% , mAP(0.7) = 81%, 和mAP(0.9) = 36%



五.导出模型

# 模型导出
%cd /home/aistudio/work/PaddleDetection/
!python tools/export_model.py -c configs/rotate/ppyoloe_r/mine.yml --output_dir=/home/aistudio/work/model \
 -o weights=output/mine/best_model

导出的静态图在 work/model 目录下

打开infer_cfg.yml 查看模型的配置

六.预测

# 预测部署
%cd /home/aistudio/work/PaddleDetection/
!python deploy/python/infer.py \
    --model_dir=/home/aistudio/work/model/mine \
    --image_dir=/home/aistudio/data/data182849/pubtest/imgs \
    --device=GPU \
    --threshold=0.1 \
    --run_mode=paddle \
    --output_dir=/home/aistudio/work/output_dir\

结果保存在output_dir目录下

目录下有生成的绘框图片,和结果文件bbox.json

查看其中一两张图片看看效果

六.生成比赛结果

预测文件predict.py, 数据输入数据通infer.py 格式保持一致,最终生成的文件效果保存在output_dir_predict 目录

# 预测
%cd /home/aistudio/work
!python  predict.py /home/aistudio/data/data182849/pubtest/imgs /home/aistudio/work/output_dir_predict

查看下几张图片的生成结果

# 打包
%cd /home/aistudio/work
!zip -r result.zip  predict.py preprocess.py keypoint_preprocess.py  model

7.总结

通过PaddleDetection可以快速实现检测目标任务

优化方向

1.本项目用的是pp-yoloe-r模型, 可以尝试下用ppyoloe 系列其他模型,看下是否有更好的效果

2.诸如学习率,数据增强等参数还有调优的可能

此文章为搬运
原项目链接

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐