今年年初的时候曾经玩了一阵openvino yolov5量化,后来找到了这个github的大神教程完美解决GitHub - Chen-MingChang/pytorch_YOLO_OpenVINO_demoContribute to Chen-MingChang/pytorch_YOLO_OpenVINO_demo development by creating an account on GitHub.https://github.com/Chen-MingChang/pytorch_YOLO_OpenVINO_demo但是当时有几个问题不是很完美

这个大神在openvino 2021.2上手写代码扩充了accuracy checker的yolov5的支持,需要在ov2021.2上打patch, 如果openvino升级的话,因为AC代码的变动, merge的时候大概率会有问题

记得当时转换完测了一下,CPU上推理是正常的,但是GPU推理有问题。在那个bus的推理图片上,莫名的多出了几个识别的红框框,明显是错了。感觉clDNN在计算上可能有数据溢出的现象,但是时间有点久了,忘了是在FP32还是在INT8时候出错了。

最近OpenVINO 2021r4.1发布了,再回过头来看看2021r4.1版本的yolov5支持

1. 搭建环境

安装windows版的openvino 2021.4.1 LTS, 按照官网的教程安装ac和pot的依赖项。

2. 下载和准备yolov5的模型

这里完全按照大神 https://github.com/Chen-MingChang/pytorch_YOLO_OpenVINO_demo里面的步骤走。

  • 下载github上分享的yolov5l v4版本的pytorch模型
  • 运行export.py将pytorch模型转成onnx模型
$ python3 models/export.py  --weights yolov5l.pt  --img-size 640

  • 然后用netron观察转换出的onnx网络节点图,记录最后3个输出点前的最后一个Conv层的名字,等下转IR时候需要指定--output输出节点,这个模型分别是Conv_403, Conv_491, Conv_435

yolov和opencv的区别 yolov5与opencv_python

yolov和opencv的区别 yolov5与opencv_深度学习_02

yolov和opencv的区别 yolov5与opencv_xml_03

3. 转换yolov5的OpenVINO FP32模型

  • 进入openvino环境,将onnx模型转成FP32的IR模型
C:\temp\yolov5_ac_ov2021_4>python "c:\Program Files (x86)\intel\openvino_2021\deployment_tools\model_optimizer\mo.py" --input_model yolov5l_v4.onnx -s 255 --reverse_input_channels --output Conv_403,Conv_419,Conv_435
Model Optimizer arguments:
Common parameters:
        - Path to the Input Model:      C:\temp\yolov5_ac_ov2021_4\yolov5l_v4.onnx
        - Path for generated IR:        C:\temp\yolov5_ac_ov2021_4\.
        - IR output name:       yolov5l_v4
        - Log level:    ERROR
        - Batch:        Not specified, inherited from the model
        - Input layers:         Not specified, inherited from the model
        - Output layers:        Conv_403,Conv_419,Conv_435
        - Input shapes:         Not specified, inherited from the model
        - Mean values:  Not specified
        - Scale values:         Not specified
        - Scale factor:         255.0
        - Precision of IR:      FP32
        - Enable fusing:        True
        - Enable grouped convolutions fusing:   True
        - Move mean values to preprocess section:       None
        - Reverse input channels:       True
ONNX specific parameters:
        - Inference Engine found in:    c:\Program Files (x86)\Intel\openvino_2021\python\python3.7\openvino
Inference Engine version:       2021.4.1-3926-14e67d86634-releases/2021/4
Model Optimizer version:        2021.4.1-3926-14e67d86634-releases/2021/4
[ SUCCESS ] Generated IR version 10 model.
[ SUCCESS ] XML file: C:\temp\yolov5_ac_ov2021_4\yolov5l_v4.xml
[ SUCCESS ] BIN file: C:\temp\yolov5_ac_ov2021_4\yolov5l_v4.bin
[ SUCCESS ] Total execution time: 14.90 seconds.

  • 接下来先做一下FP32的精度检测,好等下和INT8模型精度做比对
  1. 下载和准备coco val2017数据集,  Dataset Preparation Guide - OpenVINO™ Toolkit
  2. 下载的原始数据集有点大,用CPU做完整的AC太费时间,可以参考这里对数据库做裁剪 Cut Datasets   这里只截了256张图片做实验
  • accuracy checker

准备yolov5_640_ac.yml配置文件

