PaddleDetecion——红绿灯检测:PaddleDetection-SSD_Mobilenet-VOCdataset

最近在做智能车人工智能组的线上赛,赛题分为两个:一个是人流密度检测,另一个是红绿灯识别,我在小队中的任务是做第二部分,红绿灯识别。一开始的时候建立模型的时选用的是SSD_Mobilenet_v1模型,权重也是预训练好的默认权重,我们只需要直接在预训练的基础上训练自己的数据集,得到新的权重,然后用该权重进行预测即可。

PaddleDetection数据集准备

本项目所用数据集为VOC格式,所需要的原材料为:jpg+xml。
构建方法参考我的文章:PaddleDetection——使用(jpg + xml)制作VOC数据集并建立PD包

基于PaddleDetction模型的运行配置

项目准备

  • 在Ai Studio上创建自己的项目或者fork我的项目:PD-SSD-Smart-car model(等我智能车比完赛会公开~目前为私密)
  • 上传自己的数据集
  • 准备PaddleDetection环境(建议直接作为数据集的方式上传,方便快捷,对于新手来说出现bug的几率小,而且不用在进入项目后再下载等待)文件我已经上传到资源里了,可以自行下载(PaddleDetection完整环境压缩包,本文将直接使用PaddleDetection完整环境压缩包)
  • 注意:请用GPU环境进行运行!要不然会无法运行,因为默认是GPU,而且CPU环境训练进程极容易被killed,因为内存溢出。

基于AI Studio的PaddleDetction基础运行操作

解压数据集和环境资源
#根据自己的目录解压包含制作好的数据集'PaddleDetection完整环境压缩包'
%cd /home/aistudio/
!unzip data/data44932/PD_o_limit.zip
配置环境变量
#根据自己的路径选择PaddleDection配置python环境变量
%env PYTHONPATH=/home/aistudio/PaddleDetection-release-0.2
开始训练
%cd /home/aistudio/PaddleDetection-release-0.2
#执行train.py,开始训练,更多参数请查看train.py文件,并在末尾进行个性化设置
!python -u tools/train.py -c configs/ssd/ssd_mobilenet_v1_voc.yml --use_tb=True --eval 
导出模型

其实这步不做也可以,因为在train,py执行的时候,会默认将模型的权重导出到output_dir,这个可以在训练过程的报告中找到。

#导出模型
!python -u tools/export_model.py -c configs/ssd/ssd_mobilenet_v1_voc.yml
评估模型

其实和上一步一样,不做可以,因为在train,py执行的时候,每次迭代到一定数量后,会自动进行评估操作,这个也可以在训练过程的报告中找到。

#评估模型

!python -u tools/eval.py -c configs/ssd/ssd_mobilenet_v1_voc.yml 
模型预测
#执行infer.py,开始训练,更多参数请查看infer.py文件,并在末尾进行个性化设置
!python -u tools/infer.py -c configs/ssd/ssd_mobilenet_v1_voc.yml --infer_dir dataset/voc/VOCdevkit --output_dir output/test_result 

高级配置

自定义数据集

在configs文件夹中找到所用模型的yml文件:ssd_mobilenet_v1_voc.yml,可以根据自己的需求进行相应的调整。
配置自定义数据集时在uml文件中找到TrainReader、EvalReader和TestReader下的dataset中的anno_path、dataset_dir,根据自己的VOC数据集的路径进行配置,注意:如果对相对路径使用不熟练,建议最好使用绝对路径!绝对路径肯定不会错;如果在不会用相对路径的情况下,强行使用相对路径,会导致很多路径相关的bug,带来很多不必要的麻烦。
可调参数:

  • 学习率、批数量等超参数
  • 在reader中的数据增强等参数

具体参数调节参考文档:PaddleDetcion高级使用教程-数据处理模块

architecture: SSD
pretrain_weights: https://paddlemodels.bj.bcebos.com/object_detection/ssd_mobilenet_v1_coco_pretrained.tar
use_gpu: true
max_iters: 28000
snapshot_iter: 2000
log_smooth_window: 1
metric: VOC
map_type: 11point
save_dir: output
weights: output/ssd_mobilenet_v1_voc/model_final
# 2(label_class) + 1(background)
num_classes: 21

