parent
cc0ba93d17
commit
0c81759ae6
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,107 @@
|
||||
# Copyright 2020 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
|
||||
#
|
||||
# less 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 yolo_v3"""
|
||||
import os
|
||||
import argparse
|
||||
import time
|
||||
from mindspore import context, Tensor
|
||||
from mindspore.train.serialization import load_checkpoint, load_param_into_net
|
||||
from mindspore.model_zoo.yolov3 import yolov3_resnet18, YoloWithEval
|
||||
from dataset import create_yolo_dataset, data_to_mindrecord_byte_image
|
||||
from config import ConfigYOLOV3ResNet18
|
||||
from util import metrics
|
||||
|
||||
def yolo_eval(dataset_path, ckpt_path):
|
||||
"""Yolov3 evaluation."""
|
||||
|
||||
ds = create_yolo_dataset(dataset_path, is_training=False)
|
||||
config = ConfigYOLOV3ResNet18()
|
||||
net = yolov3_resnet18(config)
|
||||
eval_net = YoloWithEval(net, config)
|
||||
print("Load Checkpoint!")
|
||||
param_dict = load_checkpoint(ckpt_path)
|
||||
load_param_into_net(net, param_dict)
|
||||
|
||||
|
||||
eval_net.set_train(False)
|
||||
i = 1.
|
||||
total = ds.get_dataset_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():
|
||||
img_np = data['image']
|
||||
image_shape = data['image_shape']
|
||||
annotation = data['annotation']
|
||||
|
||||
eval_net.set_train(False)
|
||||
output = eval_net(Tensor(img_np), Tensor(image_shape))
|
||||
for batch_idx in range(img_np.shape[0]):
|
||||
pred_data.append({"boxes": output[0].asnumpy()[batch_idx],
|
||||
"box_scores": output[1].asnumpy()[batch_idx],
|
||||
"annotation": annotation})
|
||||
percent = round(i / total * 100, 2)
|
||||
|
||||
print(' %s [%d/%d]' % (str(percent) + '%', i, total), end='\r')
|
||||
i += 1
|
||||
print(' %s [%d/%d] cost %d ms' % (str(100.0) + '%', total, total, int((time.time() - start) * 1000)), end='\n')
|
||||
|
||||
precisions, recalls = metrics(pred_data)
|
||||
print("\n========================================\n")
|
||||
for i in range(config.num_classes):
|
||||
print("class {} precision is {:.2f}%, recall is {:.2f}%".format(i, precisions[i] * 100, recalls[i] * 100))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Yolov3 evaluation')
|
||||
parser.add_argument("--device_id", type=int, default=0, help="Device id, default is 0.")
|
||||
parser.add_argument("--mindrecord_dir", type=str, default="./Mindrecord_eval",
|
||||
help="Mindrecord directory. If the mindrecord_dir is empty, it wil generate mindrecord file by"
|
||||
"image_dir and anno_path. Note if mindrecord_dir isn't empty, it will use mindrecord_dir "
|
||||
"rather than image_dir and anno_path. Default is ./Mindrecord_eval")
|
||||
parser.add_argument("--image_dir", type=str, default="", help="Dataset directory, "
|
||||
"the absolute image path is joined by the image_dir "
|
||||
"and the relative path in anno_path.")
|
||||
parser.add_argument("--anno_path", type=str, default="", help="Annotation path.")
|
||||
parser.add_argument("--ckpt_path", type=str, required=True, help="Checkpoint path.")
|
||||
args_opt = parser.parse_args()
|
||||
|
||||
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=args_opt.device_id)
|
||||
context.set_context(enable_task_sink=True, enable_loop_sink=True, enable_mem_reuse=True,
|
||||
enable_auto_mixed_precision=False)
|
||||
|
||||
# It will generate mindrecord file in args_opt.mindrecord_dir,
|
||||
# and the file name is yolo.mindrecord0, 1, ... file_num.
|
||||
if not os.path.isdir(args_opt.mindrecord_dir):
|
||||
os.makedirs(args_opt.mindrecord_dir)
|
||||
|
||||
prefix = "yolo.mindrecord"
|
||||
mindrecord_file = os.path.join(args_opt.mindrecord_dir, prefix + "0")
|
||||
if not os.path.exists(mindrecord_file):
|
||||
if os.path.isdir(args_opt.image_dir) and os.path.exists(args_opt.anno_path):
|
||||
print("Create Mindrecord")
|
||||
data_to_mindrecord_byte_image(args_opt.image_dir,
|
||||
args_opt.anno_path,
|
||||
args_opt.mindrecord_dir,
|
||||
prefix=prefix,
|
||||
file_num=8)
|
||||
print("Create Mindrecord Done, at {}".format(args_opt.mindrecord_dir))
|
||||
else:
|
||||
print("image_dir or anno_path not exits")
|
||||
print("Start Eval!")
|
||||
yolo_eval(mindrecord_file, args_opt.ckpt_path)
|
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2020 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.
|
||||
# ============================================================================
|
||||
|
||||
echo "=============================================================================================================="
|
||||
echo "Please run the scipt as: "
|
||||
echo "sh run_eval.sh DEVICE_ID CKPT_PATH MINDRECORD_DIR IMAGE_DIR ANNO_PATH"
|
||||
echo "for example: sh run_eval.sh 0 yolo.ckpt ./Mindrecord_eval ./dataset ./dataset/eval.txt"
|
||||
echo "=============================================================================================================="
|
||||
|
||||
python eval.py --device_id=$1 --ckpt_path=$2 --mindrecord_dir=$3 --image_dir=$4 --anno_path=$5
|
@ -0,0 +1,146 @@
|
||||
# Copyright 2020 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.
|
||||
# ============================================================================
|
||||
"""metrics utils"""
|
||||
|
||||
import numpy as np
|
||||
from config import ConfigYOLOV3ResNet18
|
||||
|
||||
|
||||
def calc_iou(bbox_pred, bbox_ground):
|
||||
"""Calculate iou of predicted bbox and ground truth."""
|
||||
x1 = bbox_pred[0]
|
||||
y1 = bbox_pred[1]
|
||||
width1 = bbox_pred[2] - bbox_pred[0]
|
||||
height1 = bbox_pred[3] - bbox_pred[1]
|
||||
|
||||
x2 = bbox_ground[0]
|
||||
y2 = bbox_ground[1]
|
||||
width2 = bbox_ground[2] - bbox_ground[0]
|
||||
height2 = bbox_ground[3] - bbox_ground[1]
|
||||
|
||||
endx = max(x1 + width1, x2 + width2)
|
||||
startx = min(x1, x2)
|
||||
width = width1 + width2 - (endx - startx)
|
||||
|
||||
endy = max(y1 + height1, y2 + height2)
|
||||
starty = min(y1, y2)
|
||||
height = height1 + height2 - (endy - starty)
|
||||
|
||||
if width <= 0 or height <= 0:
|
||||
iou = 0
|
||||
else:
|
||||
area = width * height
|
||||
area1 = width1 * height1
|
||||
area2 = width2 * height2
|
||||
iou = area * 1. / (area1 + area2 - area)
|
||||
|
||||
return iou
|
||||
|
||||
|
||||
def apply_nms(all_boxes, all_scores, thres, max_boxes):
|
||||
"""Apply NMS to bboxes."""
|
||||
x1 = all_boxes[:, 0]
|
||||
y1 = all_boxes[:, 1]
|
||||
x2 = all_boxes[:, 2]
|
||||
y2 = all_boxes[:, 3]
|
||||
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
|
||||
|
||||
order = all_scores.argsort()[::-1]
|
||||
keep = []
|
||||
|
||||
while order.size > 0:
|
||||
i = order[0]
|
||||
keep.append(i)
|
||||
|
||||
if len(keep) >= max_boxes:
|
||||
break
|
||||
|
||||
xx1 = np.maximum(x1[i], x1[order[1:]])
|
||||
yy1 = np.maximum(y1[i], y1[order[1:]])
|
||||
xx2 = np.minimum(x2[i], x2[order[1:]])
|
||||
yy2 = np.minimum(y2[i], y2[order[1:]])
|
||||
|
||||
w = np.maximum(0.0, xx2 - xx1 + 1)
|
||||
h = np.maximum(0.0, yy2 - yy1 + 1)
|
||||
inter = w * h
|
||||
|
||||
ovr = inter / (areas[i] + areas[order[1:]] - inter)
|
||||
|
||||
inds = np.where(ovr <= thres)[0]
|
||||
|
||||
order = order[inds + 1]
|
||||
return keep
|
||||
|
||||
|
||||
def metrics(pred_data):
|
||||
"""Calculate precision and recall of predicted bboxes."""
|
||||
config = ConfigYOLOV3ResNet18()
|
||||
num_classes = config.num_classes
|
||||
count_corrects = [1e-6 for _ in range(num_classes)]
|
||||
count_grounds = [1e-6 for _ in range(num_classes)]
|
||||
count_preds = [1e-6 for _ in range(num_classes)]
|
||||
|
||||
for i, sample in enumerate(pred_data):
|
||||
gt_anno = sample["annotation"]
|
||||
box_scores = sample['box_scores']
|
||||
boxes = sample['boxes']
|
||||
mask = box_scores >= config.obj_threshold
|
||||
boxes_ = []
|
||||
scores_ = []
|
||||
classes_ = []
|
||||
max_boxes = config.nms_max_num
|
||||
for c in range(num_classes):
|
||||
class_boxes = np.reshape(boxes, [-1, 4])[np.reshape(mask[:, c], [-1])]
|
||||
class_box_scores = np.reshape(box_scores[:, c], [-1])[np.reshape(mask[:, c], [-1])]
|
||||
nms_index = apply_nms(class_boxes, class_box_scores, config.nms_threshold, max_boxes)
|
||||
class_boxes = class_boxes[nms_index]
|
||||
class_box_scores = class_box_scores[nms_index]
|
||||
classes = np.ones_like(class_box_scores, 'int32') * c
|
||||
boxes_.append(class_boxes)
|
||||
scores_.append(class_box_scores)
|
||||
classes_.append(classes)
|
||||
|
||||
boxes = np.concatenate(boxes_, axis=0)
|
||||
classes = np.concatenate(classes_, axis=0)
|
||||
|
||||
|
||||
# metric
|
||||
count_correct = [1e-6 for _ in range(num_classes)]
|
||||
count_ground = [1e-6 for _ in range(num_classes)]
|
||||
count_pred = [1e-6 for _ in range(num_classes)]
|
||||
|
||||
for anno in gt_anno:
|
||||
count_ground[anno[4]] += 1
|
||||
|
||||
for box_index, box in enumerate(boxes):
|
||||
bbox_pred = [box[1], box[0], box[3], box[2]]
|
||||
count_pred[classes[box_index]] += 1
|
||||
|
||||
for anno in gt_anno:
|
||||
class_ground = anno[4]
|
||||
|
||||
if classes[box_index] == class_ground:
|
||||
iou = calc_iou(bbox_pred, anno)
|
||||
if iou >= 0.5:
|
||||
count_correct[class_ground] += 1
|
||||
break
|
||||
|
||||
count_corrects = [count_corrects[i] + count_correct[i] for i in range(num_classes)]
|
||||
count_preds = [count_preds[i] + count_pred[i] for i in range(num_classes)]
|
||||
count_grounds = [count_grounds[i] + count_ground[i] for i in range(num_classes)]
|
||||
|
||||
precision = np.array([count_corrects[ix] / count_preds[ix] for ix in range(num_classes)])
|
||||
recall = np.array([count_corrects[ix] / count_grounds[ix] for ix in range(num_classes)])
|
||||
return precision, recall
|
@ -0,0 +1,76 @@
|
||||
# Copyright 2020 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.
|
||||
# ============================================================================
|
||||
|
||||
"""ReduceMin op"""
|
||||
from mindspore.ops.op_info_register import op_info_register
|
||||
|
||||
|
||||
@op_info_register("""{
|
||||
"op_name": "ReduceMin",
|
||||
"imply_type": "TBE",
|
||||
"fusion_type": "OPAQUE",
|
||||
"async_flag": false,
|
||||
"binfile_name": "reduce_min_d.so",
|
||||
"compute_cost": 10,
|
||||
"kernel_name": "reduce_min_d",
|
||||
"partial_flag": true,
|
||||
"attr": [
|
||||
{
|
||||
"name": "axis",
|
||||
"param_type": "required",
|
||||
"type": "listInt",
|
||||
"value": "all"
|
||||
},
|
||||
{
|
||||
"name": "keep_dims",
|
||||
"param_type": "required",
|
||||
"type": "bool",
|
||||
"value": "all"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"index": 0,
|
||||
"dtype": [
|
||||
"float16", "float16", "float", "float", "int8", "int8", "uint8", "uint8"
|
||||
],
|
||||
"format": [
|
||||
"DefaultFormat", "FracZ", "DefaultFormat", "FracZ", "DefaultFormat", "FracZ", "DefaultFormat", "FracZ"
|
||||
],
|
||||
"name": "x",
|
||||
"need_compile": false,
|
||||
"param_type": "required",
|
||||
"shape": "all"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"index": 0,
|
||||
"dtype": [
|
||||
"float16", "float16", "float", "float", "int8", "int8", "uint8", "uint8"
|
||||
],
|
||||
"format": [
|
||||
"DefaultFormat", "FracZ", "DefaultFormat", "FracZ", "DefaultFormat", "FracZ", "DefaultFormat", "FracZ"
|
||||
],
|
||||
"name": "y",
|
||||
"need_compile": false,
|
||||
"param_type": "required",
|
||||
"shape": "all"
|
||||
}
|
||||
]
|
||||
}""")
|
||||
def _reduce_min_tbe():
|
||||
"""ReduceMin TBE register"""
|
||||
return
|
@ -0,0 +1,65 @@
|
||||
# Copyright 2020 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.
|
||||
# ============================================================================
|
||||
|
||||
"""Round op"""
|
||||
from mindspore.ops.op_info_register import op_info_register
|
||||
|
||||
|
||||
@op_info_register("""{
|
||||
"op_name": "Round",
|
||||
"imply_type": "TBE",
|
||||
"fusion_type": "ELEMWISE",
|
||||
"async_flag": false,
|
||||
"binfile_name": "round.so",
|
||||
"compute_cost": 10,
|
||||
"kernel_name": "round",
|
||||
"partial_flag": true,
|
||||
"attr": [
|
||||
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"index": 0,
|
||||
"dtype": [
|
||||
"float16", "float16", "float16", "float", "float", "float"
|
||||
],
|
||||
"format": [
|
||||
"DefaultFormat", "NC1HWC0", "FracZ", "DefaultFormat", "NC1HWC0", "FracZ"
|
||||
],
|
||||
"name": "x",
|
||||
"need_compile": false,
|
||||
"param_type": "required",
|
||||
"shape": "all"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"index": 0,
|
||||
"dtype": [
|
||||
"float16", "float16", "float16", "float", "float", "float"
|
||||
],
|
||||
"format": [
|
||||
"DefaultFormat", "NC1HWC0", "FracZ", "DefaultFormat", "NC1HWC0", "FracZ"
|
||||
],
|
||||
"name": "y",
|
||||
"need_compile": false,
|
||||
"param_type": "required",
|
||||
"shape": "all"
|
||||
}
|
||||
]
|
||||
}""")
|
||||
def _round_tbe():
|
||||
"""Round TBE register"""
|
||||
return
|
Loading…
Reference in new issue