目录
目录README.md

基于mindspore的口罩识别项目

=======

Contents

YOLOv5 Description

YOLOv5于2020年4月发布,在COCO数据集上实现了最先进的目标检测性能。这是YoloV3的一个重要改进,主干中新架构的实施和颈部的修改使mAP(平均平均精度)提高了10%,FPS(每秒帧数)提高了12%。

code

Model Architecture

YOLOv5网络主要由作为主干的CSP和Focus、空间金字塔池(SPP)附加模块、PANet路径聚合颈部和YOLOv 3头部组成。CSP是一种新型的主干,可以增强CNN的学习能力。在CSP上添加空间金字塔池块,以增加感受野并分离出最重要的上下文特征。与YOLOv3中用于目标检测的特征金字塔网络(FPN)不同,PANet被用作不同检测器级别的参数聚合方法。更具体地说,CSPDarknet53包含5个CSP模块,它们使用卷积C,内核大小k=3x3,步长s=2x2;在PANet和SPP中,应用**1x1、5x5、9x9、13x13最大池。

Dataset

Dataset used: 数据集

数据集由小组成员自行制作和标注。

Quick Start

通过官方网站安装MindSpore后,您可以按照以下步骤开始训练和评估:

#run training example(1p) on Ascend/GPU by python command
python train.py \
    --device_target="Ascend" \ # Ascend or GPU
    --data_dir=xxx/dataset \
    --is_distributed=0 \
    --yolov5_version='yolov5s' \
    --lr=0.01 \
    --max_epoch=320 \
    --warmup_epochs=4 > log.txt 2>&1 &
# run 1p by shell script, please change `device_target` in config file to run on Ascend/GPU, and change `T_max`, `max_epoch`, `warmup_epochs` refer to contents of notes
bash run_standalone_train.sh [DATASET_PATH]

# For Ascend device, distributed training example(8p) by shell script
bash run_distribute_train.sh [DATASET_PATH] [RANK_TABLE_FILE]

# For GPU device, distributed training example(8p) by shell script
bash run_distribute_train_gpu.sh [DATASET_PATH] [RANK_SIZE]
# run evaluation on Ascend/GPU by python command
python eval.py \
    --device_target="Ascend" \ # Ascend or GPU
    --data_dir=xxx/dataset \
    --yolov5_version='yolov5s' \
    --pretrained="***/*.ckpt" \
    --eval_shape=640 > log.txt 2>&1 &
# run evaluation by shell script, please change `device_target` in config file to run on Ascend/GPU
bash run_eval.sh [DATASET_PATH] [CHECKPOINT_PATH]

请注意default_config。yaml是8p上yolov5s的默认参数。Ascend和GPU上的batchsize和lr不同,请参阅scripts/run_distribute_train中的设置。sh或scripts/run_distribute_train_gpUsh。

Script Description

Script and Sample Code

├── mindspore
    ├── README.md                              // descriptions about all the models
    ├── yolov5
        ├── README.md                          // descriptions about yolov5
        ├── scripts
        │   ├──docker_start.sh                 // shell script for docker start
        │   ├──run_distribute_train.sh         // launch distributed training(8p) in ascend
        │   ├──run_distribute_train_gpu.sh     // launch distributed training(8p) in GPU
        │   ├──run_standalone_train.sh         // launch 1p training
        │   ├──run_infer_310.sh                // shell script for evaluation on 310
        │   ├──run_eval.sh                     // shell script for evaluation
        │   ├──run_eval_onnx.sh                // shell script for onnx evaluation
        ├──model_utils
        │   ├──config.py                       // getting config parameters
        │   ├──device_adapter.py               // getting device info
        │   ├──local_adapter.py                // getting device info
        │   ├──moxing_adapter.py               // Decorator
        ├── src
        │   ├──backbone.py                     // backbone of network
        │   ├──distributed_sampler.py          // iterator of dataset
        │   ├──initializer.py                  // initializer of parameters
        │   ├──logger.py                       // log function
        │   ├──loss.py                         // loss function
        │   ├──lr_scheduler.py                 // generate learning rate
        │   ├──transforms.py                   // Preprocess data
        │   ├──util.py                         // util function
        │   ├──yolo.py                         // yolov5 network
        │   ├──yolo_dataset.py                 // create dataset for YOLOV5
        ├── Mask_data                            //dataset
        │   ├──train                                 //train files
        │   ├──val                                    //val files
        │   ├──train.json                                 //Json file of training set
        │   ├──val.json                                 //Json file of validation set
        ├── default_config.yaml                // parameter configuration(yolov5s 8p)
        ├── train.py                           // training script
        ├── eval.py                            // evaluation script
        ├── eval_onnx.py                       // ONNX evaluation script
        ├── export.py                          // export script

Training Process

Training

For Ascend device, standalone training can be started like this:

#run training example(1p) by python command
python train.py \
    --data_dir=xxx/dataset \
    --yolov5_version='yolov5s' \
    --is_distributed=0 \
    --lr=0.01 \
    --T_max=320
    --max_epoch=320 \
    --warmup_epochs=4 \
    --per_batch_size=32 \
    --lr_scheduler=cosine_annealing > log.txt 2>&1 &

在GPU上运行training 1p时,应微调参数

上面的python命令将在后台运行,您可以通过文件“log.txt”查看结果。

培训后,默认情况下,您将在outputs文件夹下获得一些检查点文件。loss值将按以下方式实现:

# grep "loss:" log.txt
2022-10-13 12:39:57,825:INFO:Args:
2022-10-13 12:39:57,825:INFO:--> enable_modelarts: False
2022-10-13 12:39:57,826:INFO:--> data_url: 
2022-10-13 12:39:57,826:INFO:--> train_url: 
2022-10-13 12:39:57,826:INFO:--> checkpoint_url: 
2022-10-13 12:39:57,826:INFO:--> outputs_url: 
2022-10-13 12:39:57,826:INFO:--> data_path: /cache/data
2022-10-13 12:39:57,827:INFO:--> output_path: /cache/train
2022-10-13 12:39:57,827:INFO:--> load_path: /cache/checkpoint_path
2022-10-13 12:39:57,827:INFO:--> device_target: CPU
2022-10-13 12:39:57,827:INFO:--> need_modelarts_dataset_unzip: True
2022-10-13 12:39:57,827:INFO:--> modelarts_dataset_unzip_name: coco
2022-10-13 12:39:57,827:INFO:--> data_dir: /content/drive/MyDrive/yolov5/Mask_Data
2022-10-13 12:39:57,827:INFO:--> per_batch_size: 16
2022-10-13 12:39:57,828:INFO:--> yolov5_version: yolov5s
2022-10-13 12:39:57,828:INFO:--> pretrained_backbone: 
2022-10-13 12:39:57,828:INFO:--> resume_yolov5: 
2022-10-13 12:39:57,828:INFO:--> pretrained_checkpoint: 
2022-10-13 12:39:57,829:INFO:--> output_dir: ./output
2022-10-13 12:39:57,829:INFO:--> train_img_dir: train
2022-10-13 12:39:57,829:INFO:--> train_json_file: /content/drive/MyDrive/yolov5/Mask_Data/train.json
2022-10-13 12:39:57,829:INFO:--> lr_scheduler: cosine_annealing
2022-10-13 12:39:57,829:INFO:--> lr: 0.01
2022-10-13 12:39:57,829:INFO:--> lr_epochs: [220, 250]
2022-10-13 12:39:57,830:INFO:--> lr_gamma: 0.1
2022-10-13 12:39:57,830:INFO:--> eta_min: 0.0
2022-10-13 12:39:57,830:INFO:--> T_max: 300
2022-10-13 12:39:57,830:INFO:--> max_epoch: 300
2022-10-13 12:39:57,830:INFO:--> warmup_epochs: 20
2022-10-13 12:39:57,830:INFO:--> weight_decay: 0.0005
2022-10-13 12:39:57,830:INFO:--> momentum: 0.9
2022-10-13 12:39:57,831:INFO:--> loss_scale: 1024
2022-10-13 12:39:57,831:INFO:--> label_smooth: 0
2022-10-13 12:39:57,831:INFO:--> label_smooth_factor: 0.1
2022-10-13 12:39:57,831:INFO:--> log_interval: 100
2022-10-13 12:39:57,832:INFO:--> ckpt_path: outputs/
2022-10-13 12:39:57,832:INFO:--> is_distributed: 0
2022-10-13 12:39:57,832:INFO:--> bind_cpu: True
2022-10-13 12:39:57,832:INFO:--> device_num: 8
2022-10-13 12:39:57,833:INFO:--> rank: 0 
2022-10-13 12:39:57,833:INFO:--> group_size: 1
2022-10-13 12:39:57,833:INFO:--> need_profiler: 0
2022-10-13 12:39:57,833:INFO:--> resize_rate: 10
2022-10-13 12:39:57,833:INFO:--> filter_weight: False
2022-10-13 12:39:57,833:INFO:--> pretrained: 
2022-10-13 12:39:57,833:INFO:--> log_path: outputs/
2022-10-13 12:39:57,834:INFO:--> ann_val_file: 
2022-10-13 12:39:57,834:INFO:--> eval_nms_thresh: 0.6
2022-10-13 12:39:57,834:INFO:--> ignore_threshold: 0.7
2022-10-13 12:39:57,834:INFO:--> test_ignore_threshold: 0.001
2022-10-13 12:39:57,834:INFO:--> multi_label: True
2022-10-13 12:39:57,834:INFO:--> multi_label_thresh: 0.1
2022-10-13 12:39:57,834:INFO:--> device_id: 0
2022-10-13 12:39:57,834:INFO:--> batch_size: 1
2022-10-13 12:39:57,834:INFO:--> testing_shape: [640, 640]
2022-10-13 12:39:57,834:INFO:--> ckpt_file: 
2022-10-13 12:39:57,834:INFO:--> file_name: yolov5
2022-10-13 12:39:57,835:INFO:--> file_format: MINDIR
2022-10-13 12:39:57,835:INFO:--> dataset_path: 
2022-10-13 12:39:57,835:INFO:--> ann_file: 
2022-10-13 12:39:57,835:INFO:--> hue: 0.015
2022-10-13 12:39:57,835:INFO:--> saturation: 1.5
2022-10-13 12:39:57,835:INFO:--> value: 0.4
2022-10-13 12:39:57,836:INFO:--> jitter: 0.3
2022-10-13 12:39:57,836:INFO:--> num_classes: 2
2022-10-13 12:39:57,836:INFO:--> max_box: 150
2022-10-13 12:39:57,836:INFO:--> checkpoint_filter_list: ['feature_map.back_block1.conv.weight', 'feature_map.back_block1.conv.bias', 'feature_map.back_block2.conv.weight', 'feature_map.back_block2.conv.bias', 'feature_map.back_block3.conv.weight', 'feature_map.back_block3.conv.bias']
2022-10-13 12:39:57,836:INFO:--> anchor_scales: [[12, 16], [19, 36], [40, 28], [36, 75], [76, 55], [72, 146], [142, 110], [192, 243], [459, 401]]
2022-10-13 12:39:57,836:INFO:--> out_channel: 255
2022-10-13 12:39:57,836:INFO:--> input_shape: [[3, 32, 64, 128, 256, 512, 1], [3, 48, 96, 192, 384, 768, 2], [3, 64, 128, 256, 512, 1024, 3], [3, 80, 160, 320, 640, 1280, 4]]
2022-10-13 12:39:57,836:INFO:--> test_img_shape: [640, 640]
2022-10-13 12:39:57,836:INFO:--> labels: ['face', 'mask']
2022-10-13 12:39:57,836:INFO:--> coco_ids: [1, 2]
2022-10-13 12:39:57,836:INFO:--> result_files: ./result_Files
2022-10-13 12:39:57,837:INFO:--> config_path: /content/drive/MyDrive/yolov5/scripts/train/model_utils/../default_config.yaml
2022-10-13 12:39:57,837:INFO:--> data_root: /content/drive/MyDrive/yolov5/Mask_Data/train
2022-10-13 12:39:57,837:INFO:--> annFile: /content/drive/MyDrive/yolov5/Mask_Data/train.json
2022-10-13 12:39:57,837:INFO:--> logger: <LOGGER YOLOV5 (NOTSET)>
2022-10-13 12:39:57,837:INFO:
2022-10-13 12:40:00,627:INFO:Finish loading dataset
2022-10-13 12:42:19,786:INFO:epoch[1], iter[1], loss:6912.432129, fps:0.12 imgs/sec, lr:1.0416666555101983e-05, per step time: 136025.09236335754ms
2022-10-13 14:42:07,053:INFO:epoch[3], iter[5], loss:457.446309, fps:0.22 imgs/sec, lr:5.208333459449932e-05, per step time: 71872.65128612518ms
2022-10-13 16:38:50,794:INFO:epoch[5], iter[9], loss:78.912332, fps:0.23 imgs/sec, lr:9.375000081490725e-05, per step time: 70037.39101886749ms
2022-10-13 18:37:11,424:INFO:epoch[7], iter[13], loss:74.624980, fps:0.23 imgs/sec, lr:0.00013541665975935757, per step time: 71006.26902580261ms
2022-10-13 20:38:46,032:INFO:epoch[9], iter[17], loss:76.142794, fps:0.22 imgs/sec, lr:0.00017708333325572312, per step time: 72946.06168746948ms
2022-10-13 22:34:27,871:INFO:epoch[11], iter[21], loss:72.063589, fps:0.23 imgs/sec, lr:0.00021875000675208867, per step time: 69418.34685087204ms
...

