实操以J5 OE1.1.60对应的docker为例
1. grid_sample算子功能解析
1.1 理论介绍
pytorch中调用接口:
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]

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

2. 使用grid_sample算子构建一个网络
先看一下地平线提供的算子支持与约束列表:

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

3. 走PTQ进行模型转换与编译
对应config.yaml文件:
使用的是OE1.1.60对应的docker

全一段,且都在BPU上
4. 走QAT进行模型转换与编译
对应的是plugin-fx,关于该部分基础解读可见另外一篇文章:https://blog.csdn.net/weixin_45377629/article/details/131354320
可运行代码如下:

可视化效果:




