Skip to content

Commit c891253

Browse files
authored
Limit combinations of backends and targets in demos and benchmark (#145)
* limit backend and target combination in demos and benchmark * simpler version checking
1 parent 506f46c commit c891253

File tree

33 files changed

+696
-608
lines changed

33 files changed

+696
-608
lines changed

benchmark/benchmark.py

+35-14
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,31 @@
88
from models import MODELS
99
from utils import METRICS, DATALOADERS
1010

11+
# Check OpenCV version
12+
assert cv.__version__ >= "4.7.0", \
13+
"Please install latest opencv-python for benchmark: python3 -m pip install --upgrade opencv-python"
14+
15+
# Valid combinations of backends and targets
16+
backend_target_pairs = [
17+
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
18+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA],
19+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16],
20+
[cv.dnn.DNN_BACKEND_TIMVX, cv.dnn.DNN_TARGET_NPU],
21+
[cv.dnn.DNN_BACKEND_CANN, cv.dnn.DNN_TARGET_NPU]
22+
]
23+
1124
parser = argparse.ArgumentParser("Benchmarks for OpenCV Zoo.")
1225
parser.add_argument('--cfg', '-c', type=str,
1326
help='Benchmarking on the given config.')
27+
parser.add_argument('--cfg_overwrite_backend_target', type=int, default=-1,
28+
help='''Choose one of the backend-target pair to run this demo:
29+
others: (default) use the one from config,
30+
{:d}: OpenCV implementation + CPU,
31+
{:d}: CUDA + GPU (CUDA),
32+
{:d}: CUDA + GPU (CUDA FP16),
33+
{:d}: TIM-VX + NPU,
34+
{:d}: CANN + NPU
35+
'''.format(*[x for x in range(len(backend_target_pairs))]))
1436
parser.add_argument("--fp32", action="store_true", help="Runs models of float32 precision only.")
1537
parser.add_argument("--fp16", action="store_true", help="Runs models of float16 precision only.")
1638
parser.add_argument("--int8", action="store_true", help="Runs models of int8 precision only.")
@@ -56,6 +78,8 @@ def __init__(self, **kwargs):
5678
opencv=cv.dnn.DNN_BACKEND_OPENCV,
5779
# vkcom=cv.dnn.DNN_BACKEND_VKCOM,
5880
cuda=cv.dnn.DNN_BACKEND_CUDA,
81+
timvx=cv.dnn.DNN_BACKEND_TIMVX,
82+
cann=cv.dnn.DNN_BACKEND_CANN,
5983
)
6084

6185
target_id = kwargs.pop('target', 'cpu')
@@ -69,28 +93,20 @@ def __init__(self, **kwargs):
6993
cuda=cv.dnn.DNN_TARGET_CUDA,
7094
cuda_fp16=cv.dnn.DNN_TARGET_CUDA_FP16,
7195
# hddl=cv.dnn.DNN_TARGET_HDDL,
96+
npu=cv.dnn.DNN_TARGET_NPU,
7297
)
7398

74-
# add extra backends & targets
75-
try:
76-
available_backends['timvx'] = cv.dnn.DNN_BACKEND_TIMVX
77-
available_targets['npu'] = cv.dnn.DNN_TARGET_NPU
78-
except:
79-
print('OpenCV is not compiled with TIM-VX backend enbaled. See https://github.com/opencv/opencv/wiki/TIM-VX-Backend-For-Running-OpenCV-On-NPU for more details on how to enable TIM-VX backend.')
80-
try:
81-
available_backends['cann'] = cv.dnn.DNN_BACKEND_CANN
82-
available_targets['npu'] = cv.dnn.DNN_TARGET_NPU
83-
except:
84-
print('OpenCV is not compiled with CANN backend enabled. See https://github.com/opencv/opencv/wiki/Huawei-CANN-Backend for more details on how to enable CANN backend.')
85-
8699
self._backend = available_backends[backend_id]
87100
self._target = available_targets[target_id]
88101

89102
self._benchmark_results = dict()
90103