Evaluation Process

Evaluation

在运行下面的命令之前,请检查用于评估的检查点路径。以下脚本中使用的文件yolov5.ckpt是最后保存的检查点文件,但我们将其重命名为“yolov5.ckpt”。

# run evaluation by python command
python eval.py \
    --data_dir=xxx/dataset \
    --pretrained=xxx/yolov5.ckpt \
    --eval_shape=640 > log.txt 2>&1 &
OR
# run evaluation by shell script
bash run_eval.sh [DATASET_PATH] [CHECKPOINT_PATH]

上面的python命令将在后台运行。您可以通过文件“log.txt”查看结果。测试数据集的mAP如下:

# log.txt
=============coco eval reulst=========
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.369
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.573
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.395
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.218
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.418
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.482
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.298
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.501
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.557
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.395
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.619
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.677
2020-12-21 17:16:40,322:INFO:testing cost time 0.35h

Inference Process

Export MindIR

python export.py --ckpt_file [CKPT_PATH] --file_name [FILE_NAME] --file_format [FILE_FORMAT]

ckpt_file参数是必需的, file_format应在[“AIR”,“MINDIR”]中

Infer on Ascend310

在执行推断之前,必须通过export导出mindir文件。py脚本。我们只提供了一个使用MINDIR模型进行推理的示例。 当前batch_Size只能设置为1。

