OAK相机如何将yoloV7模型转换成blob格式?

news2024/9/29 5:25:31

编辑:OAK中国
首发:oakchina.cn
喜欢的话,请多多👍⭐️✍
内容可能会不定期更新,官网内容都是最新的,请查看首发地址链接。

▌前言

Hello,大家好,这里是OAK中国,我是助手君。

最近咱社群里有几个朋友在将yolox转换成blob的过程有点不清楚,所以我就写了这篇博客。(请夸我贴心!咱的原则:合理要求,有求必应!)

1.其他Yolo转换及使用教程请参考
2.检测类的yolo模型建议使用在线转换(地址),如果在线转换不成功,你再根据本教程来做本地转换。

.pt 转换为 .onnx

使用下列脚本 (将脚本放到 YOLOv7 根目录中) 将 pytorch 模型转换为 onnx 模型,若已安装 openvino_dev,则可进一步转换为 OpenVINO 模型:

示例用法:

python export_onnx.py -w <path_to_model>.pt -imgsz 320 

export_onnx.py :

# coding=utf-8
import argparse
import json
import logging
import subprocess
import sys
import time
import warnings
from pathlib import Path

warnings.filterwarnings("ignore")

sys.path.append("./")  # to run '$ python *.py' files in subdirectories

import torch
import torch.nn as nn