models:

  - name: yolo-v5

    launchers:
      - framework: dlsdk
        model:   yolov5l_v4.xml
        weights: yolov5l_v4.bin
        adapter:
          type: yolo_v3
          anchors: "10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326"
          num: 9
          coords: 4
          classes: 80
          anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2],  ]
          outputs:
            - Conv_435
            - Conv_419
            - Conv_403

    datasets:
      - name: ms_coco_detection_80_class_without_background
        data_source: val2017
        annotation_conversion:
          converter: mscoco_detection
          annotation_file: instances_val2017.json
          has_background: False
          sort_annotations: True
          use_full_label_map: False
        annotation: mscoco_det_80.pickle
        dataset_meta: mscoco_det_80.json
        preprocessing:
          - type: resize
            size: 640

        postprocessing:
          - type: resize_prediction_boxes
          - type: filter
            apply_to: prediction
            min_confidence: 0.001
            remove_filtered: True
          - type: nms
            overlap: 0.5
          - type: clip_boxes
            apply_to: prediction

        metrics:
          - type: map
            integral: 11point
            ignore_difficult: true
            presenter: print_scalar
          - type: coco_precision
            max_detections: 100
            threshold: 0.5

运行ac命令

C:\temp\yolov5_ac_ov2021_4>accuracy_check -c yolov5_640_ac.yml -s ./ -td CPU
09:01:27 accuracy_checker WARNING: c:\Program Files (x86)\Intel\openvino_2021\python\python3.7\ngraph\utils\types.py:25: DeprecationWarning: `np.bool` is a deprecated alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  (NgraphType.boolean, np.bool),

Processing info:
model: yolo-v5
launcher: dlsdk
device: CPU
dataset: ms_coco_detection_80_class_without_background
OpenCV version: 4.5.2
Annotation for ms_coco_detection_80_class_without_background dataset will be loaded from mscoco_det_80.pickle
Loaded dataset info:
        Dataset name: ms_coco_detection_80_class_without_background_1
        Accuracy Checker version 0.8.7
        Dataset size 256
        Conversion parameters:
                converter: mscoco_detection
                annotation_file: PATH/instances_val2017.json
                has_background: False
                sort_annotations: True
                use_full_label_map: False
ms_coco_detection_80_class_without_background dataset metadata will be loaded from mscoco_det_80.json
IE version: 2021.4.1-3926-14e67d86634-releases/2021/4
Loaded CPU plugin version:
    CPU - MKLDNNPlugin: 2.1.2021.4.1-3926-14e67d86634-releases/2021/4
Found model yolov5l_v4.xml
Found weights yolov5l_v4.bin
Input info:
        Layer name: images
        precision: FP32
        shape [1, 3, 640, 640]

Output info
        Layer name: Conv_403
        precision: FP32
        shape: [1, 255, 80, 80]

        Layer name: Conv_419
        precision: FP32
        shape: [1, 255, 40, 40]

        Layer name: Conv_435
        precision: FP32
        shape: [1, 255, 20, 20]

09:01:28 accuracy_checker WARNING: c:\users\intel\anaconda3\lib\site-packages\accuracy_checker-0.8.7-py3.7.egg\accuracy_checker\metrics\metric_executor.py:168: DeprecationWarning: threshold option is deprecated. Please use abs_threshold instead
  warnings.warn('threshold option is deprecated. Please use abs_threshold instead', DeprecationWarning)

256 objects processed in 133.234 seconds
map: 27.70%
coco_precision: 31.18%

这个精度有问题啊,用GitHub - Chen-MingChang/pytorch_YOLO_OpenVINO_demo的代码复现的精度有60%多呢... 但是看网上很多人已经用openvino+yolov5做推理了,精度应该没有大问题,还是accuracy checker自己有问题的可能性比较大

4. 转换yolov5的OpenVINO INT8模型

  • 用pot工具做int8模型量化

准备pot配置json文件, 量化方法选择了最简单的DefaultQuantization, 这种方法在量化时不做精度检测对比,只是把所有能转成int8的fp32操作全部转成int8类型

准备yolov5l_v4_int8_simple_mode.json配置文件

{
    "model": {
        "model_name": "yolov5l_v4_int8_cpu",
        "model": "yolov5l_v4_640.xml",
        "weights": "yolov5l_v4_640.bin"
    },
    "engine": {
        "type": "simplified",
        // you can specify path to directory with images or video file
        // also you can specify template for file names to filter images to load
        // templates are unix style
        "data_source": "val2017"
    },
    "compression": {
        "target_device": "CPU",
        "algorithms": [
            {
                "name": "DefaultQuantization",
                "params": {
                    "preset": "performance",
                    "stat_subset_size": 128
                }
            }
        ]
    }
}

运行pot命令量化

C:\temp\yolov5_ac_ov2021_4>pot -c yolov5l_v4_int8_simple_mode.json
10:12:41 accuracy_checker WARNING: c:\users\intel\appdata\roaming\python\python37\site-packages\defusedxml\__init__.py:30: DeprecationWarning: defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.
  from . import cElementTree