SSD:
  backbone: MobileNet
  multi_box_head: MultiBoxHead
  output_decoder:
    background_label: 0
    keep_top_k: 200
    nms_eta: 1.0
    nms_threshold: 0.45
    nms_top_k: 400
    score_threshold: 0.01
#超参数调节
MobileNet:
  norm_decay: 0.
  conv_group_scale: 1
  conv_learning_rate: 0.1
  extra_block_filters: [[256, 512], [128, 256], [128, 256], [64, 128]]
  with_extra_blocks: true

MultiBoxHead:
  aspect_ratios: [[2.], [2., 3.], [2., 3.], [2., 3.], [2., 3.], [2., 3.]]
  base_size: 300
  flip: true
  max_ratio: 90
  max_sizes: [[], 150.0, 195.0, 240.0, 285.0, 300.0]
  min_ratio: 20
  min_sizes: [60.0, 105.0, 150.0, 195.0, 240.0, 285.0]
  offset: 0.5
#学习率
LearningRate:
  schedulers:
  - !PiecewiseDecay
    milestones: [10000, 15000, 20000, 25000]
    values: [0.001, 0.0005, 0.00025, 0.0001, 0.00001]
#优化器
OptimizerBuilder:
  optimizer:
    momentum: 0.0
    type: RMSPropOptimizer
  regularizer:
    factor: 0.00005
    type: L2


    ##训练-数据处理模块的名称统一为TrainReader;
    ##PaddleDetection的yml配置文件中,使用!直接序列化模块实例(可以是函数、类等);
    #dataset下需要序列化数据源实例,如COCODataSet、VOCDataSe和自定义的XXXDataSet;
    #inputs_def的具体定义与使用请参考模型技术文档
    #Reader的参数可选择性配置,如未在yml配置文件中定义,则会选取各参数在源码中的默认值。

TrainReader:
  inputs_def:
    image_shape: [3, 300, 300]
    fields: ['image', 'gt_bbox', 'gt_class']
  dataset:
    !VOCDataSet
    #anno_path: trainval.txt
    anno_path: /home/aistudio/PaddleDetection-release-0.2/dataset/voc/trainval.txt
    dataset_dir: /home/aistudio/PaddleDetection-release-0.2/dataset/voc
    #如果是用自己的数据集,要把默认的标签改成false
    use_default_label: false
  #使用各种单图像数据增强算子的列表,文档地址:https://paddledetection.readthedocs.io/advanced_tutorials/READER.html#%E6%95%B0%E6%8D%AE%E5%A2%9E%E5%BC%BA%E7%AE%97%E5%AD%90
  sample_transforms:
  - !DecodeImage
    #从图像文件或内存buffer中加载图像,格式为BGR、HWC格式,如果设置to_rgb=True,则转换为RGB格式。
    to_rgb: true
  - !RandomDistort
    #随机扰动图片亮度、对比度、饱和度和色相
    brightness_lower: 0.875
    brightness_upper: 1.125
    is_order: true
  - !RandomExpand
    #原理同ExpandImage,以随机比例与角度对图像进行裁剪、缩放和翻转
    fill_value: [127.5, 127.5, 127.5]
  - !RandomCrop
    #原理同CropImage,以随机比例与IoU阈值进行处理
    allow_no_crop: false
  - !NormalizeBox {}
  - !ResizeImage
    #根据特定的插值方式调整图像大小
    interp: 1
    target_size: 300
    use_cv2: false
  - !RandomFlipImage
    #随机水平翻转图像
    is_normalized: true
  - !Permute {}#对图像的通道进行排列并转为BGR格式。假如输入是HWC顺序,通道C上是RGB格式,设置channel_first=True,将变成CHW,设置to_bgr=True,通道C上变成BGR格式。
  - !NormalizeImage
    #对图像像素值进行归一化,如果设置is_scale=True,则先将像素值除以255.0,像素值缩放到到[0-1]区间。
    is_scale: false
    mean: [127.5, 127.5, 127.5]
    std: [127.502231, 127.502231, 127.502231]
  #批数据大小(图像个数/batch)
  batch_size: 32
  #是否随机打乱数据集中图像排序,默认False
  shuffle: true
  #是否删除最后一个batch的数据,默认False
  drop_last: true
  #数据读取中使用多进程的数量
  worker_num: 8
  #多进程/多线程缓冲队列的大小,队列中每个元素为一个batch的数据
  bufsize: 16
  #数据读取中是否使用多进程
  use_process: true


    #评估-数据处理模块的名称统一为EvalReader;
    #在评估配置中,数据增强需要去除各种含有随机操作的数据处理算子与操作。