from models.common import Conv
from models.experimental import attempt_load
from utils.activations import Hardswish, SiLU
from utils.general import check_img_size, set_logging
from utils.torch_utils import select_device

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-w", "--weights", type=str, default="./yolov7.pt", help="weights path"
    )
    parser.add_argument(
        "-imgsz",
        "--img-size",
        nargs="+",
        type=int,
        default=[640, 640],
        help="image size",
    )  # height, width
    parser.add_argument("-op", "--opset", type=int, default=12, help="opset version")

    opt = parser.parse_args()
    opt.img_size *= 2 if len(opt.img_size) == 1 else 1  # expand
    set_logging()
    logging.info(opt)

    t = time.time()

    # Load PyTorch model
    device = select_device("cpu")
    model = attempt_load(opt.weights, map_location=device)  # load FP32 model
    labels = model.names

    # Checks
    gs = int(max(model.stride))  # grid size (max stride)
    opt.img_size = [
        check_img_size(x, gs) for x in opt.img_size
    ]  # verify img_size are gs-multiples

    # Input
    img = torch.zeros(1, 3, *opt.img_size).to(
        device
    )  # image size(1,3,320,320) iDetection

    # Update model
    for k, m in model.named_modules():
        m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatibility
        if isinstance(m, Conv):  # assign export-friendly activations
            if isinstance(m.act, nn.Hardswish):
                m.act = Hardswish()
            elif isinstance(m.act, nn.SiLU):
                m.act = SiLU()

    model.model[-1].concat = True

    m = model.module.model[-1] if hasattr(model, "module") else model.model[-1]
    num_branches = len(m.anchor_grid)

    y = model(img)  # dry run

    # ONNX export
    try:
        import onnx

        logging.info("\nStarting ONNX export with onnx %s..." % onnx.__version__)
        export_file = Path(opt.weights).with_suffix(".onnx")  # filename
        model.eval()
        output_names = ["classes", "boxes"] if y is None else ["output"]

        torch.onnx.export(
            model,
            img,
            export_file,
            verbose=False,
            opset_version=opt.opset,
            input_names=["images"],
            output_names=output_names,
        )

        # Checks
        onnx_model = onnx.load(export_file)  # load onnx model
        onnx.checker.check_model(onnx_model)  # check onnx model

        try:
            import onnxsim

            logging.info("\nStarting to simplify ONNX...")
            onnx_model, check = onnxsim.simplify(onnx_model)
            assert check, "assert check failed"
        except Exception as e:
            logging.warning(f"Simplifier failure: {e}")

        # add named sigmoids for prunning in OpenVINO
        conv_indices = []
        for i, n in enumerate(onnx_model.graph.node):
            if "Conv" in n.name:
                conv_indices.append(i)

        inputs = conv_indices[-num_branches:]

        for i, inp in enumerate(inputs):
            sigmoid = onnx.helper.make_node(
                "Sigmoid",
                inputs=[onnx_model.graph.node[inp].output[0]],
                outputs=[f"output{i+1}_yolov7"],
            )
            onnx_model.graph.node.append(sigmoid)

        onnx.checker.check_model(onnx_model)  # check onnx model

        onnx.save(onnx_model, export_file)
        logging.info("ONNX export success, saved as %s" % export_file)

    except Exception as e:
        logging.warning("ONNX export failure: %s" % e)

    # generate anchors and sides
    anchors, sides = [], []
    m = model.module.model[-1] if hasattr(model, "module") else model.model[-1]
    for i in range(num_branches):
        sides.append(int(opt.img_size[0] // m.stride[i]))
        for j in range(m.anchor_grid[i].size()[1]):
            anchors.extend(m.anchor_grid[i][0, j, 0, 0].numpy())
    anchors = [float(x) for x in anchors]

    # generate masks
    masks = dict()
    # for i, num in enumerate(sides[::-1]):
    for i, num in enumerate(sides):
        masks[f"side{num}"] = list(range(i * 3, i * 3 + 3))

    logging.info("\nanchors: %s" % anchors)
    logging.info("anchor_masks: %s" % masks)
    export_json = export_file.with_suffix(".json")
    export_json.with_suffix(".json").write_text(
        json.dumps(
            {
                "anchors": anchors,
                "anchor_masks": masks,
                "coordinates": 4,
                "labels": labels,
                "num_classes": model.nc,
            },
            indent=4,
        )
    )
    logging.info("Anchors data export success, saved as %s" % export_json)

    # OpenVINO export
    logging.info("\nStarting to export OpenVINO...")
    export_dir = Path(str(export_file).replace(".onnx", "_openvino"))
    OpenVINO_cmd = (
        "mo --input_model %s --output_dir %s --data_type FP16 --scale 255 --reverse_input_channel --output 'output1_yolov7,output2_yolov7,output3_yolov7' "
        % (export_file, export_dir)
    )
    try:
        subprocess.check_output(OpenVINO_cmd, shell=True)
        logging.info("OpenVINO export success, saved as %s" % export_dir)
    except Exception as e:
        logging.info("OpenVINO export failure: %s" % e)
        logging.info("\nBy the way, you can try to export OpenVINO use:")
        logging.info("\n%s" % OpenVINO_cmd)

    # OAK Blob export
    logging.info("\nThen you can try to export blob use:")
    export_xml = export_dir / export_file.with_suffix(".xml")
    export_blob = export_dir / export_file.with_suffix(".blob")
    blob_cmd = (
        "compile_tool -m %s -ip U8 -d MYRIAD -VPU_NUMBER_OF_SHAVES 6 -VPU_NUMBER_OF_CMX_SLICES 6 -o %s"
        % (export_xml, export_blob)
    )
    logging.info("\n%s" % blob_cmd)

    # Finish
    logging.info("\nExport complete (%.2fs)." % (time.time() - t))

可以使用 Netron 查看模型结构

在这里插入图片描述

▌转换

openvino 本地转换

onnx -> openvino

mo 是 openvino_dev 2022.1 中脚本,

安装命令为 pip install openvino-dev

mo --input_model yolov7.onnx  --scale 255 --reverse_input_channel

openvino -> blob

<path>/compile_tool -m yolov7.xml \
-ip U8 -d MYRIAD \
-VPU_NUMBER_OF_SHAVES 6 \
-VPU_NUMBER_OF_CMX_SLICES 6

在线转换

blobconvert 网页 http://blobconverter.luxonis.com/

  • 进入网页,按下图指示操作:

在这里插入图片描述

  • 修改参数,转换模型:

在这里插入图片描述
1. 选择 onnx 模型
2. 修改 optimizer_params--data_type=FP16 --scale 255 --reverse_input_channel
3. 修改 shaves6
4. 转换

blobconverter python 代码

blobconverter.from_onnx(
            "yolov7.onnx",	
            optimizer_params=[
                " --scale 255",
                "--reverse_input_channel",
            ],
            shaves=6,
        )

blobconvert cli

blobconverter --onnx yolov7.onnx -sh 6 -o . --optimizer-params "scale=255 --reverse_input_channel"

▌DepthAI 示例

正确解码需要可配置的网络相关参数:

使用 export_onnx.py 转换模型时会将相关参数写入 json 文件中,可根据 json 文件中数据添加下列参数

  • setNumClasses - YOLO 检测类别的数量

  • setIouThreshold - iou 阈值

  • setConfidenceThreshold - 置信度阈值,低于该阈值的对象将被过滤掉

  • setAnchors - yolo 锚点

  • setAnchorMasks - 锚掩码

Anchors:

训练模型时 cfg 中的 anchors,例如:

[12,16, 19,36, 40,28, 36,75, 76,55, 72,146, 142,110, 192,243, 459,401]

是从 yolov7.yaml 中 获取

在这里插入图片描述

AnchorMasks :

如果使用不同的输入宽度,还应该重新设置sideX , sideY, sideZ, 其中 X = width/8 , Y = width/16Z = width/32 。如果您使用的是微型(tiny)模型,那么只要设置sideX , sideY,其中 X = width/16 , Y = width/32

import cv2
import depthai as dai
import numpy as np

model = dai.OpenVINO.Blob("yolov7.blob")
dim = model.networkInputs.get("images").dims
W, H = dim[:2]
labelMap = [
    # "class_1","class_2","..."
    "class_%s"%i for i in range(80)
]

# Create pipeline
pipeline = dai.Pipeline()

# Define sources and outputs
camRgb = pipeline.create(dai.node.ColorCamera)
detectionNetwork = pipeline.create(dai.node.YoloDetectionNetwork)
xoutRgb = pipeline.create(dai.node.XLinkOut)
nnOut = pipeline.create(dai.node.XLinkOut)

xoutRgb.setStreamName("rgb")
nnOut.setStreamName("nn")

# Properties
camRgb.setPreviewSize(W, H)
camRgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
camRgb.setInterleaved(False)
camRgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.BGR)
camRgb.setFps(40)

# Network specific settings
detectionNetwork.setBlob(model)
detectionNetwork.setConfidenceThreshold(0.5)
detectionNetwork.setNumClasses(80)
detectionNetwork.setCoordinateSize(4)
detectionNetwork.setAnchors(
    [
        12,16, 19,36, 40,28,
        36,75, 76,55, 72,146,
        142,110, 192,243, 459,401
    ]
)
detectionNetwork.setAnchorMasks(
    {
        "side%s"%(W/8): [0,1,2],
        "side%s"%(W/16): [3,4,5],
        "side%s"%(W/32): [6,7,8]
    }
)
detectionNetwork.setIouThreshold(0.5)

# Linking
camRgb.preview.link(detectionNetwork.input)
camRgb.preview.link(xoutRgb.input)
detectionNetwork.out.link(nnOut.input)

# Connect to device and start pipeline
with dai.Device(pipeline) as device:
    # Output queues will be used to get the rgb frames and nn data from the outputs defined above
    qRgb = device.getOutputQueue(name="rgb", maxSize=4, blocking=False)
    qDet = device.getOutputQueue(name="nn", maxSize=4, blocking=False)

    frame = None
    detections = []
    color2 = (255, 255, 255)

    # nn data, being the bounding box locations, are in <0..1> range - they need to be normalized with frame width/height
    def frameNorm(frame, bbox):
        normVals = np.full(len(bbox), frame.shape[0])
        normVals[::2] = frame.shape[1]
        return (np.clip(np.array(bbox), 0, 1) * normVals).astype(int)

    def displayFrame(name, frame):
        color = (255, 0, 0)
        for detection in detections:
            bbox = frameNorm(frame, (detection.xmin, detection.ymin, detection.xmax, detection.ymax))
            cv2.putText(frame, labelMap[detection.label], (bbox[0] + 10, bbox[1] + 20), cv2.FONT_HERSHEY_TRIPLEX, 0.5, 255)
            cv2.putText(frame, f"{int(detection.confidence * 100)}%", (bbox[0] + 10, bbox[1] + 40), cv2.FONT_HERSHEY_TRIPLEX, 0.5, 255)
            cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), color, 2)
        # Show the frame
        cv2.imshow(name, frame)

    while True:
        inRgb = qRgb.tryGet()
        inDet = qDet.tryGet()

        if inRgb is not None:
            frame = inRgb.getCvFrame()

        if inDet is not None:
            detections = inDet.detections


        if frame is not None:
            displayFrame("rgb", frame)

        if cv2.waitKey(1) == ord('q'):
            break