104+
def setBackendAndTarget(self, backend_id, target_id):
105+
self._backend = backend_id
106+
self._target = target_id
107+
91108
def run(self, model):
92-
model.setBackend(self._backend)
93-
model.setTarget(self._target)
109+
model.setBackendAndTarget(self._backend, self._target)
94110

95111
for idx, data in enumerate(self._dataloader):
96112
filename, input_data = data[:2]
@@ -118,6 +134,11 @@ def printResults(self):
118134
# Instantiate benchmark
119135
benchmark = Benchmark(**cfg['Benchmark'])
120136

137+
if args.cfg_overwrite_backend_target >= 0:
138+
backend_id = backend_target_pairs[args.backend_target][0]
139+
target_id = backend_target_pairs[args.backend_target][1]
140+
benchmark.setBackendAndTarget(backend_id, target_id)
141+
121142
# Instantiate model
122143
model_config = cfg['Model']
123144
model_handler, model_paths = MODELS.get(model_config.pop('name'))

models/face_detection_yunet/demo.py

+39-31
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,42 @@
1111

1212
from yunet import YuNet
1313

14-
def str2bool(v):
15-
if v.lower() in ['on', 'yes', 'true', 'y', 't']:
16-
return True
17-
elif v.lower() in ['off', 'no', 'false', 'n', 'f']:
18-
return False
19-
else:
20-
raise NotImplementedError
21-
22-
backends = [cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_BACKEND_CUDA]
23-
targets = [cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16]
24-
help_msg_backends = "Choose one of the computation backends: {:d}: OpenCV implementation (default); {:d}: CUDA"
25-
help_msg_targets = "Choose one of the target computation devices: {:d}: CPU (default); {:d}: CUDA; {:d}: CUDA fp16"
26-
try:
27-
backends += [cv.dnn.DNN_BACKEND_TIMVX]
28-
targets += [cv.dnn.DNN_TARGET_NPU]
29-
help_msg_backends += "; {:d}: TIMVX"
30-
help_msg_targets += "; {:d}: NPU"
31-
except:
32-
print('This version of OpenCV does not support TIM-VX and NPU. Visit https://github.com/opencv/opencv/wiki/TIM-VX-Backend-For-Running-OpenCV-On-NPU for more information.')
14+
# Check OpenCV version
15+
assert cv.__version__ >= "4.7.0", \
16+
"Please install latest opencv-python to try this demo: python3 -m pip install --upgrade opencv-python"
17+
18+
# Valid combinations of backends and targets
19+
backend_target_pairs = [
20+
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
21+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA],
22+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16],
23+
[cv.dnn.DNN_BACKEND_TIMVX, cv.dnn.DNN_TARGET_NPU],
24+
[cv.dnn.DNN_BACKEND_CANN, cv.dnn.DNN_TARGET_NPU]
25+
]
3326