EvalReader:
  inputs_def:
    image_shape: [3, 300, 300]
    fields: ['image', 'gt_bbox', 'gt_class', 'im_shape', 'im_id', 'is_difficult']
  dataset:
    !VOCDataSet
    anno_path: /home/aistudio/PaddleDetection-release-0.2/dataset/voc/test.txt
    dataset_dir: /home/aistudio/PaddleDetection-release-0.2/dataset/voc
    #如果是用自己的数据集,要把默认的标签改成false
    use_default_label: false
  sample_transforms:
  - !DecodeImage
    to_rgb: true
  - !NormalizeBox {}
  - !ResizeImage
    interp: 1
    target_size: 300
    use_cv2: false
  - !Permute {}
  - !NormalizeImage
    is_scale: false
    mean: [127.5, 127.5, 127.5]
    std: [127.502231, 127.502231, 127.502231]
  batch_size: 32
  worker_num: 8
  bufsize: 32
  use_process: True


    #推理-数据处理模块的名称统一为TestReader;
    #在推理配置中dataset的数据源一般都设置为ImageFolder数据源。ImageFolder可以指定图片的文件夹地址,将读取该文件夹下的所有图片。

TestReader:
  inputs_def:
    image_shape: [3,300,300]
    fields: ['image', 'im_id', 'im_shape']
  dataset:
    !ImageFolder
    anno_path: /home/aistudio/PaddleDetection-release-0.2/dataset/voc/anno.txt
    #如果是用自己的数据集,要把默认的标签改成false
    use_default_label: false
  sample_transforms:
  - !DecodeImage
    to_rgb: true
  - !ResizeImage
    interp: 1
    max_size: 0
    target_size: 300
    use_cv2: false
  - !Permute {}
  - !NormalizeImage
    is_scale: false
    mean: [127.5, 127.5, 127.5]
    std: [127.502231, 127.502231, 127.502231]
  batch_size: 1
自定义训练扩展功能

在train.py中自定义扩展功能:
具体参数调节参考官方文档:PaddleDetcion高级使用教程-数据处理模块

#可添加的功能后缀,可以直接更改default即可
if __name__ == '__main__':
    parser = ArgsParser()
    parser.add_argument(
        "-r",
        "--resume_checkpoint",
        default=None,
        type=str,
        help="Checkpoint path for resuming training.")
    parser.add_argument(
        "--fp16",
        action='store_true',
        default=False,
        help="Enable mixed precision training.")
    parser.add_argument(
        "--loss_scale",
        default=8.,
        type=float,
        help="Mixed precision training loss scale.")
    parser.add_argument(
        "--eval",
        action='store_true',
        default=True,
        help="Whether to perform evaluation in train")
    parser.add_argument(
        "--output_eval",
        default=None,
        type=str,
        help="Evaluation directory, default is current directory.")
    parser.add_argument(
        "--use_tb",
        type=bool,
        default=True,
        help="whether to record the data to Tensorboard.")
    parser.add_argument(
        '--tb_log_dir',
        type=str,
        default="tb_log_dir/scalar",
        help='Tensorboard logging directory for scalar.')
    FLAGS = parser.parse_args()
    main()