▌参考资料

https://www.oakchina.cn/2023/02/23/yolov7-blob/
https://docs.oakchina.cn/en/latest/
https://www.oakchina.cn/selection-guide/


OAK中国
| OpenCV AI Kit在中国区的官方代理商和技术服务商
| 追踪AI技术和产品新动态

戳「+关注」获取最新资讯↗↗

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/371033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7安装

centos7安装制作U盘启动盘下载镜像下载 UltralISO制作启动盘使用U盘安装系统修改模式为 UEFI调整BOOT option保存重启进入安装界面安装图形界面安装搜狗输入法制作U盘启动盘 下载镜像 去官网下载镜像&#xff0c;找到 mirrors链接&#xff08;速度快&#xff09; 选择一个中…

OpenAI是什么

OpenAI是一家非营利性人工智能研究公司&#xff0c;致力于研究人工智能和其他机器学习技术。OpenAI 会和谷歌、苹果、IBM 等知名公司创办的其它一系列项目一道探索先进计算机技术&#xff0c;解决面部识别或语言翻译等问题。 OpenAI 是由马斯克、奥特曼等人 2015 年联合创办的人…

奔四的路上,依旧倔强的相信未来

本文首发于2022年12月31日 原标题: 奔四的路上,依旧倔强的相信未来!–我的2022年终总结 读大学那几年,一直保持着写日记和做计划的习惯,还记得大学毕业刚开始打工的时候,我的床头的墙上一定会画一张表,写上一个月的计划和一周的计划 计划也会有完不成的时候,但加深了…

