1.bev参考算法模型信息
板端或者X86端运行hrt_model_exec model_info命令获取模型输入输出信息,参考命令如下:
使用以上命令获取的bev模型输入信息分别如下所示:
模型 | input name | input shape | layout | 数据格式 | 量化scale |
|---|---|---|---|---|---|
IPM | input[0] | (6,3,512,960) | NCHW | NV12 | --- |
IPM | input[1] | (6,2,128,128) | NCHW | int16 | 0.0078125 |
LSS | input[0] | (6,3,256,704) | NCHW | NV12 | --- |
LSS | input[1] | (10,2,128,128) | NCHW | int16 | 0.0078125 |
LSS | input[2] | (10,2,128,128) | NCHW | int16 | 0.03125 |
GKT | input[0] | (6,3,512,960) | NCHW | NV12 | --- |
GKT | input[1]-input[9] | (6,2,64,64) | NCHW | int16 | 0.00390625 |
2. 图像输入生成
根据模型输入信息,需要将6张图像转成NV12格式后拼接在一起,然后导出为.bin文件作为板端模型的input[0]输入,图像格式转为NV12代码如下:
orig_img = cv2.imread(img_path)
orig_img = Image.fromarray(orig_img)
orig_img = pil_to_tensor(orig_img)
resize_hw = (
int(resize_size[0]),
int(resize_size[1]),
)
#resize后的图像大小,lss参考算法为(396, 704)
resize_size = (540, 960)
#input_size用于裁剪 resized image
#模型输入的图像大小,lss参考算法为(256, 704)
input_size = (512, 960)
orig_imgs = []
#输入的6V图像路径
inputs = './single_frame/imgs'
#这里可以定义输入图像的顺序,需要与训练时输入的顺序一致
input_list=["01.jpg","02.jpg","03.jpg","04.jpg","05.jpg","06.jpg"]
for i, img in enumerate(input_list):
img = os.path.join(inputs, img)
img, orig_shape = process_img(img, resize_size, input_size)
orig_imgs.append({"name": i, "img": img})
input_imgs = []
for image in orig_imgs:
image=image["img"].permute(0,2,3,1).squeeze(0)
#bgr to nv12
image=image.numpy().astype(np.uint8)
height, width = image.shape[0], image.shape[1]
yuv420p = cv2.cvtColor(image, cv2.COLOR_BGR2YUV_I420)
yuv420p = yuv420p.reshape((height * width * 3 // 2, ))
y = yuv420p[:height * width]
uv_planar = yuv420p[height * width:].reshape((2, height * width // 4))
uv_packed = uv_planar.transpose((1, 0)).reshape((height * width // 2, ))
nv12 = np.zeros_like(yuv420p)
nv12[:height * width] = y
nv12[height * width:] = uv_packed
input_imgs.append(nv12)
input_imgs=np.array(input_imgs)
input_imgs=input_imgs.reshape(6 * 3 * input_size[0] * input_size[1] // 2)
#导出为bin
input_imgs.tofile("inputnv12.bin")
ipm和gkt参考算法的resize_size = (540, 960)和input_size = (512, 960),lss参考算法的resize_size=(396, 704),input_size = (256, 704)。
3. 采样点points输入生成
points输入的生成需要以下4个步骤:
相机内外参数获取;
生成homography矩阵;
根据homography矩阵导出浮点points;
对浮点points做int16量化。
3.1 相机内外参数获取
上述脚本中的参数意义为:
--data-path :配置为bev参考算法运行时构建的meta文件夹路径
--save-path:生成相机内外参的保存路径;
--save-by-city:nuscenes数据集中不同城市的相机内外参可能是不同的,为了便于区分,所以用city 名称命名生成的相机内外参数;
- --version:使用的nuscenes数据据版本,可选为v1.0-mini和v1.0-trainval,默认为v1.0-mini;
脚本运行结束后,会在--save-path下生成boston和singapore两个文件夹,文件夹中包含相机内参/外参矩阵,目录结构如下所示:
这里生成了boston和singapore两个文件夹,是因为nuscenes数据集在boston和singapore location下采集的数据的相机参数不同。
3.2 生成homography矩阵
python3 ./tools/homography_generator.py --sensor2ego-translation ./boston/sensor2ego_translation.npy --sensor2ego-rotation ./boston/sensor2ego_rotation.npy --camera-intrinsic ./boston/camera_intrinsic.npy --save-path ./boston
上述脚本的参数意义为:
--sensor2ego-translation:即上节生成的sensor2ego_translation.npy
--sensor2ego-rotation:即上节生成的sensor2ego_rotation.npy
--camera-intrinsic: 内参矩阵的路径,即上节生成的camera_intrinsic.npy
--save-path:保存路径
3.3 导出浮点Points
获取homography矩阵后,使用tools文件夹下的reference_points_generator.py脚本导出浮点类型的points,参考命令如下:
可以通过修改config文件路径导出ipm、gkt参考算法的Points.
上述脚本的参数意义为:
--config:config文件的路径 ,脚本中以bev_mt_lss参考算法为例
--homography:上节中导出homo矩阵的路径
--save_path:保存路径
输出文件说明:
ipm有1个points输入,所以会在save_path下生成一个reference_points0.npy;
lss有2个points输入,所以会在save_path下生成一个reference_points0.npy和reference_points1.npy;
gkt有 9个points,所以会在save_path下生成一个reference_points0.npy到reference_points8.npy等9个npy文件;
3.4 对浮点Points做量化
导出浮点Points后 ,需要对其做int16量化。这里提供了给浮点Points进行int16量化的process_reference_points.py,源代码为:
parser = argparse.ArgumentParser()
parser.add_argument(
"--model",
"-m",
type=str,
required=True,
help="Selectable as ipm,lss,gkt",
)
parser.add_argument(
"--points_path",
"-p",
type=str,
required=True,
help="path of points(float32)"
)
parser.add_argument(
"--save_path",
type=str,
default=".",
help="path for saving point(int16)",
)
known_args, unknown_args = parser.parse_known_args()
return known_args, unknown_args
def process_reference_points(model, points_path, save_path):
for i, name in enumerate(os.listdir(points_path)):
if model=="ipm":
scale = [0.0078125]
elif model == "gkt":
scale = [
0.00390625, 0.00390625, 0.00390625, 0.00390625, 0.00390625,
0.00390625, 0.00390625, 0.00390625, 0.00390625]
if model == "lss":
scale = [0.0078125, 0.03125]
path= os.path.join(points_path, name)
print(path)
points = np.load(path)
idx=int(path[-5])
points = points.transpose(0, 3, 1, 2) / scale[idx]
print(points.shape)
points = np.floor(points + 0.5)
points = np.clip(points, -32768, 32767)
points = points.astype(np.int16)
save_name= os.path.join(save_path, name)[2:-4]
print("save_name:",save_name)
points.tofile(save_name+".bin")
print("----save points OK----")
if name == "__main__":
args, args_env = parse_args()
if args_env:
setup_args_env(args_env)
process_reference_points(args.model, args.points_path, args.save_path)
参考命令如下:
命令中的参数意义是:
--model:参考算法类型,可选为lss,ipm,gkt
--points_path:浮点points路径,注意每个参考算法在singapore和boston location下的浮点points是不同的
--save_path:保存路径
输出文件说明:
ipm有1个points输入,所以会在save_path下生成一个reference_points1.bin;
lss有2个points输入,所以会在save_path下生成一个reference_points0.bin和reference_points1.bin;
gkt有 9个points,所以会在save_path下生成一个reference_points0.bin到reference_points8.bin等9个bin文件。
至此,bev参考算法板端输入数据的准备完成。


