【gridsample】地平线如何支持gridsample算子

文章目录

  • 1. grid_sample算子功能解析
    • 1.1 理论介绍
    • 1.2 代码分析
      • 1.2.1 x,y取值范围[-1,1]
      • 1.2.2 x,y取值范围超出[-1,1]
  • 2. 使用grid_sample算子构建一个网络
  • 3. 走PTQ进行模型转换与编译

实操以J5 OE1.1.60对应的docker为例

1. grid_sample算子功能解析

该段主要参考:https://blog.csdn.net/jameschen9051/article/details/124714759,不想看理论可直接跳至第2节

1.1 理论介绍

在图像处理领域,grid_sample 是一个常用的操作,通常用于对图像进行仿射变换或透视变换。它可以在给定输入图像和一个变换矩阵的情况下,对输入图像进行采样,生成一个新的输出图像。
pytorch中调用接口:

torch.nn.functional.grid_sample(input,grid,mode='bilinear',padding_mode='zeros',align_corners=None)
  • input:输入特征图,可以是四维或者五维张量,本文主要以四维为例进行介绍,表示为 (N,C,Hin,Win) 。
  • grid:采样网格,包含输出特征图的shape大小(Hout、Wout),每个 网格值 通过变换对应到输入特征图的采样点位,当对应四维input时,其张量形式为(N,Hout,Wout,2),其中最后一维大小必须为2,如果输入input为五维张量,那么最后一维大小必须为3。

为什么最后一维必须为2或者3?因为grid的最后一个维度实际上代表一个坐标(x,y)或者(x,y,z),对应到输入特征图的二维或三维特征图的坐标维度,x,y取值范围一般为[-1,1],该范围映射到输入特征图的全图,一通操作变换后对应于输出图像上的一个像素点。

  • mode:采样模式,可以是 ‘bilinear’(双线性插值)、 ‘nearest’(最近邻插值)、‘bicubic’ 双三次插值。。
  • padding_mode:填充模式,用于处理采样时超出输入图像边界的情况,可以是 ‘zeros’ 、 ‘border’、 ‘reflection’。
  • align_corners:一个布尔值,用于指定特征图坐标与特征值对应方式,设定为TRUE时,特征值位于像素中心。
    总的说来,grid_sample 算子会根据给定的网格(grid)在输入图像上进行采样,然后根据选择的插值方法在采样点周围的像素上进行插值,最终生成输出图像。

画一个在BEV方案中grid_sample原理图来帮助理解grid_sample怎么回事:
在这里插入图片描述

1.2 代码分析

对照代码进行下一步解读。
假设输入shape为(N,C,H_in,W_in),grid的shape设定为(N,H_out,W_out,2),使用双线性差值,填充模式为zeros,align_corners需要设置为True。

首先根据input和grid设定,输出特征图tensor的shape为(N,C,H_out,W_out),输出特征图上每一个cell上的值与grid最后一维(x,y)息息相关,那么如何计算输出tensor上每一个点的值?

首先,通过(x,y)找到输入特征图上的采样位置:由于x,y取值范围为[-1,1],为了便于计算,先将x,y取值范围调整为[0,1],方法是(x+1)/2,(y+1)/2。因此,将x,y映射为输入特征图的具体坐标位置:(w-1)(x+1)/2、(h-1)(y+1)/2。
将x,y映射到输入特征图实际坐标后,取该坐标附近四个角点特征值,通过四个特征值坐标与采样点坐标相对关系进行双线性插值,得到采样点的值。

注意:x,y映射后的坐标可能是输入特征图上任意位置。

基于上面的思路,可以进行一个简单的自定义实现。根据指定shape生成input和grid,之后取grid中的第一个位置中的x,y,根据x,y从input中通过双线性插值计算出output第一个位置的值。类比使用pytorch中的grid_sample算子生成output。

其它的看代码注释即可。

1.2.1 x,y取值范围[-1,1]