【Hello Linux】初识冯诺伊曼体系

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍冯诺伊曼体系 冯诺伊曼体系 冯诺伊曼体系结构的合理性 我们在Linux的第一篇博客中讲解了第一台计算机的发明是为了解决导弹的…

实例7:树莓派呼吸灯

实例7&#xff1a;树莓派呼吸灯 实验目的 通过背景知识学习&#xff0c;了解digital与analog的区别。通过GPIO对外部LED灯进行呼吸控制&#xff0c;熟悉PWM技术。 实验要求 通过python编程&#xff0c;用GPIO控制LED灯&#xff0c;使之亮度逐渐增大&#xff0c;随后减小&am…

交换字符使得字符串相同[贪心]

贪心前言一、交换字符使得字符串相同二、贪心1、分析问题的思路过程2、go总结参考资料前言 贪心算法&#xff0c;必须先看清楚有哪些选择&#xff0c;才能在这些选择的基础上进行贪心&#xff0c;做最优选择&#xff0c;除此之外&#xff0c;还得看局部最优会不会形成全局最优…

8 百度接口

0 建议学时 2学时 1 简介 百度人工智能平台-站在巨人的肩膀上 https://ai.baidu.com/ 控制台->立即注册 百度人工智能平台 APP Key 和 Secret Key AI接入指南 https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjgn3 百度智能云视频参考 https://abcxueyuan.baidu.com/#/…

2023年最新详细教程!手把手教你搭建Hexo + GitLab个人博客

文章目录前言一、安装和配置环境1.安装 Git2.安装 Node.js二、新建博客项目1.GitLab配置CI/CD自动化部署1.1 GitLab新建项目1.2 GitLab自建Runners1.2.1 下载gitlab-runner1.2.2 注册Runners1.2.3 安装Runners并启动1.3 添加.gitlab-ci.yml文件2.拉取和推送hexo blog2.1 拉取he…

