迁移修改
一键迁移
修改“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; }
父主题: 模型迁移