Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenCV inference #332

Merged
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions results/validation/validation_results_opencv_ie.md

Large diffs are not rendered by default.

21 changes: 12 additions & 9 deletions src/benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [Intel® Optimization for TensorFlow][intel-tensorflow].
- [TensorFlow Lite][tensorflow-lite].
- [ONNX Runtime][onnx-runtime].
- [OpenCV][opencv].
- [MXNet][mxnet].

### Алгоритм работы скрипта
Expand Down Expand Up @@ -105,16 +106,17 @@ Inference Engine предоставляет 2 программных интер

**Примечание:** в публикуемой html-таблице содержатся только показатели FPS.

### Показатели производительности вывода для Intel® Optimization for Caffe, Intel® Optimization for TensorFlow, TensorFlow Lite и MXNet
### Показатели производительности вывода для Intel® Optimization for Caffe, Intel® Optimization for TensorFlow, TensorFlow Lite, OpenCV и MXNet

При оценке производительности вывода для Intel® Optimization for Caffe,
Intel® Optimization for TensorFlow, TensorFlow Lite и MXNet осуществляется
последовательный и независимый запуск запросов. Запуск очередного запроса
выполняется после завершения предыдущего. Для каждого запроса осуществляется
замер времени его выполнения. Для множества полученных времен определяется
стандартное среднеквадратичное отклонение, и отбрасываются времена,
выходящие за пределы трех стандартных отклонений от среднего времени вывода.
Результирующий набор времен используется для вычисления показателя латентности.
Intel® Optimization for TensorFlow, TensorFlow Lite, OpenCV и MXNet
осуществляется последовательный и независимый запуск запросов.
Запуск очередного запроса выполняется после завершения предыдущего.
Для каждого запроса осуществляется замер времени его выполнения.
Для множества полученных времен определяется стандартное среднеквадратичное
отклонение, и отбрасываются времена, выходящие за пределы трех стандартных
отклонений от среднего времени вывода. Результирующий набор времен
используется для вычисления показателя латентности.
Остальные показатели вычисляются для всего множества времен.

- **Латентность (latency)** - медиана множества времен выполнения вывода.
Expand Down Expand Up @@ -235,7 +237,7 @@ pip install openvino_dev[mxnet,caffe,caffe2,onnx,pytorch,tensorflow2]==<your ver
1. В конфигурационном файле (секция `FrameworkDependent`)
укажите `Mode`: `ovbenchmark_python_latency` или `ovbenchmark_python_throughput`.

1. Запустите скрипт `nference_benchmark.py`.
1. Запустите скрипт `inference_benchmark.py`.