3427
parser = argparse.ArgumentParser(description='YuNet: A Fast and Accurate CNN-based Face Detector (https://github.com/ShiqiYu/libfacedetection).')
35-
parser.add_argument('--input', '-i', type=str, help='Usage: Set input to a certain image, omit if using camera.')
36-
parser.add_argument('--model', '-m', type=str, default='face_detection_yunet_2022mar.onnx', help="Usage: Set model type, defaults to 'face_detection_yunet_2022mar.onnx'.")
37-
parser.add_argument('--backend', '-b', type=int, default=backends[0], help=help_msg_backends.format(*backends))
38-
parser.add_argument('--target', '-t', type=int, default=targets[0], help=help_msg_targets.format(*targets))
39-
parser.add_argument('--conf_threshold', type=float, default=0.9, help='Usage: Set the minimum needed confidence for the model to identify a face, defauts to 0.9. Smaller values may result in faster detection, but will limit accuracy. Filter out faces of confidence < conf_threshold.')
40-
parser.add_argument('--nms_threshold', type=float, default=0.3, help='Usage: Suppress bounding boxes of iou >= nms_threshold. Default = 0.3.')
41-
parser.add_argument('--top_k', type=int, default=5000, help='Usage: Keep top_k bounding boxes before NMS.')
42-
parser.add_argument('--save', '-s', type=str, default=False, help='Usage: Set “True” to save file with results (i.e. bounding box, confidence level). Invalid in case of camera input. Default will be set to “False”.')
43-
parser.add_argument('--vis', '-v', type=str2bool, default=True, help='Usage: Default will be set to “True” and will open a new window to show results. Set to “False” to stop visualizations from being shown. Invalid in case of camera input.')
28+
parser.add_argument('--input', '-i', type=str,
29+
help='Usage: Set input to a certain image, omit if using camera.')
30+
parser.add_argument('--model', '-m', type=str, default='face_detection_yunet_2022mar.onnx',
31+
help="Usage: Set model type, defaults to 'face_detection_yunet_2022mar.onnx'.")
32+
parser.add_argument('--backend_target', '-bt', type=int, default=0,
33+
help='''Choose one of the backend-target pair to run this demo:
34+
{:d}: (default) OpenCV implementation + CPU,
35+
{:d}: CUDA + GPU (CUDA),
36+
{:d}: CUDA + GPU (CUDA FP16),
37+
{:d}: TIM-VX + NPU,
38+
{:d}: CANN + NPU
39+
'''.format(*[x for x in range(len(backend_target_pairs))]))
40+
parser.add_argument('--conf_threshold', type=float, default=0.9,
41+
help='Usage: Set the minimum needed confidence for the model to identify a face, defauts to 0.9. Smaller values may result in faster detection, but will limit accuracy. Filter out faces of confidence < conf_threshold.')
42+
parser.add_argument('--nms_threshold', type=float, default=0.3,
43+
help='Usage: Suppress bounding boxes of iou >= nms_threshold. Default = 0.3.')
44+
parser.add_argument('--top_k', type=int, default=5000,
45+
help='Usage: Keep top_k bounding boxes before NMS.')
46+
parser.add_argument('--save', '-s', action='store_true',
47+
help='Usage: Specify to save file with results (i.e. bounding box, confidence level). Invalid in case of camera input.')
48+
parser.add_argument('--vis', '-v', action='store_true',
49+
help='Usage: Specify to open a new window to show results. Invalid in case of camera input.')
4450
args = parser.parse_args()
4551

4652
def visualize(image, results, box_color=(0, 255, 0), text_color=(0, 0, 255), fps=None):
@@ -70,14 +76,17 @@ def visualize(image, results, box_color=(0, 255, 0), text_color=(0, 0, 255), fps
7076
return output
7177

7278
if __name__ == '__main__':
79+
backend_id = backend_target_pairs[args.backend_target][0]
80+
target_id = backend_target_pairs[args.backend_target][1]
81+
7382
# Instantiate YuNet
7483
model = YuNet(modelPath=args.model,
7584
inputSize=[320, 320],
7685
confThreshold=args.conf_threshold,
7786
nmsThreshold=args.nms_threshold,
7887
topK=args.top_k,
79-
backendId=args.backend,
80-
targetId=args.target)
88+
backendId=backend_id,
89+
targetId=target_id)
8190

