迁移修改
一键迁移
修改“tools/train.py”脚本。
在import torch部分后添加一键迁移逻辑:
import torch_npu from torch_npu.contrib import transfer_to_npu
修改RotateIOU算子
RotateIOU在PointPillars模型推理阶段使用到,由于NPU不支持RotateIOU算子,将该算子使用CPU上运算会非常慢,因此使用多进程程序多核跑加速推理。
修改“pcdet/datasets/kitti/kitti_object_eval_python/eval.py”脚本。
修改前:
def calculate_iou_partly(gt_annos, dt_annos, metric, num_parts=50):
for num_part in split_parts:
gt_annos_part = gt_annos[example_idx:example_idx + num_part]
dt_annos_part = dt_annos[example_idx:example_idx + num_part]
if metric == 0:
gt_boxes = np.concatenate([a["bbox"] for a in gt_annos_part], 0)
dt_boxes = np.concatenate([a["bbox"] for a in dt_annos_part], 0)
overlap_part = image_box_overlap(gt_boxes, dt_boxes)
elif metric == 1:
loc = np.concatenate(
[a["location"][:, [0, 2]] for a in gt_annos_part], 0)
dims = np.concatenate(
[a["dimensions"][:, [0, 2]] for a in gt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in gt_annos_part], 0)
gt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
loc = np.concatenate(
[a["location"][:, [0, 2]] for a in dt_annos_part], 0)
dims = np.concatenate(
[a["dimensions"][:, [0, 2]] for a in dt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in dt_annos_part], 0)
dt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
overlap_part = bev_box_overlap(gt_boxes, dt_boxes).astype(
np.float64)
elif metric == 2:
loc = np.concatenate([a["location"] for a in gt_annos_part], 0)
dims = np.concatenate([a["dimensions"] for a in gt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in gt_annos_part], 0)
gt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
loc = np.concatenate([a["location"] for a in dt_annos_part], 0)
dims = np.concatenate([a["dimensions"] for a in dt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in dt_annos_part], 0)
dt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
overlap_part = d3_box_overlap(gt_boxes, dt_boxes).astype(
np.float64)
else:
raise ValueError("unknown metric")
parted_overlaps.append(overlap_part)
example_idx += num_part
overlaps = []
example_idx = 0
for j, num_part in enumerate(split_parts):
parted_overlaps[i] = overlap_part
修改后:
def calculate_iou_partly_single(gt_annos, dt_annos, example_idx, split_parts, i, parted_overlaps, metric):
gt_annos_part = gt_annos[example_idx: example_idx + split_parts[i]]
dt_annos_part = dt_annos[example_idx: example_idx + split_parts[i]]
if metric == 0:
gt_boxes = np.concatenate([a["bbox"] for a in gt_annos_part], 0)
dt_boxes = np.concatenate([a["bbox"] for a in dt_annos_part], 0)
overlap_part = image_box_overlap(gt_boxes, dt_boxes)
elif metric == 1:
loc = np.concatenate(
[a["location"][:, [0, 2]] for a in gt_annos_part], 0)
dims = np.concatenate(
[a["dimensions"][:, [0, 2]] for a in gt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in gt_annos_part], 0)
gt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
loc = np.concatenate(
[a["location"][:, [0, 2]] for a in dt_annos_part], 0)
dims = np.concatenate(
[a["dimensions"][:, [0, 2]] for a in dt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in dt_annos_part], 0)
dt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
overlap_part = bev_box_overlap(gt_boxes, dt_boxes).astype(
np.float64)
elif metric == 2:
loc = np.concatenate([a["location"] for a in gt_annos_part], 0)
dims = np.concatenate([a["dimensions"] for a in gt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in gt_annos_part], 0)
gt_boxes = np.concatenate([loc, dims, rots[..., np.newaxis]], axis=1)
loc = np.concatenate([a["location"] for a in dt_annos_part], 0)
dims = np.concatenate([a["dimensions"] for a in dt_annos_part], 0)
rots = np.concatenate([a["rotation_y"] for a in dt_annos_part], 0)
dt_boxes = np.concatenate(
[loc, dims, rots[..., np.newaxis]], axis=1)
overlap_part = d3_box_overlap(gt_boxes, dt_boxes).astype(
np.float64)
else:
raise ValueError("unknown metric")
parted_overlaps[i] = overlap_part
在“pcdet/datasets/kitti/kitti_object_eval_python/ rotate_iou.py”文件中新增rotate_iou_cpu_eval函数:
def rotate_iou_cpu_eval(dev_boxes, dev_query_boxes, criterion=-1):
num_boxes = dev_boxes.shape[0]
num_qboxes = dev_query_boxes.shape[0]
dev_iou = np.zeros((num_boxes, num_qboxes))
for box_i in range(num_boxes):
for qbox_i in range(num_qboxes):
dev_iou[box_i, qbox_i] = devRotateIoUEval(dev_query_boxes[qbox_i], dev_boxes[box_i], criterion)
return dev_iou
修改NMS算子
nms_cuda算子在昇腾NPU上无法使用,需要迁移到CPU上计算。
修改路径:“pcdet/ops/iou3d_nms/src/iou3d_cpu.cpp”。
修改(新增)内容如下所示:
int nms_cpu(at::Tensor boxes, at::Tensor keep, float nms_overlap_thresh) {
int boxes_num = boxes.size(0);
const float * boxes_data = boxes.data<float>();
long * keep_data = keep.data<long>();
int num_to_keep = 0;
std::vector<int> boxIndex;
for (int i = 0; i < boxes_num; i++) {
boxIndex.push_back(i);
}
while (boxIndex.size() > 0) {
int keep_box_index = boxIndex[0];
keep[num_to_keep++] = keep_box_index;
boxIndex.erase(boxIndex.begin());
for (auto it = boxIndex.begin(); it != boxIndex.end(); ) {
float iou_bev_v = iou_bev(boxes_data + keep_box_index * 7, boxes_data + (*it) * 7);
if (iou_bev_v > nms_overlap_thresh) {
it = boxIndex.erase(it);
} else {
it++;
}
}
}
return num_to_keep;
}
父主题: 模型迁移