10:12:41 accuracy_checker WARNING: c:\users\intel\anaconda3\lib\site-packages\pot-1.0-py3.7.egg\compression\algorithms\quantization\optimization\algorithm.py:39: UserWarning: Nevergrad package could not be imported. If you are planning to useany hyperparameter optimization algo, consider installing itusing pip. This implies advanced usage of the tool.Note that nevergrad is compatible only with Python 3.6+
  'Nevergrad package could not be imported. If you are planning to use'

10:12:41 accuracy_checker WARNING: c:\users\intel\anaconda3\lib\site-packages\past\builtins\misc.py:4: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
  from collections import Mapping

INFO:app.run:Output log dir: ./results\yolov5l_v4_int8_gpu_DefaultQuantization\2021-09-16_10-12-41
INFO:app.run:Creating pipeline:
 Algorithm: DefaultQuantization
 Parameters:
        preset                     : performance
        stat_subset_size           : 128
        target_device              : CPU
        model_type                 : None
        dump_intermediate_model    : False
        exec_log_dir               : ./results\yolov5l_v4_int8_gpu_DefaultQuantization\2021-09-16_10-12-41
 ===========================================================================
INFO:compression.statistics.collector:Start computing statistics for algorithms : DefaultQuantization
INFO:compression.statistics.collector:Computing statistics finished
INFO:compression.pipeline.pipeline:Start algorithm: DefaultQuantization
INFO:compression.algorithms.quantization.default.algorithm:Start computing statistics for algorithm : ActivationChannelAlignment
INFO:compression.algorithms.quantization.default.algorithm:Computing statistics finished
INFO:compression.algorithms.quantization.default.algorithm:Start computing statistics for algorithms : MinMaxQuantization,FastBiasCorrection
INFO:compression.algorithms.quantization.default.algorithm:Computing statistics finished
INFO:compression.pipeline.pipeline:Finished: DefaultQuantization
 ===========================================================================

  • 用ac测一下int8模型的精度

C:\temp\yolov5_ac_ov2021_4>accuracy_check -c yolov5_int8_640_ac.yml -s ./ -td CPU
10:17:13 accuracy_checker WARNING: c:\Program Files (x86)\Intel\openvino_2021\python\python3.7\ngraph\utils\types.py:25: DeprecationWarning: `np.bool` is a deprecated alias for the builtin `bool`. To silence this warning, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  (NgraphType.boolean, np.bool),

Processing info:
model: yolo-v5-int8
launcher: dlsdk
device: CPU
dataset: ms_coco_detection_80_class_without_background
OpenCV version: 4.5.2
Annotation for ms_coco_detection_80_class_without_background dataset will be loaded from mscoco_det_80.pickle
Loaded dataset info:
        Dataset name: ms_coco_detection_80_class_without_background_1
        Accuracy Checker version 0.8.7
        Dataset size 256
        Conversion parameters:
                converter: mscoco_detection
                annotation_file: PATH/instances_val2017.json
                has_background: False
                sort_annotations: True
                use_full_label_map: False
ms_coco_detection_80_class_without_background dataset metadata will be loaded from mscoco_det_80.json
IE version: 2021.4.1-3926-14e67d86634-releases/2021/4
Loaded CPU plugin version:
    CPU - MKLDNNPlugin: 2.1.2021.4.1-3926-14e67d86634-releases/2021/4
Found model yolov5l_v4_int8_cpu.xml
Found weights yolov5l_v4_int8_cpu.bin
Input info:
        Layer name: images
        precision: FP32
        shape [1, 3, 640, 640]

Output info
        Layer name: Conv_403
        precision: FP32
        shape: [1, 255, 80, 80]

        Layer name: Conv_419
        precision: FP32
        shape: [1, 255, 40, 40]

        Layer name: Conv_435
        precision: FP32
        shape: [1, 255, 20, 20]

10:17:13 accuracy_checker WARNING: c:\users\intel\anaconda3\lib\site-packages\accuracy_checker-0.8.7-py3.7.egg\accuracy_checker\metrics\metric_executor.py:168: DeprecationWarning: threshold option is deprecated. Please use abs_threshold instead
  warnings.warn('threshold option is deprecated. Please use abs_threshold instead', DeprecationWarning)

256 objects processed in 106.666 seconds
map: 28.67%
coco_precision: 33.07%

虽说精度不对,但是看上去int8模型的精度竟然比fp32的精度还好一点,这个有点意思 

5. yolov5的OpenVINO C++推理实现