import torch
import numpy as npdef grid_sample(input, grid):N, C, H_in, W_in = input.shapeN, H_out, W_out, _ = grid.shapeoutput = np.random.random((N,C,H_out,W_out))for i in range(N):for j in range(C):for k in range(H_out):for l in range(W_out):param = [0.0, 0.0]# 通过(w-1)*(x+1)/2、(h-1)*(y+1)/2将x,y映射为输入特征图的具体坐标位置。param[0] = (W_in - 1) * (grid[i][k][l][0] + 1) / 2param[1] = (H_in - 1) * (grid[i][k][l][1] + 1) / 2x0 = int(param[0])  # int取整规则:将小数部分截断去掉。x1 = x0 + 1y0 = int(param[1])y1 = y0 + 1param[0] -= x0  # 此时param里装的是小数部分param[1] -= y0# 双线性插值left_top = input[i][j][y0][x0] * (1 - param[0]) * (1 - param[1])left_bottom = input[i][j][y1][x0] * (1 - param[0]) * param[1]right_top = input[i][j][y0][x1] * param[0] * (1 - param[1])right_bottom = input[i][j][y1][x1] * param[0] * param[1]result = left_bottom + left_top + right_bottom + right_topoutput[i][j][k][l] = resultreturn outputif __name__=='__main__':N, C, H_in, W_in, H_out, W_out = 1, 1, 4, 4, 2, 2input = np.random.random((N,C,H_in,W_in))# np.random.random()范围是[0,1),想要[a,b)的数据,需要(b-a)*np.random.random() + agrid = -1 + 2*np.random.random((N,H_out,W_out,2))  # 最后一维2,生成了坐标out = grid_sample(input, grid)print(f'自定义实现输出结果:\n{out}')input = torch.from_numpy(input)grid = torch.from_numpy(grid)# 注意:这儿align_corners=Trueoutput = torch.nn.functional.grid_sample(input,grid,mode='bilinear', padding_mode='zeros',align_corners=True)print(f'grid_sample输出结果:\n{output}')

输出
在这里插入图片描述
从输出结果上看,与pytorch基本一致。

注意:这里没有对超出[-1,1]范围的x,y值做处理,只能处理四维input,五维input的实现思路与这里基本一致:再加一层循环,内插算法改为3维。。

1.2.2 x,y取值范围超出[-1,1]

考虑到(x,y)取值范围可能越界,pytorch中的padding_mode设置就是对(x,y)落在输入特征图外边缘情况进行处理,一般设置’zero’,也就是对靠近输入特征图范围以外的采样点进行0填充,如果不进行处理显然会造成索引越界。要解决(x,y)越界问题,可以进行如下修改:

import torch
import numpy as npdef grid_sample(input, grid):N, C, H_in, W_in = input.shapeN, H_out, W_out, _ = grid.shapeoutput = np.random.random((N,C,H_out,W_out))for i in range(N):for j in range(C):for k in range(H_out):for l in range(W_out):param = [0.0, 0.0]# 通过(w-1)*(x+1)/2、(h-1)*(y+1)/2将x,y映射为输入特征图的具体坐标位置。param[0] = (W_in - 1) * (grid[i][k][l][0] + 1) / 2param[1] = (H_in - 1) * (grid[i][k][l][1] + 1) / 2x1 = int(param[0] + 1)  # int取整规则:将小数部分截断去掉。x0 = x1 - 1 y1 = int(param[1] + 1)y0 = y1 - 1param[0] = abs(param[0] - x0)  # 此时param里装的是离x0,y0的距离param[1] = abs(param[1] - y0)# 填充left_top_value, left_bottom_value, right_top_value, right_bottom_value = 0, 0, 0, 0if 0 <= x0 < W_in and 0 <= y0 < H_in:left_top_value = input[i][j][y0][x0]if 0 <= x1 < W_in and 0 <= y0 < H_in:right_top_value = input[i][j][y0][x1]if 0 <= x0 < W_in and 0 <= y1 < H_in:left_bottom_value = input[i][j][y1][x0]if 0 <= x1 < W_in and 0 <= y1 < H_in:right_bottom_value = input[i][j][y1][x1]# 双线性插值left_top = left_top_value * (1 - param[0]) * (1 - param[1])left_bottom = left_bottom_value * (1 - param[0]) * param[1]right_top = right_top_value * param[0] * (1 - param[1])right_bottom = right_bottom_value * param[0] * param[1]result = left_bottom + left_top + right_bottom + right_topoutput[i][j][k][l] = resultreturn outputif __name__=='__main__':N, C, H_in, W_in, H_out, W_out = 1, 1, 4, 4, 2, 2input = np.random.random((N,C,H_in,W_in))# np.random.random()范围是[0,1),想要[a,b)的数据,需要(b-a)*np.random.random() + agrid = -1 + 2*np.random.random((N,H_out,W_out,2))  # 最后一维2,生成了坐标grid[0][0][0] = [-1.2, 1.3]     # 超出[-1,1]的范围out = grid_sample(input, grid)print(f'自定义实现输出结果:\n{out}')input = torch.from_numpy(input)grid = torch.from_numpy(grid)# 注意:这儿align_corners=Trueoutput = torch.nn.functional.grid_sample(input,grid,mode='bilinear', padding_mode='zeros',align_corners=True)print(f'grid_sample输出结果:\n{output}')

输出
在这里插入图片描述

2. 使用grid_sample算子构建一个网络

先看一下地平线提供的算子支持与约束列表:
在这里插入图片描述

据此,构建一个简单的网络,test.py代码如下:

import torch
import torch.nn as nn
import torch.nn.functional as Ffrom horizon_nn.torch import export_onnxclass GridSampleModel(nn.Module):def __init__(self):super(GridSampleModel, self).__init__()self.unitconv = nn.Conv2d(24, 24, (1, 1), groups=3)nn.init.constant_(self.unitconv.weight, 1)nn.init.constant_(self.unitconv.bias, 0)def forward(self, x1, x2):x1 = self.unitconv(x1)x = F.grid_sample(x1,grid=x2,mode='bilinear',padding_mode='zeros',align_corners=True)x = self.unitconv(x)return xif __name__ == "__main__":model = GridSampleModel()model.eval()input_names = ['x1', 'x2']output_names = ['output']x1 = torch.randn((1, 24, 600, 800))x2 = torch.randn((1, 48, 64, 2))export_onnx(model, (x1, x2), 'gridsample.onnx', verbose=True, opset_version=11,input_names=input_names, output_names=output_names)print('convert to gridsampe onnx finish!!!')

运行test.py,生成onnx模型,可视化结构如下图:
在这里插入图片描述

3. 走PTQ进行模型转换与编译

对应config.yaml文件:

# 模型转化相关的参数
model_parameters:onnx_model: './gridsample.onnx'march: "bayes"working_dir: 'model_output'output_model_file_prefix: 'gridsample'# 模型输入相关参数, 若输入多个节点, 则应使用';'进行分隔, 使用默认缺省设置则写None
input_parameters:input_name: "x1;x2"input_type_rt: 'featuremap;featuremap'input_layout_rt: 'NCHW;NCHW'input_type_train: 'featuremap;featuremap'input_layout_train: 'NCHW;NCHW'input_shape: '1x24x600x800;1x48x64x2'norm_type: 'no_preprocess;no_preprocess'# 模型量化相关参数
calibration_parameters:calibration_type: 'skip'# 编译器相关参数
compiler_parameters:compile_mode: 'latency'optimize_level: 'O3'

使用的是OE1.1.60对应的docker

hb_mapper makertbin --config config.yaml --model-type onnx

在这里插入图片描述
全一段,且都在BPU上

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

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

相关文章

