Skip to content

Commit 004a627

Browse files
authored
add evaluation framework and imagenet evaluation (#69)
1 parent 64b3eda commit 004a627

File tree

12 files changed

+311
-27
lines changed

12 files changed

+311
-27
lines changed

benchmark/config/image_classification_mobilenetv1.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ Benchmark:
1717
Model:
1818
name: "MobileNetV1"
1919
modelPath: "models/image_classification_mobilenet/image_classification_mobilenetv1_2022apr.onnx"
20-
labelPath: "models/image_classification_mobilenet/imagenet_labels.txt"
20+

benchmark/config/image_classification_mobilenetv2.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ Benchmark:
1717
Model:
1818
name: "MobileNetV2"
1919
modelPath: "models/image_classification_mobilenet/image_classification_mobilenetv2_2022apr.onnx"
20-
labelPath: "models/image_classification_mobilenet/imagenet_labels.txt"
20+

benchmark/config/image_classification_ppresnet.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ Benchmark:
1717
Model:
1818
name: "PPResNet"
1919
modelPath: "models/image_classification_ppresnet/image_classification_ppresnet50_2022jan.onnx"
20-
labelPath: "models/image_classification_ppresnet/imagenet_labels.txt"
20+

models/image_classification_mobilenet/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applicatio
44

55
MobileNetV2: Inverted Residuals and Linear Bottlenecks
66

7+
Results of accuracy evaluation with [tools/eval](../../tools/eval).
8+
9+
| Models | Top-1 Accuracy | Top-5 Accuracy |
10+
| ------ | -------------- | -------------- |
11+
| MobileNet V1 | 67.64 | 87.97 |
12+
| MobileNet V1 quant | 55.53 | 78.74 |
13+
| MobileNet V2 | 69.44 | 89.23 |
14+
| MobileNet V2 quant | 68.37 | 88.56 |
15+
16+
\*: 'quant' stands for 'quantized'.
17+
718
## Demo
819

920
Run the following command to try the demo:
@@ -24,3 +35,4 @@ All files in this directory are licensed under [Apache 2.0 License](./LICENSE).
2435
- MobileNet V2: https://arxiv.org/abs/1801.04381
2536
- MobileNet V1 weight and scripts for training: https://github.com/wjc852456/pytorch-mobilenet-v1
2637
- MobileNet V2 weight: https://github.com/onnx/models/tree/main/vision/classification/mobilenet
38+

models/image_classification_mobilenet/mobilenet_v1.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
import cv2 as cv
33

44
class MobileNetV1:
5-
def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
5+
def __init__(self, modelPath, labelPath=None, topK=1, backendId=0, targetId=0):
66
self.model_path = modelPath
77
self.label_path = labelPath
8+
assert topK >= 1
9+
self.top_k = topK
810
self.backend_id = backendId
911
self.target_id = targetId
1012

@@ -23,9 +25,10 @@ def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
2325

2426
def _load_labels(self):
2527
labels = []
26-
with open(self.label_path, 'r') as f:
27-
for line in f:
28-
labels.append(line.strip())
28+
if self.label_path is not None:
29+
with open(self.label_path, 'r') as f:
30+
for line in f:
31+
labels.append(line.strip())
2932
return labels
3033

3134
@property
@@ -61,9 +64,18 @@ def infer(self, image):
6164
return results
6265

6366
def _postprocess(self, output_blob):
64-
predicted_labels = []
67+
batched_class_id_list = []
6568
for o in output_blob:
66-
class_id = np.argmax(o)
67-
predicted_labels.append(self.labels[class_id])
68-
return predicted_labels
69+
class_id_list = o.argsort()[::-1][:self.top_k]
70+
batched_class_id_list.append(class_id_list)
71+
if len(self.labels) > 0:
72+
batched_predicted_labels = []
73+
for class_id_list in batched_class_id_list:
74+
predicted_labels = []
75+
for class_id in class_id_list:
76+
predicted_labels.append(self._labels[class_id])
77+
batched_predicted_labels.append(predicted_labels)
78+
return batched_predicted_labels
79+
else:
80+
return batched_class_id_list
6981

models/image_classification_mobilenet/mobilenet_v2.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
import cv2 as cv
33

44
class MobileNetV2:
5-
def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
5+
def __init__(self, modelPath, labelPath=None, topK=1, backendId=0, targetId=0):
66
self.model_path = modelPath
77
self.label_path = labelPath
8+
assert topK >= 1
9+
self.top_k = topK
810
self.backend_id = backendId
911
self.target_id = targetId
1012

@@ -23,9 +25,10 @@ def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
2325

2426
def _load_labels(self):
2527
labels = []
26-
with open(self.label_path, 'r') as f:
27-
for line in f:
28-
labels.append(line.strip())
28+
if self.label_path is not None:
29+
with open(self.label_path, 'r') as f:
30+
for line in f:
31+
labels.append(line.strip())
2932
return labels
3033

3134
@property
@@ -61,9 +64,18 @@ def infer(self, image):
6164
return results
6265

6366
def _postprocess(self, output_blob):
64-
predicted_labels = []
67+
batched_class_id_list = []
6568
for o in output_blob:
66-
class_id = np.argmax(o)
67-
predicted_labels.append(self.labels[class_id])
68-
return predicted_labels
69+
class_id_list = o.argsort()[::-1][:self.top_k]
70+
batched_class_id_list.append(class_id_list)
71+
if len(self.labels) > 0:
72+
batched_predicted_labels = []
73+
for class_id_list in batched_class_id_list:
74+
predicted_labels = []
75+
for class_id in class_id_list:
76+
predicted_labels.append(self._labels[class_id])
77+
batched_predicted_labels.append(predicted_labels)
78+
return batched_predicted_labels
79+
else:
80+
return batched_class_id_list
6981

models/image_classification_ppresnet/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ Deep Residual Learning for Image Recognition
44

55
This model is ported from [PaddleHub](https://github.com/PaddlePaddle/PaddleHub) using [this script from OpenCV](https://github.com/opencv/opencv/blob/master/samples/dnn/dnn_model_runner/dnn_conversion/paddlepaddle/paddle_resnet50.py).
66

7+
Results of accuracy evaluation with [tools/eval](../../tools/eval).
8+
9+
| Models | Top-1 Accuracy | Top-5 Accuracy |
10+
| ------ | -------------- | -------------- |
11+
| PP-ResNet | 82.28 | 96.15 |
12+
| PP-ResNet quant | 0.22 | 0.96 |
13+
14+
\*: 'quant' stands for 'quantized'.
15+
716
## Demo
817

918
Run the following command to try the demo:
@@ -19,4 +28,5 @@ All files in this directory are licensed under [Apache 2.0 License](./LICENSE).
1928

2029
- https://arxiv.org/abs/1512.03385
2130
- https://github.com/opencv/opencv/tree/master/samples/dnn/dnn_model_runner/dnn_conversion/paddlepaddle
22-
- https://github.com/PaddlePaddle/PaddleHub
31+
- https://github.com/PaddlePaddle/PaddleHub
32+

models/image_classification_ppresnet/ppresnet.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import cv2 as cv
1010

1111
class PPResNet:
12-
def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
12+
def __init__(self, modelPath, labelPath=None, topK=1, backendId=0, targetId=0):
1313
self._modelPath = modelPath
1414
self._labelPath = labelPath
15+
assert topK >= 1
16+
self._topK = topK
1517
self._backendId = backendId
1618
self._targetId = targetId
1719

@@ -30,9 +32,10 @@ def __init__(self, modelPath, labelPath, backendId=0, targetId=0):
3032

3133
def _load_labels(self):
3234
labels = []
33-
with open(self._labelPath, 'r') as f:
34-
for line in f:
35-
labels.append(line.strip())
35+
if self._labelPath is not None:
36+
with open(self._labelPath, 'r') as f:
37+
for line in f:
38+
labels.append(line.strip())
3639
return labels
3740

3841
@property
@@ -65,11 +68,23 @@ def infer(self, image):
6568
outputBlob = self._model.forward(self._outputNames)
6669

6770
# Postprocess
68-
results = self._postprocess(outputBlob)
71+
results = self._postprocess(outputBlob[0])
6972

7073
return results
7174

7275
def _postprocess(self, outputBlob):
73-
class_id = np.argmax(outputBlob[0])
74-
return self._labels[class_id]
76+
batched_class_id_list = []
77+
for ob in outputBlob:
78+
class_id_list = ob.argsort()[::-1][:self._topK]
79+
batched_class_id_list.append(class_id_list)
80+
if len(self._labels) > 0:
81+
batched_predicted_labels = []
82+
for class_id_list in batched_class_id_list:
83+
predicted_labels = []
84+
for class_id in class_id_list:
85+
predicted_labels.append(self._labels[class_id])
86+
batched_predicted_labels.append(predicted_labels)
87+
return batched_predicted_labels
88+
else:
89+
return batched_class_id_list
7590

tools/eval/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Accuracy evaluation of models in OpenCV Zoo
2+
3+
Make sure you have the following packages installed:
4+
5+
```shell
6+
pip install tqdm
7+
```
8+
9+
Generally speaking, evaluation can be done with the following command:
10+
11+
```shell
12+
python eval.py -m model_name -d dataset_name -dr dataset_root_dir
13+
```
14+
15+
Supported datasets:
16+
- [ImageNet](./datasets/imagenet.py)
17+
18+
## ImageNet
19+
20+
### Prepare data
21+
22+
Please visit https://image-net.org/ to download the ImageNet dataset and [the labels from caffe](http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz). Organize files as follow:
23+
24+
```shell
25+
$ tree -L 2 /path/to/imagenet
26+
.
27+
├── caffe_ilsvrc12
28+
│   ├── det_synset_words.txt
29+
│   ├── imagenet.bet.pickle
30+
│   ├── imagenet_mean.binaryproto
31+
│   ├── synsets.txt
32+
│   ├── synset_words.txt
33+
│   ├── test.txt
34+
│   ├── train.txt
35+
│   └── val.txt
36+
├── caffe_ilsvrc12.tar.gz
37+
├── ILSVRC
38+
│   ├── Annotations
39+
│   ├── Data
40+
│   └── ImageSets
41+
├── imagenet_object_localization_patched2019.tar.gz
42+
├── LOC_sample_submission.csv
43+
├── LOC_synset_mapping.txt
44+
├── LOC_train_solution.csv
45+
└── LOC_val_solution.csv
46+
```
47+
48+
### Evaluation
49+
50+
Run evaluation with the following command:
51+
52+
```shell
53+
python eval.py -m mobilenet -d imagenet -dr /path/to/imagenet
54+
```
55+

tools/eval/datasets/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from .imagenet import ImageNet
2+
3+
class Registery:
4+
def __init__(self, name):
5+
self._name = name
6+
self._dict = dict()
7+
8+
def get(self, key):
9+
return self._dict[key]
10+
11+
def register(self, item):
12+
self._dict[item.__name__] = item
13+
14+
DATASETS = Registery("Datasets")
15+
DATASETS.register(ImageNet)

0 commit comments

Comments
 (0)