Skip to content

Commit 5d6a0ea

Browse files
author
Anna Grebneva
authored
Added support for ssd-vgg model (#2928)
1 parent c4be092 commit 5d6a0ea

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

tools/accuracy_checker/openvino/tools/accuracy_checker/adapters/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ AccuracyChecker supports following set of adapters:
459459
* `noise_suppression` - converts output of audio denoising model to `NoiseSuppressionPrediction`.
460460
* `output_blob` - name of output layer with processed signal (Optional, if not provided, first found output from model will be used).
461461
* `kaldi_latgen_faster_mapped` - decodes output Kaldi\* automatic speech recognition model using lattice generation approach with transition model to `CharcterRecognitionPrediction`.
462-
**Important note** This adapter requires [Kaldi\* installation](https://kaldi-asr.org/doc/install.html)(we recommend to use `67db30cc` commit)
462+
**Important note** This adapter requires [Kaldi\* installation](https://kaldi-asr.org/doc/install.html) (we recommend to use `67db30cc` commit)
463463
and providing path to directory with compiled executable apps: `latgen-faster-mapped`, `lattice-scale`, `lattice-add-penalty`, `lattice-best-path`.
464464
Path directory can be provided using `--kaldi_bin_dir` commandline argument or `KALDI_BIN_DIR` environment variable.
465465
* `fst_file` - Weighted Finite-State Transducers (WFST) state graph file.
@@ -481,3 +481,9 @@ AccuracyChecker supports following set of adapters:
481481
* `output_name` - name of output node to convert.
482482
* `mask_to_binary_classification` - converts output of model represented as segmentation mask to `ArgMaxClassificationPrediction`. Class label calculated as comparision maximal probability in mask with given threshold.
483483
* `threshold` - probability threshold for label 1 (Optional, default 0.5).
484+
* `ssd_multilabel` - converting output of SSD-based model where multiple labels can correspond to one box to `DetectionPrediction` representation.
485+
* `scores_out` - name of output layer with bounding boxes scores.
486+
* `boxes_out` - name of output layer with bounding boxes coordinates.
487+
* `confidence_threshold` - lower bound for valid boxes scores (optional, default 0.01).
488+
* `nms_threshold` - overlap threshold for NMS (optional, default 0.45).
489+
* `keep_top_k ` - maximal number of boxes which should be kept (optional, default 200).

tools/accuracy_checker/openvino/tools/accuracy_checker/adapters/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
PersonVehicleDetectionRefinementAdapter
6868
)
6969
from .detection_head import HeadDetectionAdapter
70-
from .ssd import SSDAdapter, PyTorchSSDDecoder, FacePersonAdapter, SSDAdapterMxNet, SSDONNXAdapter
70+
from .ssd import SSDAdapter, PyTorchSSDDecoder, FacePersonAdapter, SSDAdapterMxNet, SSDONNXAdapter, SSDMultiLabelAdapter
7171
from .retinaface import RetinaFaceAdapter, RetinaFacePyTorchAdapter
7272
from .retinanet import RetinaNetAdapter, MultiOutRetinaNet, RetinaNetTF2
7373
from .yolo import (
@@ -167,6 +167,7 @@
167167
'SSDONNXAdapter',
168168
'PyTorchSSDDecoder',
169169
'FacePersonAdapter',
170+
'SSDMultiLabelAdapter',
170171

171172
'RetinaNetAdapter',
172173
'MultiOutRetinaNet',

tools/accuracy_checker/openvino/tools/accuracy_checker/adapters/ssd.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,72 @@ def find_layer(regex, output_name, all_outputs):
380380
self.bboxes_out = find_layer(bboxes_regex, 'bboxes', raw_outputs)
381381

382382
self.outputs_verified = True
383+
384+
385+
class SSDMultiLabelAdapter(Adapter):
386+
__provider__ = 'ssd_multilabel'
387+
388+
@classmethod
389+
def parameters(cls):
390+
params = super().parameters()
391+
params.update({
392+
'scores_out': StringField(description='scores output'),
393+
'boxes_out': StringField(description='boxes output'),
394+
'confidence_threshold': NumberField(optional=True, default=0.01, description="confidence threshold"),
395+
'nms_threshold': NumberField(optional=True, default=0.45, description="NMS threshold"),
396+
'keep_top_k': NumberField(optional=True, value_type=int, default=200, description="keep top K")
397+
})
398+
return params
399+
400+
def configure(self):
401+
self.scores_out = self.get_value_from_config('scores_out')
402+
self.boxes_out = self.get_value_from_config('boxes_out')
403+
self.confidence_threshold = self.get_value_from_config('confidence_threshold')
404+
self.iou_threshold = self.get_value_from_config('nms_threshold')
405+
self.keep_top_k = self.get_value_from_config('keep_top_k')
406+
self.outputs_verified = False
407+
408+
def select_output_blob(self, outputs):
409+
self.scores_out = self.check_output_name(self.scores_out, outputs)
410+
self.boxes_out = self.check_output_name(self.boxes_out, outputs)
411+
self.outputs_verified = True
412+
413+
def process(self, raw, identifiers, frame_meta):
414+
result = []
415+
raw_output = self._extract_predictions(raw, frame_meta)
416+
if not self.outputs_verified:
417+
self.select_output_blob(raw_output)
418+
419+
for identifier, logits, boxes in zip(identifiers, raw_output[self.scores_out], raw_output[self.boxes_out]):
420+
detections = {'labels': [], 'scores': [], 'x_mins': [], 'y_mins': [], 'x_maxs': [], 'y_maxs': []}
421+
for class_index in range(1, logits.shape[-1]):
422+
probs = logits[:, class_index]
423+
mask = probs > self.confidence_threshold
424+
probs = probs[mask]
425+
if probs.size == 0:
426+
continue
427+
subset_boxes = boxes[mask, :]
428+
429+
x_mins, y_mins, x_maxs, y_maxs = subset_boxes.T
430+
431+
keep = NMS.nms(x_mins, y_mins, x_maxs, y_maxs, probs, self.iou_threshold, include_boundaries=False,
432+
keep_top_k=self.keep_top_k)
433+
434+
filtered_probs = probs[keep]
435+
x_mins = x_mins[keep]
436+
y_mins = y_mins[keep]
437+
x_maxs = x_maxs[keep]
438+
y_maxs = y_maxs[keep]
439+
440+
labels = [class_index] * filtered_probs.size
441+
detections['labels'].extend(labels)
442+
detections['scores'].extend(filtered_probs)
443+
detections['x_mins'].extend(x_mins)
444+
detections['y_mins'].extend(y_mins)
445+
detections['x_maxs'].extend(x_maxs)
446+
detections['y_maxs'].extend(y_maxs)
447+
448+
result.append(DetectionPrediction(identifier, detections['labels'], detections['scores'],
449+
detections['x_mins'], detections['y_mins'], detections['x_maxs'],
450+
detections['y_maxs']))
451+
return result

0 commit comments

Comments
 (0)