Unity 编辑器资源导入处理函数 OnPreprocessAudio :深入解析与实用案例

Unity 编辑器资源导入处理函数 OnPreprocessAudio 用法 点击封面跳转下载页面 简介 在 Unity 中&#xff0c;资源导入是一个非常重要的环节&#xff0c;它决定了资源在项目中的使用方式和效果。Unity 提供了一系列的资源导入处理函数&#xff0c;其中之一就是 OnPreprocessAud…

线性代数(三) 线性方程组

前言 如何利用行列式&#xff0c;矩阵求解线性方程组。 线性方程组的相关概念 用矩阵方程表示 齐次线性方程组&#xff1a;Ax0&#xff1b;非齐次线性方程组&#xff1a;Axb. 可以理解 齐次线性方程组 是特殊的 非齐次线性方程组 如何判断线性方程组的解 其中R(A)表示矩阵A的…

主数据管理案例-中国外运

1、 背景介绍及难点分析 作为世界领先的物流行业整合商、端到端的全程供应链解决方案和一站式物流服务提供商&#xff0c;中国外运非常重视信息化建设&#xff0c;先后投资建设了 300多个信息系统&#xff0c;为中国外运的内部管理和业务运作提供 IT 支持和保障。 由于缺乏统一…

进程间通信的编程方式(IPC)及实验

进程间通信&#xff08;IPC&#xff09;方式 目录 Socket 管道 匿名管道 消息队列 共享内存 信号 远程过程调用 Socket Socket编程是一种在计算机网络中进程间通信的编程方法。Socket提供了一种在不同主机上运行的进程之间传输数据的机制。通过使用Socket API&#xff…

Effective Java笔记(30)优先考虑泛型方法

正如类可以从泛型中受益一般 &#xff0c;方法也一样。静态工具方法尤其适合于泛型化 。 Collections 中的所有“算法”方法&#xff08;例如 binarySearch 和 sort &#xff09;都泛型化了 。 编写泛型方法与编写泛型类型相类似 。 例如下面这个方法&#xff0c;它返回两个集合…

iOS问题记录 - Xcode 15安装低版本iOS模拟器(持续更新)

文章目录 前言开发环境问题描述问题分析1. 定位问题2. 逆向分析2.1. IDA Free2.2. Hopper Disassembler Demo 3. 模拟器日志4. supportedArchs 解决方案最后 前言 最近新需求很多&#xff0c;项目改动很大&#xff0c;开发完成后想测一遍在低版本iOS系统上的兼容性&#xff0c…

分享21年电赛F题-智能送药小车-做题记录以及经验分享

这里写目录标题 前言一、赛题分析1、车型选择2、巡线1、OpenMv循迹2、灰度循迹 3、装载药品4、识别数字5、LED指示6、双车通信7、转向方案1、开环转向2、位置环速度环闭环串级转向3、MPU6050转向 二、调试经验分享1、循迹2、识别数字3、转向4、双车通信5、逻辑处理6、心态问题 …

Docker卸载安装及国内镜像源(详细版)

文章目录 一、卸载已有Docker1、首先判断本地有没有docker&#xff1a;2、判断CentOS下 docker是否在运行&#xff1a;3、停止docker运行&查看状态4、yum查看docker安装的包并卸载5、删除docker安装目录6、查看docker version 二、Docker安装及镜像源配置1、centOS 7 yum源…

Jay17 2023.8.10日报

笔记 【python反序列化】 序列化 类对象->字节流&#xff08;字符串&#xff09; 反序列化 字节流->对象 python反序列化没PHP这么灵活&#xff0c;没这么多魔术方法。 import pickle import os class ctfshow(): def init(self): self.username0 self.password0 d…

【数理知识】求刚体旋转矩阵和平移矩阵,已知 N>=3 个点在前后时刻的坐标,且这 N>=3 点间距离始终不变代表一个刚体

