PaddleDetection代码分析和训练数据集(1)

2021SC@SDUSC

paddledetection作为国内出名的应用于目标检测框架,想要搞明白并不是一件非常容易的事,在分析代码之前,要首先知道如何使用它

举个例子 我们现在有一份数据集 我们需要训练这份数据集 该怎么办呢

方法如下:

1.转换格式 将这份数据集的格式转换成我们的PaddleDetection可以操作的格式,比如COCO或VOC数据集格式

如果需要转化的数据集格式是labelme或者cityscape的 一般使用x2coco.py(在tools目录下)来转化成coco格式

问题1:如何判断自己得到数据集格式?

labelme数据集


打开预先准备好的数据集,如果文件目录为 

 这就是labelme格式的数据集 其中image放的原始图片 label放的二值化灰度图(举个例子)

image的png图                           

对应的label

 cityscape数据集 

  对应目录  里面内容不再赘述 小白如果不知道可以去搜索

 

 问题2:如何开始转换?

找到x2coco.py所在路径 在此处资源管理器执行cmd

 执行以下命令

python ./ppdet/data/tools/x2coco.py \
                --dataset_type labelme \
                --json_input_dir ./labelme_annos/ \
                --image_input_dir ./labelme_imgs/ \
                --output_dir ./cocome/ \
                --train_proportion 0.8 \
                --val_proportion 0.2 \
                --test_proportion 0.0 \

--dataset_type:需要转换的数据格式,目前支持:'labelme'和'cityscape'
--json_input_dir:使用labelme标注的json文件所在文件夹
--image_input_dir:图像文件所在文件夹
--output_dir:转换后的COCO格式数据集存放位置
--train_proportion:标注数据中用于train的比例
--val_proportion:标注数据中用于validation的比例
--test_proportion:标注数据中用于infer的比例
此处参考大佬

VOC数据集所必须的文件内容如下所示,数据集根目录需有VOCdevkit/VOC2007或VOCdevkit/VOC2012文件夹,该文件夹中需有Annotations,JPEGImages和ImageSets/Main三个子目录,Annotations存放图片标注的xml文件,JPEGImages存放数据集图片,ImageSets/Main存放训练trainval.txt和测试test.txt列表。

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

执行以下脚本,将根据ImageSets/Main目录下的trainval.txt和test.txt文件在数据集根目录生成最终的trainval.txt和test.txt列表文件:

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


2.选择模型

根据需求选择一个合适的模型

PaddleDetection中提供了丰富的模型库,具体可在模型库中查看各个模型的指标,您可依据实际部署算力的情况,选择合适的模型:

算力资源小时,推荐您使用移动端模型,PaddleDetection中的移动端模型经过迭代优化,具有较高性价比。
算力资源强大时,推荐您使用服务器端模型,该模型是PaddleDetection提出的面向服务器端实用的目标检测方案。
同时也可以根据使用场景不同选择合适的模型:

当小物体检测时,推荐您使用两阶段检测模型,比如Faster RCNN系列模型,具体可在模型库中找到。
当在交通领域使用,如行人,车辆检测时,推荐您使用特色垂类检测模型。
当在竞赛中使用,推荐您使用竞赛冠军模型CACascadeRCNN与OIDV5_BASELINE_MODEL。
当在人脸检测中使用,推荐您使用人脸检测模型。
同时也可以尝试PaddleDetection中开发的YOLOv3增强模型、YOLOv4模型与Anchor Free模型等。
 

剩下两个步骤在我的下一篇博客中 此处开始分析已经看的源码

因为我负责分析的是特色垂类检测模型

包含的车辆检测和行人检测是使用了YOLOv3算法的 因此在此分析此算法部分源码

常用的eval分析

1def yolo_eval(yolo_outputs,      #模型输出,格式如下【(?,13,13,255)(?,26,26,255)(?,52,52,255)】 ?:bitch size; 13-26-52:多尺度预测; 255:预测值(3*(80+5))
              anchors,            #[(10,13), (16,30), (33,23), (30,61), (62,45), (59,119), (116,90), (156,198),(373,326)]
              num_classes,     # 类别个数,coco集80类
              image_shape,        #placeholder类型的TF参数,默认(416, 416);
              max_boxes=20,       #每张图每类最多检测到20个框同类别框的IoU阈值,大于阈值的重叠框被删除,重叠物体较多,则调高阈值,重叠物体较少,则调低阈值
              score_threshold=.6, #框置信度阈值,小于阈值的框被删除,需要的框较多,则调低阈值,需要的框较少,则调高阈值;
              iou_threshold=.5):  #同类别框的IoU阈值,大于阈值的重叠框被删除,重叠物体较多,则调高阈值,重叠物体较少,则调低阈值
 
    """Evaluate YOLO model on given input and return filtered boxes."""
 
    num_layers = len(yolo_outputs)   #yolo的输出层数;num_layers = 3  -> 13-26-52
 
    anchor_mask = [[6,7,8], [3,4,5], [0,1,2]] if num_layers==3 else [[3,4,5], [1,2,3]]
  # default setting  #每层分配3个anchor box.如13*13分配到【6,7,8】即【(116,90)(156,198)(373,326)】
 
    input_shape = K.shape(yolo_outputs[0])[1:3] * 32   
  #输入shape(?,13,13,255);即第一维和第二维分别*32  ->13*32=416; input_shape:(416,416)
 
    boxes = []
    box_scores = []
    for l in range(num_layers):
        _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
            anchors[anchor_mask[l]], num_classes, input_shape, image_shape)
        boxes.append(_boxes)
        box_scores.append(_box_scores)
    boxes = K.concatenate(boxes, axis=0)    #K.concatenate:将数据展平 ->(?,4)
    box_scores = K.concatenate(box_scores, axis=0)   # ->(?,)
 
    mask = box_scores >= score_threshold  #MASK掩码,过滤小于score阈值的值,只保留大于阈值的值
    max_boxes_tensor = K.constant(max_boxes, dtype='int32')   #最大检测框数20
    boxes_ = []
    scores_ = []
    classes_ = []
    for c in range(num_classes):
        # TODO: use keras backend instead of tf.
        class_boxes = tf.boolean_mask(boxes, mask[:, c])    #通过掩码MASK和类别C筛选框boxes
        class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])    #通过掩码MASK和类别C筛选scores
        nms_index = tf.image.non_max_suppression(        #运行非极大抑制
            class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)
        class_boxes = K.gather(class_boxes, nms_index)     #K.gather:根据索引nms_index选择class_boxes
        class_box_scores = K.gather(class_box_scores, nms_index)   #根据索引nms_index选择class_box_score)
        classes = K.ones_like(class_box_scores, 'int32') * c    #计算类的框得分
        boxes_.append(class_boxes)
        scores_.append(class_box_scores)
        classes_.append(classes)
 
    boxes_ = K.concatenate(boxes_, axis=0)    
   #K.concatenate().将相同维度的数据连接在一起;把boxes_展平。  -> 变成格式:(?,4);  ?:框的个数;4:(x,y,w,h)
 
    scores_ = K.concatenate(scores_, axis=0)   #变成格式(?,)
    classes_ = K.concatenate(classes_, axis=0) #变成格式(?,)
 
    return boxes_, scores_, classes_

以上是示例分析,接下来的博客会进行更加系统的分析


版权声明:本文为tegddhdrhdd原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。