rknn上部署人体关键点检测模型(2)

rknn上部署人体关键点检测模型(2)模型转换、部署 源代码仓库地址为:https://github.com/HRNet/Lite-HRNet.git,不过更推荐使用开源项目open-mmlab(https://openmmlab.com/),该项目有多种类丰富的开源代码,实现了分类、检测 、识别、定位等多种模型。其中的mmpose项目

模型转换、部署

源代码仓库地址为:https://github.com/HRNet/Lite-HRNet.git,不过更推荐使用开源项目open-mmlab(https://openmmlab.com/),该项目有多种类丰富的开源代码,实现了分类、检测

、识别、定位等多种模型。其中的mmpose项目(https://github.com/open-mmlab/mmpose.git)即实现了lite-hrnet模型,我们可以通过mmpose项目中的脚本,轻松的训练、导出模型。

rknn的部署一般先要将模型转换为onnx模型,然后将onnx模型转换为rknn模型,其中转换为onnx模型的脚本我们可以利用mmpose/tools/deployment/pytorch2onnx.py脚本进行转换。也可以参考源代码通过以下步骤导入,转换模型:

import argparse

import mmcv

import numpy as np

import torch

from mmcv.runner import load_checkpoint

from time import time

from models import build_posenet

from mmcv.onnx.symbolic import register_extra_symbolics

 

def parse_args():

    parser = argparse.ArgumentParser(

        description=’Convert models to ONNX’)

    parser.add_argument(‘–config’,

default=”configs/top_down/lite_hrnet/coco/litehrnet_30_coco_256x192.py”,

                        help=’config file path’)

    parser.add_argument(‘–checkpoint’,

                        default=”litehrnet_30_256x192.pth”,

                        help=’checkpoint file’)

    parser.add_argument(‘–output-file’, type=str, default=’lite_hr_30_256.onnx’)

    parser.add_argument(

        ‘–shape’,

        type=int,

        default=(1, 3, 256, 192),

        help=’input size’)

    args = parser.parse_args()

    return args

 

 

if __name__ == ‘__main__’:

    args = parse_args()

 

    cfg = mmcv.Config.fromfile(args.config)

    # build the model

    model = build_posenet(cfg.model)

    

    if hasattr(model, ‘forward_dummy’):

        model.forward = model.forward_dummy

    else:

        raise NotImplementedError(

            ‘Please implement the forward method for exporting.’)

 

    checkpoint = load_checkpoint(model, args.checkpoint,map_location=’cpu’)

 

    model.eval()

    pytorch2onnx(

        model,

        args.shape,

        output_file=args.output_file)

 

这样model就是导入的模型了,之后使用pytorch2onnx函数即可进行转换。

def pytorch2onnx(model,

                 input_shape,

                 output_file=’a.onnx’):

    model.eval()

one_img = torch.randn(input_shape)

 

    register_extra_symbolics(11)

    torch.onnx.export(

        model,

        one_img,

        output_file,

        export_params=True,

        do_constant_folding=True,

        opset_version=11

        )

 

    print(f’Successfully exported ONNX model: {output_file}’)

 

导出模型过程中可能出现RuntimeError: Failed to export an ONNX attribute ‘onnx::Gather’, since it’s not constant, please try to make things (e.g., kernel size) static if possible问题。官方代码中使用了自适应的池化函数adaptive_avg_pool2d,导致无法正常导出。需要修改官方github中的models\backbones\litehrnet.py,将其中的自适应池化函数改为正常的池化函数,因此需要计算出正常池化函数的几个参数:核大小kernel_size、步长stride_size、填充padding(一般都是0,可以忽略这个参数)。修改其中的CrossResolutionWeighting类的forward。

 def forward(self, x):

        #mini_size = x[-1].size()[-2:]

        #out = [F.adaptive_avg_pool2d(s, mini_size) for s in x[:-1]] + [x[-1]]

        

        stridesize_list, kernelsize_list, output_size = self.get_avgpool_para(x)

        out = [torch.nn.AvgPool2d(kernel_size=kernelsize_list.tolist(),stride=stridesize_list.tolist())(s) for s,kernel_size,stride_size in

               zip(x[:-1],kernelsize_list,stridesize_list) ] + [x[-1]]

        

 

        out = torch.cat(out, dim=1)        

        out = self.conv1(out)

        out = self.conv2(out)

        out = torch.split(out, self.channels, dim=1)

        out = [

            s * F.interpolate(a, size=s.size()[-2:], mode=’nearest’)

            for s, a in zip(x, out)

        ]

        return out

get_avgpool_para实现如下:

def get_avgpool_para(self,x):

    output_size = np.array(x[-1].size()[-2:])

    stride_size_list = []

    kernel_size_list = []

    for index in range(len(x)):

        input_size = np.array(x[index].size()[-2:])

        stride_size = np.floor(input_size / output_size ).astype(np.int32)

        kernel_size = input_size – (output_size – 1) * stride_size 

        stride_size_list.append(stride_size)

        kernel_size_list.append(kernel_size)

    return stride_size_list,kernel_size_list,output_size 

 

 

转换为onnx模型后通过rknn中onnx转rknn脚本进行转换。将onnx模型转换为rknn模型。rknn开发套件地址为:https://github.com/rockchip-linux/rknn-toolkit2.git

RKNN-Toolkit2是一款软件开发套件,供用户在PC和瑞芯微NPU平台(RK3566、RK3568、RK3588、RK3588S、RV1103、RV1106)上进行模型转换、推理和性能评估。RKNN-Toolkit-Lite2为Rockchip NPU平台(RK3566、RK3568、RK3588、RK3588S)提供Python编程接口,帮助用户部署RKNN模型,加速AI应用落地。

我们可以按照rknn-toolkit2/examples/onnx/yolov5/的例子,修改后转换我们已经生成了的onnx模型。

注意事项:

rknn.config中预处理方式与模型预处理方式要相同,即mean_values、std_values要与实际训练过程中预处理方式相同。mean_values:输入的均值。参数格式是一个列表,列表中包含一个或多个均值子列表,多输入模型对应多个子列表,每个子列表的长度与该输入的通道数一致,例如[[128,128,128]],表示一个输入的三个通道的值减去 128。如果quant_img_RGB2BGR设置成 True,则优先做 RGB2BGR 转换,再做减均值。 std_values:输入的归一化值。参数格式是一个列表,列表中包含一个或多个归一化值子列表,多输入模型对应多个子列表,每个子列表的长度与该输入的通道数一致, 18 例如[[128,128,128]],表示设置一个输入的三个通道的值减去均值后再除以128。如果 quant_img_RGB2BGR 设置成 True,则优先做 RGB2BGR 转换,再减均值和除以归一化值。

如果要连接rknn设备进行推理测试需要在config及init_runtime中设置target:指定 RKNN 模型是基于哪个目标芯片平台生成的。目前支持“rk3566”、“rk3568”、“rk3588”、“rv1103”、“rv1106”。值得注意的是init_runtime中参数为target而config中参数为target_platform。

转换为rknn模型后可以通过rknn.eval_perf(inputs=[image], is_print=True)评估模型性能,查看每层消耗的时间,针对性修改模型从而提高模型的推理速度,降低输入层尺寸也是提速度最简单的方式之一。

rk芯片可能存在的问题:

 

(1)在转换过程中,报错有些算子不支持,可以自己修改比较通用的算子后重新转换模型。

(2)算子支持不同步,如在3568上支持的算子在3588上反而不支持。

(3)算子在cpu上执行,有些层的算子在硬件cpu上执行,导致速度很慢。

 **************************************宣传分割线**********************************

深圳原数科技提供嵌入式软硬件、服务器、APP、代工生产一站式服务,对国产MCU和SOC(全志,瑞芯微)有丰富开发经验,特别是在低成本的wifi图传和AI视觉识别领域有深厚沉淀,相关产品出货超过50W台。近来顺应市场需求陆续推出人形追踪云台、虚拟背景直播一体机等落地产品,欢迎联系咨询,李生13686461548微信同号,也可官网查询相关信息www.atom-math.com

rknn上部署人体关键点检测模型(2)

今天的文章rknn上部署人体关键点检测模型(2)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/57601.html

(0)
编程小号编程小号
上一篇 2023-08-25
下一篇 2023-08-25

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注