# Ascend310 inference
bash run_infer_310.sh [MINDIR_PATH] [DATA_PATH] [ANN_FILE] [DVPP] [DEVICE_ID]
  • DVPP is mandatory, and must choose from [“DVPP”, “CPU”], it’s case-insensitive. The DVPP hardware restricts width 16-alignment and height even-alignment. Therefore, the network needs to use the CPU operator to process images.
  • DATA_PATH is mandatory, path of the dataset containing images.
  • ANN_FILE is mandatory, path to annotation file.
  • DEVICE_ID is optional, default value is 0.

result

推断结果保存在当前路径中,您可以在acc.log文件中找到类似的结果。

Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.369
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.573
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.395
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.218
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.418
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.482
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.298
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.501
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.557
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.395
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.619
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.677

1.png

optimization

Attention Mechanism

本次任务对主干网络中加入了SE注意力机制,用于提高其精准度.

import mindspore.nn as nn
import mindspore.ops.operations as P
import mindspore.ops as ops
class eca_block(nn.Cell):
    def __init__(self, channel, ratio=16):
        super(eca_block, self).__init__()
        self.avg_pool = ops.AdaptiveAvgPool2D(1)
        self.fc = nn.SequentialCell([
                nn.Dense(in_channels=channel, out_channels=channel // ratio, has_bias=False),
                nn.ReLU(),
                nn.Dense(in_channels=channel // ratio, out_channels=channel, has_bias=False),
                nn.Sigmoid()
        ])
    def construct(self, x):
        b, c, _, _ = P.Shape()(x)
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y

Loss Function

损失函数方面原本的YOLOv5使用的是GIOU_Loss,而我们将其改为CIOU_Loss,以提高边界框定位的精度,最终提高预测精度,其实现代码如下。

def ciou(boxes1,boxes2):
    '''
    cal CIOU of two boxes or batch boxes
    :param boxes1:[xmin,ymin,xmax,ymax] or
                [[xmin,ymin,xmax,ymax],[xmin,ymin,xmax,ymax],...]
    :param boxes2:[xmin,ymin,xmax,ymax]
    :return:
    '''

    #cal the box's area of boxes1 and boxess
    boxes1Area = (boxes1[...,2]-boxes1[...,0])*(boxes1[...,3]-boxes1[...,1])
    boxes2Area = (boxes2[..., 2] - boxes2[..., 0]) * (boxes2[..., 3] - boxes2[..., 1])

    # cal Intersection
    left_up = np.maximum(boxes1[...,:2],boxes2[...,:2])
    right_down = np.minimum(boxes1[...,2:],boxes2[...,2:])

    inter_section = np.maximum(right_down-left_up,0.0)
    inter_area = inter_section[...,0] * inter_section[...,1]
    union_area = boxes1Area+boxes2Area-inter_area
    ious = np.maximum(1.0*inter_area/union_area,np.finfo(np.float32).eps)

    # cal outer boxes
    outer_left_up = np.minimum(boxes1[..., :2], boxes2[..., :2])
    outer_right_down = np.maximum(boxes1[..., 2:], boxes2[..., 2:])
    outer = np.maximum(outer_right_down - outer_left_up, 0.0)
    outer_diagonal_line = np.square(outer[...,0]) + np.square(outer[...,1])

    # cal center distance
    boxes1_center = (boxes1[..., :2] +  boxes1[...,2:]) * 0.5
    boxes2_center = (boxes2[..., :2] +  boxes2[...,2:]) * 0.5
    center_dis = np.square(boxes1_center[...,0]-boxes2_center[...,0]) +\
                 np.square(boxes1_center[...,1]-boxes2_center[...,1])

    # cal penalty term
    # cal width,height
    boxes1_size = np.maximum(boxes1[...,2:]-boxes1[...,:2],0.0)
    boxes2_size = np.maximum(boxes2[..., 2:] - boxes2[..., :2], 0.0)
    v = (4.0/np.square(np.pi)) * np.square((
            np.arctan((boxes1_size[...,0]/boxes1_size[...,1])) -
            np.arctan((boxes2_size[..., 0] / boxes2_size[..., 1])) ))
    alpha = v / (1-ious+v)
    #cal ciou
    cious = ious - (center_dis / outer_diagonal_line + alpha*v)

    return cious
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

©Copyright 2023 CCF 开源发展委员会
Powered by Trustie& IntelliDE 京ICP备13000930号