这部分相对就比较简单了,主要参考了大神的项目

c++实现yolov5的OpenVINO部署

代码的工作就是把OpenVINO推理输出的3个输出层的结果(窗口的座标,分类label和信心度)做一些处理,先筛掉信心度比较低的检测窗,再把同一物体上不同大小的检测窗再筛一遍,保留信息度最大的框

具体代码就不贴了,整个项目奉上 yolov5-ov2021: 基于c++/openvino 2021r4的yolov5推理实现

运行FP32模型,GPU推理

yolov和opencv的区别 yolov5与opencv_yolov和opencv的区别_04

运行INT8模型,GPU推理

yolov和opencv的区别 yolov5与opencv_python_05

6. 模型benchmarking

用OpenVINO2021r4自带的benchmarking工具测试

 CPU推理性能测试

9900K 8核16线程

FP32模型CPU推理 5.59FPS

C:\Users\test\Documents\Intel\OpenVINO\inference_engine_cpp_samples_build\intel64\Release>benchmark_app.exe -m yolov5l_v4_640.xml -nireq 1 -nstreams 1 -b 1 -d CPU
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading Inference Engine
[ INFO ] InferenceEngine:
        IE version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4
[ INFO ] Device info:
        CPU
        MKLDNNPlugin version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4

[Step 3/11] Setting device configuration
[Step 4/11] Reading network files
[ INFO ] Loading network files
[ INFO ] Read network took 151.36 ms
[Step 5/11] Resizing network to match image sizes and given batch
[ INFO ] Network batch size was changed to: 1
[Step 6/11] Configuring input of the model
Network inputs:
    images : U8 / NCHW
Network outputs:
    Conv_403 : FP32 / NCHW
    Conv_419 : FP32 / NCHW
    Conv_435 : FP32 / NCHW
[Step 7/11] Loading the model to the device
[ INFO ] Load network took 195.02 ms
[Step 8/11] Setting optimal runtime parameters
[Step 9/11] Creating infer requests and filling input blobs with images
[ INFO ] Network input 'images' precision U8, dimensions (NCHW): 1 3 640 640
[ WARNING ] No input files were given: all inputs will be filled with random values!
[ INFO ] Infer Request 0 filling
[ INFO ] Fill input 'images' with random values (image is expected)
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests using 1 streams for CPU, limits: 60000 ms duration)
[ INFO ] First inference took 182.24 ms

[Step 11/11] Dumping statistics report
Count:      337 iterations
Duration:   60327.10 ms
Latency:    177.38 ms
Throughput: 5.59 FPS

INT8模型CPU推理 13.37FPS,

C:\Users\test\Documents\Intel\OpenVINO\inference_engine_cpp_samples_build\intel64\Release>benchmark_app.exe -m yolov5l_v4_640_int8_cpu.xml -nireq 1 -nstreams 1 -b 1 -d CPU
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading Inference Engine
[ INFO ] InferenceEngine:
        IE version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4
[ INFO ] Device info:
        CPU
        MKLDNNPlugin version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4

[Step 3/11] Setting device configuration
[Step 4/11] Reading network files
[ INFO ] Loading network files
[ INFO ] Read network took 82.20 ms
[Step 5/11] Resizing network to match image sizes and given batch
[ INFO ] Network batch size was changed to: 1
[Step 6/11] Configuring input of the model
Network inputs:
    images : U8 / NCHW
Network outputs:
    Conv_403 : FP32 / NCHW
    Conv_419 : FP32 / NCHW
    Conv_435 : FP32 / NCHW
[Step 7/11] Loading the model to the device
[ INFO ] Load network took 409.73 ms
[Step 8/11] Setting optimal runtime parameters
[Step 9/11] Creating infer requests and filling input blobs with images
[ INFO ] Network input 'images' precision U8, dimensions (NCHW): 1 3 640 640
[ WARNING ] No input files were given: all inputs will be filled with random values!
[ INFO ] Infer Request 0 filling
[ INFO ] Fill input 'images' with random values (image is expected)
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests using 1 streams for CPU, limits: 60000 ms duration)
[ INFO ] First inference took 82.14 ms

[Step 11/11] Dumping statistics report
Count:      804 iterations
Duration:   60135.29 ms
Latency:    74.23 ms
Throughput: 13.37 FPS

 GPU推理性能测试

TGL 集显Gen12 96EU

FP32模型GPU推理 9.86FPS

C:\Users\test\Documents\Intel\OpenVINO\inference_engine_cpp_samples_build\intel64\Release>benchmark_app.exe -m yolov5l_v4_640.xml -nireq 1 -nstreams 1 -b 1 -d GPU
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading Inference Engine
[ INFO ] InferenceEngine:
        IE version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4