基于遗传算法的配电网故障定位(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

sonarqube 外部扫描器 go vet golangci-lint 无法导入问题

首先&#xff0c;请看[外部分析报告]各种语言的报告生成 go vet 2> govet-report.out#没有golangci-lint&#xff0c;我从网上找到了 golangci-lint run --out-format checkstyle ./... > golangci-lint-report.xml值得注意的是&#xff0c;貌似不支持目录&#xff0c;仅…

6.2 负反馈放大电路的四种基本组态

通常&#xff0c;引入交流负反馈的放大电路称为负反馈放大电路。 一、负反馈放大电路分析要点 如图6.2.1(a)所示电路中引入了交流负反馈&#xff0c;输出电压 uOu_OuO​ 的全部作为反馈电压作用于集成运放的反向输入端。在输入电压 uIu_IuI​ 不变的情况下&#xff0c;若由于…

mysys2+minGW方案编译ffmpeg的最佳实践

一、Win10 64bit编译环境的建立1&#xff09;从http://www.msys2.org/下载 msys2-x86_64-xxx.exe2&#xff09; 安装msys2到默认路径 C:\msys64\3&#xff09; 运行MSYS2 w644&#xff09;执行 pacman -Syu 更新系统当出现提示时&#xff0c;选择y5) 当窗口关闭时&#xff0c;重…

JavaScript函数

目录 定义函数 调用函数 函数参数 函数返回值 匿名函数 箭头函数 使用JavaScript编程时&#xff0c;函数是一种非常有用的编程结构&#xff0c;用于执行特定的任务并返回结果。函数可以重复使用&#xff0c;因此您只需编写一次代码&#xff0c;即可在需要时多次调用该代码…

深入解析dubbo的延迟暴露

一、引子 最近搭建了一个新的Java工程&#xff0c;主要是提供dubbo服务给其他业务用的。突然想起之前dubbo服务都会配置延迟暴露来解决平滑发布的问题&#xff0c;但是好像现在新的Java项目都没有配置延迟暴露了&#xff0c;觉得很奇怪&#xff0c;所以去研究了一下关于dubbo延…

Delete `␍`eslint(prettier/prettier) in vscode 的解决方案

错误描述从 Github 仓库拉取代码&#xff0c;使用 vscode 打开&#xff0c;页面报错&#xff0c;每一行都爆红 &#xff08;如下图&#xff09;问题原因由于历史原因&#xff0c;windows下和linux下的文本文件的换行符不一致。Windows在换行的时候&#xff0c;使用了换行符CRLF…

ROG配置ubuntu20.04.5双系统要点

win11ubuntu20.04.5 1. BIOS设置 开机长按F2进入bios设置&#xff0c;修改advanced参数&#xff1a; boot -> 关闭fast bootsecurity -> 关闭secure boot设置VMD controller为Disabled&#xff08;其他电脑是修改硬盘的SATA和ACHI模式&#xff09;。但是改了之后windo…

【大数据离线开发】8.1 Hive介绍和架构

Hive&#xff1a;数据分析引擎 了解 大数据的终极目标: 使用SQL语句来处理大数据 Hadoop的体系架构中: Hive:支持SOLPig:支持PiqLatin Spark的体系架构中: Spark SQL:类似Hive&#xff0c;支持SOL、支持DSL 另一个&#xff1a;Impala 8.1 什么是Hive&#xff1f; 起源自f…

Linux 离线安装Ruby和RubyGems环境

文章目录简介1. 安装GCC环境2. 安装ruby3. 安装 RubyGems4. 安装 redis-xxx.gem提示&#xff1a;以下是本篇文章正文内容&#xff0c;Redis系列学习将会持续更新 简介 在学习 Redis 集群对这几个词的概念和关系感混乱&#xff0c;故在此对其梳理。 Ruby 是什么&#xff1f; 它…

鼠标更换指针图案和更改typora的主题

鼠标更换指针图案 由此偶然看见好几个朋友都使用了新的图案替换掉了原有的鼠标图案&#xff0c;今天寻思自己也换一个图案 主要是觉得鼠标大一点儿会好看一些&#xff0c;所以就找了一些教程 官方教程&#xff0c;小的变动 当然最多的是官方教程&#xff0c;如果你只是想要…

Web Spider Ast-Hook 浏览器内存漫游 - 数据检索

文章目录一、资源下载二、通过npm安装anyproxy模块三、anyproxy的介绍以及基本使用1. anyproxy的功能介绍2. anyproxy的基本使用四、给浏览器挂代理五、实操极验demo案例总结提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、资源下载 Github&#x…