如果读者觉得好,跟着博主做出了项目,不要忘了点个赞哦~

  • 20
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
优化该代码class Path(object): def __init__(self,path,cost1,cost2): self.__path = path self.__cost1 = cost1 self.__cost2 = cost2 #路径上最后一个节点 def getLastNode(self): return self.__path[-1] #获取路径路径 @property def path(self): return self.__path #判断node是否为路径上最后一个节点 def isLastNode(self, node): return node == self.getLastNode() #增加加点和成本产生一个新的path对象 def addNode(self, node, price1,price2): return Path(self.__path+[node],self.__cost1+ price1,self.__cost2+ price2) #输出当前路径 def printPath(self): global num #将num作为循环次数,即红绿灯数量 global distance num = 0 for n in self.__path: if self.isLastNode(node=n): print(n) else: print(n, end="->") num += 1 print("全程约为 {:.4}公里".format(str(self.__cost1))) print("时间大约为 {}分钟".format(str(self.__cost2))) print("需要经过{}个红绿灯".format(num)) distance = self.__cost1 #获取路径总成本的只读属性 @property def travelCost1(self): return self.__cost1 @property def travelCost2(self): return self.__cost2 class DirectedGraph(object): def __init__(self, d): if isinstance(d, dict): self.__graph = d else: self.__graph = dict() print('Sth error') def __generatePath(self, graph, path, end, results): #current = path[-1] current = path.getLastNode() if current == end: results.append(path) else: for n in graph[current]: #if n not in path: if n not in path.path: #self.__generatePath(graph, path + [n], end, results) self.__generatePath(graph, path.addNode(n,self.__graph[path.getLastNode()][n][0],self.__graph[path.getLastNode()][n][1]),end, results) #self.__generatePath(graph,使其能够保存输入记录并且能够查询和显示
06-13
可以考虑以下优化: 1. 在 `Path` 类中,可以将 `getLastNode()` 方法改为直接返回 `self.__path[-1]`,因为这个方法只被 `addNode()` 方法调用,而 `addNode()` 方法中也可以直接使用 `self.__path[-1]`。 2. 在 `Path` 类中,可以将 `isLastNode()` 方法改为直接比较 `node` 和 `self.__path[-1]`,因为这个方法只被 `printPath()` 方法调用,而 `printPath()` 方法中也可以直接比较。 3. 在 `Path` 类中,可以将 `printPath()` 方法中的 `global` 声明去掉,因为在该方法中没有使用到任何全局变量。 4. 在 `Path` 类中,可以将 `distance` 变量改为实例变量,即在 `__init__()` 方法中初始化为 0,并在 `printPath()` 方法中使用 `self.__cost1` 赋值。 5. 在 `DirectedGraph` 类中,可以将 `__graph` 变量改为实例变量,即在 `__init__()` 方法中初始化为空字典,并在需要使用时直接使用 `self.__graph`。 下面是修改后的代码: ``` class Path(object): def __init__(self, path, cost1, cost2): self.__path = path self.__cost1 = cost1 self.__cost2 = cost2 self.__distance = 0 # 路径总长度,初始为 0 @property def path(self): return self.__path def getLastNode(self): return self.__path[-1] def isLastNode(self, node): return node == self.__path[-1] def addNode(self, node, price1, price2): return Path(self.__path + [node], self.__cost1 + price1, self.__cost2 + price2) def printPath(self): num = 0 for n in self.__path: if self.isLastNode(n): print(n) else: print(n, end="->") num += 1 print("全程约为 {:.4}公里".format(str(self.__cost1))) print("时间大约为 {}分钟".format(str(self.__cost2))) print("需要经过{}个红绿灯".format(num)) self.__distance = self.__cost1 @property def travelCost1(self): return self.__cost1 @property def travelCost2(self): return self.__cost2 class DirectedGraph(object): def __init__(self, d): if isinstance(d, dict): self.__graph = d else: self.__graph = dict() print('Sth error') def __generatePath(self, graph, path, end, results): current = path.getLastNode() if current == end: results.append(path) else: for n in graph[current]: if n not in path.path: results = self.__generatePath(graph, path.addNode(n, graph[path.getLastNode()][n][0], graph[path.getLastNode()][n][1]), end, results) return results ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值