序号内容1【数理知识】自由度 degree of freedom 及自由度的计算方法2【数理知识】刚体 rigid body 及刚体的运动3【数理知识】刚体基本运动&#xff0c;平动&#xff0c;转动4【数理知识】向量数乘&#xff0c;内积&#xff0c;外积&#xff0c;matlab代码实现5【数理知识】最…

轻松预约,尽享美食,详解餐厅预约小程序的设计与实现

随着智能手机的普及和人们生活水平的提高&#xff0c;餐厅预约已经成为人们日常生活中的一部分。为了更好地满足人们的需求&#xff0c;许多餐厅开始使用小程序来提供更方便快捷的预约服务。本文将介绍如何制作一款餐厅预约小程序的详细步骤。 1. 进入乔拓云网后台&#xff0c;…

uni-app微信小程序开发自定义select下拉多选内容篇

分享-2023年资深前端进阶&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 技术框架公司的选型&#xff1a;uni-app uni-ui vue3 vite4 ts 需求分析&#xff1a;微信小程序-uni-ui内容 1、创建一个自定义的下拉&#xff0c;支持多…

OSPF无法建立领居的原因有哪些(第三十五课)

1 配置OSPF 1.1 思路 1&#xff0c;配置IP地址 2&#xff0c;配置OSPF 配置进程号 route-id进入区域宣告网段 配置IP地址 R1路由表 ------------------------------------------------------------------------------ Routing Tables: Public Destinations : 10 …

《人脸识别技术应用安全管理规定(征求意见稿)》,需要关注三个焦点

目录 严防人脸信息采集与滥用 规范人脸识别信息的处理 保障人脸识别技术的安全 人脸识别主要有三类风险 近日&#xff0c;国家互联网信息办公室发布《人脸识别技术应用安全管理规定&#xff08;试行&#xff09;&#xff08;征求意见稿&#xff09;》公开征求意见的通知。 …

Python 模块 locust 性能测试

简介 locust 是 Python 的一个开源的负载测试工具&#xff0c;用于测试网络应用程序的性能和可伸缩性。它使用Python编写&#xff0c;并提供了一个简单易用的语法来定义和执行负载测试。locust模块允许用户模拟大量并发用户并观察系统在高负载下的响应情况。 目录 1. 基本用法…

多线程的实现方式Thread、Runnable、Callable

1.并发和并行 并发&#xff1a;在同一时刻&#xff0c;有多个指令在单个CPU上交替执行。 并行&#xff1a;在同一时刻&#xff0c;有多个指令在多个CPU上同时执行 2.多线程的实现方式 2.1 继承Thread类实现方式 2.2 实现Runnable接口的实现方式 2.3 利用Callable接口和Futur…

基于金融行业的软件测试分析

随着银行业务不断增加&#xff0c;业务模式不断复杂化&#xff0c;对我们的银行软件也要求越来越高&#xff0c;产出高质量的产品也非常重要&#xff0c;下面对银行软件测试进行分析总结。 银行软件集中度高&#xff0c;规模庞大&#xff0c;往往是以系统群的方式存在&#xff…

F. Sum and Product - 思维

分析&#xff1a; 题目中的格式有点像韦达定理&#xff0c;就是对于一元二次方程ax^2 bx c 0有 所以可以推出要找的就是两个点&#xff0c;可以直接二分查找存不存在&#xff0c;这题有很多边界问题&#xff0c;有b^2 - 4ac小于0或者等于0&#xff0c;或者求出来的根在数组中…

【STM32】利用CubeMX对FreeRTOS用按键控制任务

对于FreeRTOS中的操作&#xff0c;最常用的就是创建、删除、暂停和恢复任务。 此次实验目标&#xff1a; 1.创建任务一&#xff1a;LED1每间隔1秒闪烁一次&#xff0c;并通过串口打印 2.创建任务二&#xff1a;LED2每间隔0.5秒闪烁一次&#xff0c;并通过串口打印 3.创建任…