[ INFO ] Device info:
        GPU
        clDNNPlugin version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4

[Step 3/11] Setting device configuration
[Step 4/11] Reading network files
[ INFO ] Loading network files
[ INFO ] Read network took 137.94 ms
[Step 5/11] Resizing network to match image sizes and given batch
[ INFO ] Network batch size was changed to: 1
[Step 6/11] Configuring input of the model
Network inputs:
    images : U8 / NCHW
Network outputs:
    Conv_403 : FP32 / NCHW
    Conv_419 : FP32 / NCHW
    Conv_435 : FP32 / NCHW
[Step 7/11] Loading the model to the device
[ INFO ] Load network took 57321.88 ms
[Step 8/11] Setting optimal runtime parameters
[Step 9/11] Creating infer requests and filling input blobs with images
[ INFO ] Network input 'images' precision U8, dimensions (NCHW): 1 3 640 640
[ WARNING ] No input files were given: all inputs will be filled with random values!
[ INFO ] Infer Request 0 filling
[ INFO ] Fill input 'images' with random values (image is expected)
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests using 1 streams for GPU, limits: 60000 ms duration)
[ INFO ] First inference took 89.20 ms

[Step 11/11] Dumping statistics report
Count:      593 iterations
Duration:   60131.64 ms
Latency:    113.72 ms
Throughput: 9.86 FPS

INT8模型GPU推理 30.91FPS

C:\Users\test\Documents\Intel\OpenVINO\inference_engine_cpp_samples_build\intel64\Release>benchmark_app.exe -m yolov5l_v4_640_int8_cpu.xml -nireq 1 -nstreams 1 -b 1 -d GPU
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading Inference Engine
[ INFO ] InferenceEngine:
        IE version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4
[ INFO ] Device info:
        GPU
        clDNNPlugin version ......... 2021.4.1
        Build ........... 2021.4.1-3926-14e67d86634-releases/2021/4

[Step 3/11] Setting device configuration
[Step 4/11] Reading network files
[ INFO ] Loading network files
[ INFO ] Read network took 65.74 ms
[Step 5/11] Resizing network to match image sizes and given batch
[ INFO ] Network batch size was changed to: 1
[Step 6/11] Configuring input of the model
Network inputs:
    images : U8 / NCHW
Network outputs:
    Conv_403 : FP32 / NCHW
    Conv_419 : FP32 / NCHW
    Conv_435 : FP32 / NCHW
[Step 7/11] Loading the model to the device
[ INFO ] Load network took 61720.85 ms
[Step 8/11] Setting optimal runtime parameters
[Step 9/11] Creating infer requests and filling input blobs with images
[ INFO ] Network input 'images' precision U8, dimensions (NCHW): 1 3 640 640
[ WARNING ] No input files were given: all inputs will be filled with random values!
[ INFO ] Infer Request 0 filling
[ INFO ] Fill input 'images' with random values (image is expected)
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests using 1 streams for GPU, limits: 60000 ms duration)
[ INFO ] First inference took 34.45 ms

[Step 11/11] Dumping statistics report
Count:      1856 iterations
Duration:   60050.95 ms
Latency:    31.02 ms
Throughput: 30.91 FPS
CPU INT8/FP32 = 13.37/5.59 = 2.4X
GPU INT8/FP32 = 30.91/9.86 = 3.13X
GPU/CPU FP32 = 9.86/5.59 = 1.76X
GPU/CPU INT8 = 30.91/13.37 = 2.31X

性能提升非常不错,在Intel集显上Yolov5l的V4版本终于到30FPS了 :)

收工!!! :)

最后照例分享一下踩过的小坑

  1. 今年在openvino 2021的4个版本(2021.1/2/3/4 )上尝试了yolov5的精度检测,发现好像accuracy checker对python的不同版本有依赖,我用的不同anaconda里带的python, 3.6 3.7 3.8安装测试,发现有些python版本装ac/pot的依赖项时候会出错,不知道是不是我这边环境的问题还是openvino问题(我这机器好多年没重装python了, 各种包反复升级卸载)
  2. 从 https://github.com/openvinotoolkit/open_model_zoo/pull/2051  看accuracy checker已经支持了yolov5, 但是我这边从来没成功过,不知道是哪里有问题,还要求各位大佬解惑
  3. mo转换的时候必须要用--output 指定那几个输出的conv层的名字, 如果不指定output的话单纯做推理是没问题的,但是做ac的时候会报一个输入数据无法reshape成输出数组大小的错误。