8291
# If input is an image
8392
if args.input is not None:
@@ -134,4 +143,3 @@ def visualize(image, results, box_color=(0, 255, 0), text_color=(0, 0, 255), fps
134143
cv.imshow('YuNet Demo', frame)
135144

136145
tm.reset()
137-

models/face_detection_yunet/yunet.py

+1-13
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,8 @@ def __init__(self, modelPath, inputSize=[320, 320], confThreshold=0.6, nmsThresh
3333
def name(self):
3434
return self.__class__.__name__
3535

36-
def setBackend(self, backendId):
36+
def setBackendAndTarget(self, backendId, targetId):
3737
self._backendId = backendId
38-
self._model = cv.FaceDetectorYN.create(
39-
model=self._modelPath,
40-
config="",
41-
input_size=self._inputSize,
42-
score_threshold=self._confThreshold,
43-
nms_threshold=self._nmsThreshold,
44-
top_k=self._topK,
45-
backend_id=self._backendId,
46-
target_id=self._targetId)
47-
48-
def setTarget(self, targetId):
4938
self._targetId = targetId
5039
self._model = cv.FaceDetectorYN.create(
5140
model=self._modelPath,
@@ -64,4 +53,3 @@ def infer(self, image):
6453
# Forward
6554
faces = self._model.detect(image)
6655
return faces[1]
67-

models/face_recognition_sface/demo.py

+35-30
Original file line numberDiff line numberDiff line change
@@ -15,49 +15,55 @@
1515
sys.path.append('../face_detection_yunet')
1616
from yunet import YuNet
1717

18-
def str2bool(v):
19-
if v.lower() in ['on', 'yes', 'true', 'y', 't']:
20-
return True
21-
elif v.lower() in ['off', 'no', 'false', 'n', 'f']:
22-
return False
23-
else:
24-
raise NotImplementedError
18+
# Check OpenCV version
19+
assert cv.__version__ >= "4.7.0", \
20+
"Please install latest opencv-python to try this demo: python3 -m pip install --upgrade opencv-python"
2521

26-
backends = [cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_BACKEND_CUDA]
27-
targets = [cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16]
28-
help_msg_backends = "Choose one of the computation backends: {:d}: OpenCV implementation (default); {:d}: CUDA \n Usage: Set backend DNN model, defaults to cv.dnn.DNN_BACKEND_OPENCV (int = 0). Based on your OpenCV version, it may or may not support cv.dnn.DNN_BACKEND_TIMVX. More details: [https://gist.github.com/fengyuentau/5a7a5ba36328f2b763aea026c43fa45f]"
29-
help_msg_targets = "Chose one of the target computation devices: {:d}: CPU (default); {:d}: CUDA; {:d}: CUDA fp16"
30-
try:
31-
backends += [cv.dnn.DNN_BACKEND_TIMVX]
32-
targets += [cv.dnn.DNN_TARGET_NPU]
33-
help_msg_backends += "; {:d}: TIMVX"
34-
help_msg_targets += "; {:d}: NPU"
35-
except:
36-
print('This version of OpenCV does not support TIM-VX and NPU. Visit https://github.com/opencv/opencv/wiki/TIM-VX-Backend-For-Running-OpenCV-On-NPU for more information.')
22+
# Valid combinations of backends and targets
23+
backend_target_pairs = [
24+
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
25+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA],
26+
[cv.dnn.DNN_BACKEND_CUDA, cv.dnn.DNN_TARGET_CUDA_FP16],
27+
[cv.dnn.DNN_BACKEND_TIMVX, cv.dnn.DNN_TARGET_NPU],
28+
[cv.dnn.DNN_BACKEND_CANN, cv.dnn.DNN_TARGET_NPU]
29+
]
3730

3831
parser = argparse.ArgumentParser(
3932
description="SFace: Sigmoid-Constrained Hypersphere Loss for Robust Face Recognition (https://ieeexplore.ieee.org/document/9318547)")
40-
parser.add_argument('--input1', '-i1', type=str, help='Usage: Set path to the input image 1 (original face).')
41-
parser.add_argument('--input2', '-i2', type=str, help='Usage: Set path to the input image 2 (comparison face).')
42-
parser.add_argument('--model', '-m', type=str, default='face_recognition_sface_2021dec.onnx', help='Usage: Set model path, defaults to face_recognition_sface_2021dec.onnx.')
43-
parser.add_argument('--backend', '-b', type=int, default=backends[0], help=help_msg_backends.format(*backends))
44-
parser.add_argument('--target', '-t', type=int, default=targets[0], help=help_msg_targets.format(*targets))
45-
parser.add_argument('--dis_type', type=int, choices=[0, 1], default=0, help='Usage: Distance type. \'0\': cosine, \'1\': norm_l1. Defaults to \'0\'')
46-
parser.add_argument('--save', '-s', type=str, default=False, help='Usage: Set “True” to save file with results (i.e. bounding box, confidence level). Invalid in case of camera input. Default will be set to “False”.')
47-
parser.add_argument('--vis', '-v', type=str2bool, default=True, help='Usage: Default will be set to “True” and will open a new window to show results. Set to “False” to stop visualizations from being shown. Invalid in case of camera input.')
33+
parser.add_argument('--input1', '-i1', type=str,
34+
help='Usage: Set path to the input image 1 (original face).')
35+
parser.add_argument('--input2', '-i2', type=str,
36+
help='Usage: Set path to the input image 2 (comparison face).')
37+
parser.add_argument('--model', '-m', type=str, default='face_recognition_sface_2021dec.onnx',
38+
help='Usage: Set model path, defaults to face_recognition_sface_2021dec.onnx.')
39+
parser.add_argument('--backend_target', '-bt', type=int, default=0,
40+
help='''Choose one of the backend-target pair to run this demo:
41+
{:d}: (default) OpenCV implementation + CPU,
42+
{:d}: CUDA + GPU (CUDA),
43+
{:d}: CUDA + GPU (CUDA FP16),
44+
{:d}: TIM-VX + NPU,
45+
{:d}: CANN + NPU
46+
'''.format(*[x for x in range(len(backend_target_pairs))]))
47+
parser.add_argument('--dis_type', type=int, choices=[0, 1], default=0,
48+
help='Usage: Distance type. \'0\': cosine, \'1\': norm_l1. Defaults to \'0\'')
4849
args = parser.parse_args()
4950

5051
if __name__ == '__main__':
52+
backend_id = backend_target_pairs[args.backend_target][0]
53+
target_id = backend_target_pairs[args.backend_target][1]
5154
# Instantiate SFace for face recognition
52-
recognizer = SFace(modelPath=args.model, disType=args.dis_type, backendId=args.backend, targetId=args.target)
55+
recognizer = SFace(modelPath=args.model,
56+
disType=args.dis_type,
57+
backendId=backend_id,
58+
targetId=target_id)
5359
# Instantiate YuNet for face detection
5460
detector = YuNet(modelPath='../face_detection_yunet/face_detection_yunet_2022mar.onnx',
5561
inputSize=[320, 320],
5662
confThreshold=0.9,
5763
nmsThreshold=0.3,
5864
topK=5000,
59-
backendId=args.backend,
60-
targetId=args.target)
65+
backendId=backend_id,
66+
targetId=target_id)
6167

6268
img1 = cv.imread(args.input1)
6369
img2 = cv.imread(args.input2)
@@ -73,4 +79,3 @@ def str2bool(v):
7379
# Match
7480
result = recognizer.match(img1, face1[0][:-1], img2, face2[0][:-1])
7581
print('Result: {}.'.format('same identity' if result else 'different identities'))
76-

models/face_recognition_sface/sface.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import numpy as np
88
import cv2 as cv
99

10-
from _testcapi import FLT_MIN
11-
1210
class SFace:
1311
def __init__(self, modelPath, disType=0, backendId=0, targetId=0):
1412
self._modelPath = modelPath
@@ -30,15 +28,8 @@ def __init__(self, modelPath, disType=0, backendId=0, targetId=0):
3028
def name(self):
3129
return self.__class__.__name__
3230

33-
def setBackend(self, backendId):
31+
def setBackendAndTarget(self, backendId, targetId):
3432
self._backendId = backendId
35-
self._model = cv.FaceRecognizerSF.create(
36-
model=self._modelPath,
37-
config="",
38-
backend_id=self._backendId,
39-
target_id=self._targetId)
40-
41-
def setTarget(self, targetId):
4233
self._targetId = targetId
4334
self._model = cv.FaceRecognizerSF.create(
4435
model=self._modelPath,
@@ -70,4 +61,3 @@ def match(self, image1, face1, image2, face2):
7061
else: # NORM_L2
7162
norml2_distance = self._model.match(feature1, feature2, self._disType)
7263
return 1 if norml2_distance <= self._threshold_norml2 else 0
73-

0 commit comments

Comments
 (0)