|
- # Copyright 2023 Huawei Technologies Co., Ltd
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- # ============================================================================
-
- """Evaluation for sabl"""
-
- import os
- import time
- import numpy as np
- import mindspore
- from mindspore import nn
- from mindspore import ops
- from mindspore import context, Tensor
- from mindspore.train.serialization import load_checkpoint, load_param_into_net
- from src.sablhead import sablhead, SablInferWithDecoder
- from src.backbone import resnet101
- from src.dataset import create_dataset, data_to_mindrecord_byte_image, voc_data_to_mindrecord
- from src.model_utils.config import config
- from src.model_utils.moxing_adapter import moxing_wrapper
- from src.model_utils.device_adapter import get_device_id
- from src.coco_eval import metrics
- from src.box_utils import default_square_boxes_ltrb
-
- def filter_scores_and_topk(scores, score_thr=0.01, topk=1000, results=None):
- valid_mask = scores > score_thr
- if not valid_mask.any():
- return 0
- scores = scores[valid_mask]
- temp = valid_mask.nonzero()
- valid_idx1 = temp[0][:,None]
- valid_idx2 = temp[1][:,None]
- valid_idxs = np.concatenate((valid_idx1,valid_idx2), 1)
-
- num_topk = min(topk, valid_idxs.shape[0])
- idxs= np.argsort(scores)[::-1]
- scores = scores[idxs]
- scores = scores[:num_topk]
- topk_idxs = valid_idxs[idxs[:num_topk]]
- keep_idxs = topk_idxs[:,0]
- labels = topk_idxs[:,1]
-
- filtered_results = {}
- for k, v in results.items():
- filtered_results[k] = v[keep_idxs]
- return scores, labels, keep_idxs, filtered_results
-
- def decode(bboxes, pred_bboxes):
- assert len(pred_bboxes) == 2
- cls_preds, offset_preds = pred_bboxes
- assert cls_preds.shape[0] == bboxes.shape[0] and offset_preds.shape[0] == bboxes.shape[0]
- decoded_bboxes = bucket2bbox(bboxes, cls_preds, offset_preds,
- 14, 3.0, True)
-
- return decoded_bboxes
-
- def bbox_rescale(bboxes, scale_factor=1.0):
- cx = (bboxes[:, 0] + bboxes[:, 2]) * 0.5
- cy = (bboxes[:, 1] + bboxes[:, 3]) * 0.5
- w = bboxes[:, 2] - bboxes[:, 0]
- h = bboxes[:, 3] - bboxes[:, 1]
- w = w * scale_factor
- h = h * scale_factor
- x1 = cx - 0.5 * w
- x2 = cx + 0.5 * w
- y1 = cy - 0.5 * h
- y2 = cy + 0.5 * h
- rescaled_bboxes = np.stack((x1, y1, x2, y2),axis=-1)
- return rescaled_bboxes
-
- def bucket2bbox(proposals,
- cls_preds,
- offset_preds,
- num_buckets,
- scale_factor=1.0,
- clip_border=True):
-
- side_num = int(np.ceil(num_buckets / 2.0))
- cls_preds = cls_preds.reshape(-1, side_num)
- offset_preds = offset_preds.reshape(-1, side_num)
-
- scores = ops.Softmax(-1)(Tensor(cls_preds))
- score_topk, score_label = ops.TopK(sorted=True)(scores, 2)
- score_topk = score_topk.asnumpy()
- score_label = score_label.asnumpy()
-
- rescaled_proposals = bbox_rescale(proposals, scale_factor)
-
- pw = rescaled_proposals[..., 2] - rescaled_proposals[..., 0]
- ph = rescaled_proposals[..., 3] - rescaled_proposals[..., 1]
- px1 = rescaled_proposals[..., 0]
- py1 = rescaled_proposals[..., 1]
- px2 = rescaled_proposals[..., 2]
- py2 = rescaled_proposals[..., 3]
-
- bucket_w = pw / num_buckets
- bucket_h = ph / num_buckets
-
- score_inds_l = score_label[0::4, 0]
- score_inds_r = score_label[1::4, 0]
- score_inds_t = score_label[2::4, 0]
- score_inds_d = score_label[3::4, 0]
- l_buckets = px1 + (0.5 + score_inds_l) * bucket_w
- r_buckets = px2 - (0.5 + score_inds_r) * bucket_w
- t_buckets = py1 + (0.5 + score_inds_t) * bucket_h
- d_buckets = py2 - (0.5 + score_inds_d) * bucket_h
-
- offsets = offset_preds.reshape(-1, 4, side_num)
- inds = np.arange(proposals.shape[0])
- l_offsets = offsets[:, 0, :][inds, score_inds_l]
- r_offsets = offsets[:, 1, :][inds, score_inds_r]
- t_offsets = offsets[:, 2, :][inds, score_inds_t]
- d_offsets = offsets[:, 3, :][inds, score_inds_d]
-
- x1 = l_buckets - l_offsets * bucket_w
- x2 = r_buckets - r_offsets * bucket_w
- y1 = t_buckets - t_offsets * bucket_h
- y2 = d_buckets - d_offsets * bucket_h
-
- if clip_border:
- x1 = np.clip(x1, 0, 1)
- y1 = np.clip(y1, 0, 1)
- x2 = np.clip(x2, 0, 1)
- y2 = np.clip(y2, 0, 1)
- bboxes = np.concatenate([x1[:, None], y1[:, None], x2[:, None], y2[:, None]], -1)
-
- # bucketing guided rescoring
- loc_confidence = score_topk[:, 0]
- top2_neighbor_inds = abs((score_label[:, 0] - score_label[:, 1])) == 1
- loc_confidence += score_topk[:, 1] * top2_neighbor_inds
- loc_confidence = loc_confidence.reshape(-1, 4).mean(axis=1)
-
- return bboxes, loc_confidence
-
- def sabl_eval(dataset_path, ckpt_path):
- """sabl evaluation."""
- batch_size = 1
- ds = create_dataset(dataset_path, batch_size=batch_size, repeat_num=1, is_training=False)
- backbone = resnet101(config.num_classes)
- net = sablhead(backbone, config)
- net = SablInferWithDecoder(net, Tensor(default_square_boxes_ltrb), config)
- print("Load Checkpoint!")
- print("ckpt_path: ", ckpt_path)
- param_dict = load_checkpoint(ckpt_path)
- net.init_parameters_data()
- load_param_into_net(net, param_dict)
-
- net.set_train(False)
- i = batch_size
- total = ds.get_dataset_size() * batch_size
- start = time.time()
- pred_data = []
- print("\n========================================\n")
- print("total images num: ", total)
- print("Processing, please wait a moment.")
- for data in ds.create_dict_iterator(output_numpy=True):
- img_id = data['img_id']
- img_np = data['image']
- image_shape = data['image_shape']
-
- bbox_reg_pred, scores, bbox_cls_pred = net(Tensor(img_np))
- bbox_reg_pred, scores, bbox_cls_pred = bbox_reg_pred.asnumpy(), scores.asnumpy(), bbox_cls_pred.asnumpy()
- # Five-layer feature map with up to 1000 boxes per layer
- idx = [0,5625,7069,7430,7530,7555]
- final_scores = np.array([0.0])
- final_labels = np.array([0])
- final_anchors = np.array([[0.0]*4])
- final_bbox_cls_pred = np.array([[0.0]*28])
- final_bbox_reg_pred = np.array([[0.0]*28])
- for n in range(5):
- results = filter_scores_and_topk(
- scores[idx[n]:idx[n+1],:],
- results =
- dict(
- anchors=default_square_boxes_ltrb[idx[n]:idx[n+1],:],
- bbox_cls_pred=bbox_cls_pred[idx[n]:idx[n+1],:],
- bbox_reg_pred=bbox_reg_pred[idx[n]:idx[n+1],:]))
- if results == 0:
- continue
- scores_level, labels_level, _, filtered_results_level = results
- final_scores = np.concatenate((final_scores,scores_level), 0)
- final_labels = np.concatenate((final_labels,labels_level), 0)
- final_anchors = np.concatenate((final_anchors,filtered_results_level['anchors']), 0)
- final_bbox_cls_pred = np.concatenate((final_bbox_cls_pred,filtered_results_level['bbox_cls_pred']),0)
- final_bbox_reg_pred = np.concatenate((final_bbox_reg_pred,filtered_results_level['bbox_reg_pred']),0)
- final_scores = final_scores[1:].astype(np.float32)
- final_labels = final_labels[1:].astype(np.int32)
- final_anchors = final_anchors[1:,:].astype(np.float32)
- final_bbox_cls_pred = final_bbox_cls_pred[1:,:].astype(np.float32)
- final_bbox_reg_pred = final_bbox_reg_pred[1:,:].astype(np.float32)
- bbox_preds = [
- final_bbox_cls_pred,
- final_bbox_reg_pred
- ]
- bboxes, confids = decode(
- final_anchors, bbox_preds)
-
- pred_data.append({"boxes": bboxes.astype(np.float32),
- "box_scores": (final_scores * confids).astype(np.float32),
- "labels":final_labels.astype(np.int32),
- "img_id": int(img_id[0]),
- "img_shape": image_shape[0]})
- percent = round(i / total * 100., 2)
- print(" {}% [{}/{}]".format(str(percent), i, total))
- i += batch_size
- cost_time = int((time.time() - start) * 1000)
- print(" 100% [{arg1}/{arg1}] cost {arg2} ms".format(arg1=total, arg2=cost_time))
- mAP = metrics(pred_data)
-
-
- def modelarts_process():
- if config.need_modelarts_dataset_unzip:
- config.coco_root = os.path.join(config.coco_root, config.modelarts_dataset_unzip_name)
- print(os.listdir(os.path.join(config.data_path, config.modelarts_dataset_unzip_name)))
-
-
- @moxing_wrapper(pre_process=modelarts_process)
- def eval_sabl_resnet101():
- """ eval_sabl_resnet101 """
- if config.train_mode == 'Graph':
- context.set_context(mode=context.GRAPH_MODE, device_target=config.run_platform, device_id=get_device_id())
- else :
- context.set_context(mode=context.PYNATIVE_MODE, device_target=config.run_platform, device_id=get_device_id())
-
- prefix = "sabl_eval.mindrecord"
- mindrecord_dir = config.mindrecord_dir
- mindrecord_file = os.path.join(mindrecord_dir, prefix + "0")
- if config.dataset == "voc":
- config.coco_root = config.voc_root
- if not os.path.exists(mindrecord_file):
- if not os.path.isdir(mindrecord_dir):
- os.makedirs(mindrecord_dir)
- if config.dataset == "coco":
- if os.path.isdir(config.coco_root):
- print("Create Mindrecord.")
- data_to_mindrecord_byte_image("coco", False, prefix)
- print("Create Mindrecord Done, at {}".format(mindrecord_dir))
- else:
- print("coco_root not exits.")
- elif config.dataset == "voc":
- if os.path.isdir(config.voc_dir) and os.path.isdir(config.voc_root):
- print("Create Mindrecord.")
- voc_data_to_mindrecord(mindrecord_dir, False, prefix)
- print("Create Mindrecord Done, at {}".format(mindrecord_dir))
- else:
- print("voc_root or voc_dir not exits.")
- else:
- if os.path.isdir(config.image_dir) and os.path.exists(config.anno_path):
- print("Create Mindrecord.")
- data_to_mindrecord_byte_image("other", False, prefix)
- print("Create Mindrecord Done, at {}".format(mindrecord_dir))
- else:
- print("IMAGE_DIR or ANNO_PATH not exits.")
- else:
- print("Mindrecord file exists.")
-
- print("Start Eval!")
- sabl_eval(mindrecord_file, config.checkpoint_path)
-
-
- if __name__ == '__main__':
- eval_sabl_resnet101()
|