```bash
python3 inference_benchmark.py -c <path_to_benchmark_configuration_file.xml> -r result.csv
Expand All @@ -249,3 +251,4 @@ pip install openvino_dev[mxnet,caffe,caffe2,onnx,pytorch,tensorflow2]==<your ver
[tensorflow-lite]: https://www.tensorflow.org/lite
[onnx-runtime]: https://onnxruntime.ai
[mxnet]: https://mxnet.apache.org
[opencv]: https://opencv.org
3 changes: 3 additions & 0 deletions src/benchmark/config_parser_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from frameworks.tensorflow.tensorflow_parameters_parser import TensorFlowParametersParser
from frameworks.tensorflow_lite.tensorflow_lite_parameters_parser import TensorFlowLiteParametersParser
from frameworks.mxnet.mxnet_parameters_parser import MXNetParametersParser
from frameworks.opencv_dnn_python.opencv_dnn_python_parameters_parser import OpenCVDNNPythonParametersParser
from frameworks.config_parser.dependent_parameters_parser_cpp import CppParametersParser


Expand All @@ -20,6 +21,8 @@ def get_parameters_parser(framework):
return TensorFlowLiteParametersParser()
if framework == KnownFrameworks.mxnet:
return MXNetParametersParser()
if framework == KnownFrameworks.opencv_dnn_python:
return OpenCVDNNPythonParametersParser()
if framework == KnownFrameworks.opencv_dnn_cpp:
return CppParametersParser()
raise NotImplementedError(f'Unknown framework {framework}')
2 changes: 2 additions & 0 deletions src/benchmark/frameworks/framework_wrapper_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .tensorflow.tensorflow_wrapper import TensorFlowWrapper
from .onnx_runtime.onnx_runtime_wrapper import OnnxRuntimeWrapper
from .tensorflow_lite.tensorflow_lite_wrapper import TensorFlowLiteWrapper
from .opencv_dnn_python.opencv_dnn_python_wrapper import OpenCVDNNPythonWrapper
from .mxnet.mxnet_wrapper import MXNetWrapper
from .opencv_dnn_cpp.opencv_dnn_cpp_wrapper import OpenCVDNNCppWrapper

Expand Down Expand Up @@ -34,5 +35,6 @@ def _get_wrappers(self):
self._framework_wrappers[OpenVINOWrapper.framework_name] = OpenVINOWrapper()
self._framework_wrappers[OnnxRuntimeWrapper.framework_name] = OnnxRuntimeWrapper()
self._framework_wrappers[TensorFlowLiteWrapper.framework_name] = TensorFlowLiteWrapper()
self._framework_wrappers[OpenCVDNNPythonWrapper.framework_name] = OpenCVDNNPythonWrapper()
self._framework_wrappers[MXNetWrapper.framework_name] = MXNetWrapper()
self._framework_wrappers[OpenCVDNNCppWrapper.framework_name] = OpenCVDNNCppWrapper()
1 change: 1 addition & 0 deletions src/benchmark/frameworks/known_frameworks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ class KnownFrameworks:
onnx_runtime = 'ONNX Runtime'
tensorflow_lite = 'TensorFlowLite'
mxnet = 'MXNet'
opencv_dnn_python = 'OpenCV DNN Python'
opencv_dnn_cpp = 'OpenCV DNN Cpp'
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from ..config_parser.dependent_parameters_parser import DependentParametersParser
from ..config_parser.framework_parameters_parser import FrameworkParameters


class OpenCVDNNPythonParametersParser(DependentParametersParser):
def parse_parameters(self, curr_test):
CONFIG_FRAMEWORK_DEPENDENT_TAG = 'FrameworkDependent'
CONFIG_FRAMEWORK_DEPENDENT_BACKEND_TAG = 'Backend'
CONFIG_FRAMEWORK_DEPENDENT_INPUT_SCALE_TAG = 'InputScale'
CONFIG_FRAMEWORK_DEPENDENT_INPUT_SHAPE_TAG = 'InputShape'
CONFIG_FRAMEWORK_DEPENDENT_INPUT_NAME_TAG = 'InputName'
CONFIG_FRAMEWORK_DEPENDENT_OUTPUT_NAMES_TAG = 'OutputNames'
CONFIG_FRAMEWORK_DEPENDENT_MEAN_TAG = 'Mean'
CONFIG_FRAMEWORK_DEPENDENT_STD_TAG = 'Std'
CONFIG_FRAMEWORK_DEPENDENT_SWAP_RB_TAG = 'SwapRB'
CONFIG_FRAMEWORK_DEPENDENT_CROP_TAG = 'Crop'
CONFIG_FRAMEWORK_DEPENDENT_LAYOUT_TAG = 'Layout'

dep_parameters_tag = curr_test.getElementsByTagName(CONFIG_FRAMEWORK_DEPENDENT_TAG)[0]

_backend = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_BACKEND_TAG)[0].firstChild
_input_scale = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_INPUT_SCALE_TAG)[0].firstChild
_input_shape = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_INPUT_SHAPE_TAG)[0].firstChild
_input_name = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_INPUT_NAME_TAG)[0].firstChild
_output_names = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_OUTPUT_NAMES_TAG)[0].firstChild
_mean = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_MEAN_TAG)[0].firstChild
_std = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_STD_TAG)[0].firstChild
_swapRB = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_SWAP_RB_TAG)[0].firstChild
_crop = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_CROP_TAG)[0].firstChild
_layout = dep_parameters_tag.getElementsByTagName(
CONFIG_FRAMEWORK_DEPENDENT_LAYOUT_TAG)[0].firstChild

return OpenCVParameters(
backend=_backend.data if _backend else None,
input_scale=_input_scale.data if _input_scale else None,
input_shape=_input_shape.data if _input_shape else None,
input_name=_input_name.data if _input_name else None,
output_names=_output_names.data if _output_names else None,
mean=_mean.data if _mean else None,
std=_std.data if _std else None,
swapRB=_swapRB.data if _swapRB else None,
crop=_crop.data if _crop else None,
layout=_layout.data if _layout else None,
)


class OpenCVParameters(FrameworkParameters):
def __init__(self, backend, input_scale, input_name, output_names,
input_shape, mean, std, swapRB, crop, layout):
self.backend = None
self.input_scale = None
self.input_shape = None
self.input_name = None
self.output_names = None
self.mean = None
self.std = None
self.swapRB = None
self.crop = None
self.layout = None

if self._parameter_not_is_none(backend):
self.backend = backend
if self._parameter_not_is_none(input_scale):
self.input_scale = input_scale
if self._parameter_not_is_none(input_name):
self.input_name = input_name
if self._parameter_not_is_none(output_names):
self.output_names = output_names
if self._parameter_not_is_none(input_shape):
self.input_shape = input_shape
if self._parameter_not_is_none(mean):
self.mean = mean
if self._parameter_not_is_none(std):
self.mean = std
if self._parameter_not_is_none(swapRB):
self.swapRB = swapRB
if self._parameter_not_is_none(crop):
self.crop = crop
if self._parameter_not_is_none(layout):
self.layout = layout
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from pathlib import Path

from ..processes import ProcessHandler


class OpenCVDNNPythonProcess(ProcessHandler):
def __init__(self, test, executor, log):
super().__init__(test, executor, log)

@staticmethod
def create_process(test, executor, log):
return OpenCVDNNPythonProcess(test, executor, log)

def get_performance_metrics(self):
if self._status != 0 or len(self._output) == 0:
return None, None, None

result = self._output[-1].strip().split(',')
average_time = float(result[0])
fps = float(result[1])
latency = float(result[2])

return average_time, fps, latency

def _fill_command_line(self):
path_to_opencv_script = Path.joinpath(self.inference_script_root, 'inference_opencv.py')
python = ProcessHandler.get_cmd_python_version()

model = self._test.model.model
weights = self._test.model.weight
dataset = self._test.dataset.path
batch = self._test.indep_parameters.batch_size
device = self._test.indep_parameters.device
iteration = self._test.indep_parameters.iteration
common_params = f'-m {model} -w {weights} -i {dataset} -b {batch} -d {device} -ni {iteration}'

backend = self._test.dep_parameters.backend
common_params = self._add_optional_argument_to_cmd_line(common_params, '--backend', backend)

input_scale = self._test.dep_parameters.input_scale
common_params = self._add_optional_argument_to_cmd_line(common_params, '--input_scale', input_scale)

input_shape = self._test.dep_parameters.input_shape
common_params = self._add_optional_argument_to_cmd_line(common_params, '--input_shape', input_shape)

input_name = self._test.dep_parameters.input_name
common_params = self._add_optional_argument_to_cmd_line(common_params, '--input_name', input_name)

output_names = self._test.dep_parameters.output_names
common_params = self._add_optional_argument_to_cmd_line(common_params, '--output_names', output_names)

mean = self._test.dep_parameters.mean
common_params = self._add_optional_argument_to_cmd_line(common_params, '--mean', mean)

std = self._test.dep_parameters.std
common_params = self._add_optional_argument_to_cmd_line(common_params, '--std', std)

swapRB = self._test.dep_parameters.swapRB
common_params = self._add_optional_argument_to_cmd_line(common_params, '--swapRB', swapRB)

crop = self._test.dep_parameters.crop
common_params = self._add_optional_argument_to_cmd_line(common_params, '--crop', crop)

layout = self._test.dep_parameters.layout
common_params = self._add_optional_argument_to_cmd_line(common_params, '--layout', layout)

common_params = self._add_argument_to_cmd_line(common_params, '--raw_output', 'true')
command_line = f'{python} {path_to_opencv_script} {common_params}'

return command_line
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from ..config_parser.test_reporter import Test


class OpenCVDNNPythonTest(Test):
def __init__(self, model, dataset, indep_parameters, dep_parameters):
super().__init__(model, dataset, indep_parameters, dep_parameters)

def get_report(self):
parameters = {}
parameters.update({'Iteration count': self.indep_parameters.iteration})
parameters.update({'Target device': self.indep_parameters.device})
parameters.update({'Backend': self.dep_parameters.backend})
parameters.update({'Input scale': self.dep_parameters.input_scale})
parameters.update({'Input shape': self.dep_parameters.input_shape})
parameters.update({'Input name': self.dep_parameters.input_name})
parameters.update({'Output names': self.dep_parameters.output_names})
parameters.update({'Mean': self.dep_parameters.mean})
parameters.update({'Std': self.dep_parameters.std})
parameters.update({'Channel swap': self.dep_parameters.swapRB})
parameters.update({'Crop': self.dep_parameters.crop})
parameters.update({'Layout': self.dep_parameters.layout})
other_param = self._get_optional_parameters_string(parameters)

report_res = {
'task': self.model.task,
'model': self.model.name,
'dataset': self.dataset.name,
'source_framework': self.model.source_framework,
'inference_framework': self.indep_parameters.inference_framework,
'precision': self.model.precision,
'batch_size': self.indep_parameters.batch_size,
'mode': 'Sync',
'framework_params': other_param,
}

return report_res
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .opencv_dnn_python_process import OpenCVDNNPythonProcess
from .opencv_dnn_python_test import OpenCVDNNPythonTest
from ..framework_wrapper import FrameworkWrapper
from ..known_frameworks import KnownFrameworks


class OpenCVDNNPythonWrapper(FrameworkWrapper):
framework_name = KnownFrameworks.opencv

@staticmethod
def create_process(test, executor, log, cpp_benchmarks_dir=None):
return OpenCVDNNPythonProcess.create_process(test, executor, log)

@staticmethod
def create_test(model, dataset, indep_parameters, dep_parameters):
return OpenCVDNNPythonTest(model, dataset, indep_parameters, dep_parameters)
34 changes: 33 additions & 1 deletion src/configs/benchmark_configuration_file_template.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,40 @@
<InputShape></InputShape>
<Normalize></Normalize>
<Mean></Mean>
<Std></Std>
<Std></Std>
<ChannelSwap></ChannelSwap>
</FrameworkDependent>
</Test>
<Test>
<Model>
<Task></Task>
<Name></Name>
<Precision></Precision>
<SourceFramework></SourceFramework>
<ModelPath></ModelPath>
<WeightsPath></WeightsPath>
</Model>
<Dataset>
<Name></Name>
<Path></Path>
</Dataset>
<FrameworkIndependent>
<InferenceFramework>OpenCV DNN Python</InferenceFramework>
<BatchSize></BatchSize>
<Device></Device>
<IterationCount></IterationCount>
<TestTimeLimit></TestTimeLimit>
</FrameworkIndependent>
<FrameworkDependent>
<Backend>IE</Backend>
<InputScale></InputScale>
<InputName></InputName>
<InputShape></InputShape>
<OutputNames></OutputNames>
<Mean></Mean>
<SwapRB></SwapRB>
<Crop></Crop>
<Layout></Layout>
</FrameworkDependent>
</Test>
</Tests>
Loading