Hello classification, classification_async, hello_reshape_ssd python samples with API 2.0 (#9091)
* Hello classification python with API 2.0 * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Ekaterina Aidova <ekaterina.aidova@intel.com> * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Ekaterina Aidova <ekaterina.aidova@intel.com> * changed linters processing * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> * Update samples/python/hello_classification/hello_classification.py Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> * updated import * Moved classification_sample_async to new API 2.0 * moved hello_reshape_ssd sample to new API 2.0 * [classification_sample_async] refactoring * [hello_classification] refactoring * [hello_reshape_ssd] refactoring Co-authored-by: Ekaterina Aidova <ekaterina.aidova@intel.com> Co-authored-by: Vladimir Dudnik <vladimir.dudnik@intel.com> Co-authored-by: Dmitry Pigasin <dmitry.pigasin@intel.com>
This commit is contained in:
@@ -2,13 +2,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import logging as log
|
||||
import sys
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from openvino.inference_engine import IECore, StatusCode
|
||||
from openvino.preprocess import PrePostProcessor
|
||||
from openvino.runtime import AsyncInferQueue, Core, InferRequest, Layout, Type
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
@@ -16,150 +18,111 @@ def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
args.add_argument('-h', '--help', action='help',
|
||||
help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', type=str, required=True,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
args.add_argument('-i', '--input', required=True, type=str, nargs='+', help='Required. Path to an image file(s).')
|
||||
args.add_argument('-l', '--extension', type=str, default=None,
|
||||
help='Optional. Required by the CPU Plugin for executing the custom operation on a CPU. '
|
||||
'Absolute path to a shared library with the kernels implementations.')
|
||||
args.add_argument('-c', '--config', type=str, default=None,
|
||||
help='Optional. Required by GPU or VPU Plugins for the custom operation kernel. '
|
||||
'Absolute path to operation description file (.xml).')
|
||||
args.add_argument('-d', '--device', default='CPU', type=str,
|
||||
args.add_argument('-i', '--input', type=str, required=True, nargs='+',
|
||||
help='Required. Path to an image file(s).')
|
||||
args.add_argument('-d', '--device', type=str, default='CPU',
|
||||
help='Optional. Specify the target device to infer on; CPU, GPU, MYRIAD, HDDL or HETERO: '
|
||||
'is acceptable. The sample will look for a suitable plugin for device specified. '
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
args.add_argument('-nt', '--number_top', default=10, type=int, help='Optional. Number of top results.')
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
def completion_callback(infer_request: InferRequest, image_path: str) -> None:
|
||||
predictions = next(iter(infer_request.results.values()))
|
||||
|
||||
# Change a shape of a numpy.ndarray with results to get another one with one dimension
|
||||
probs = predictions.reshape(-1)
|
||||
|
||||
# Get an array of 10 class IDs in descending order of probability
|
||||
top_10 = np.argsort(probs)[-10:][::-1]
|
||||
|
||||
header = 'class_id probability'
|
||||
|
||||
log.info(f'Image path: {image_path}')
|
||||
log.info('Top 10 results: ')
|
||||
log.info(header)
|
||||
log.info('-' * len(header))
|
||||
|
||||
for class_id in top_10:
|
||||
probability_indent = ' ' * (len('class_id') - len(str(class_id)) + 1)
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}')
|
||||
|
||||
log.info('')
|
||||
|
||||
|
||||
def main() -> int:
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
# --------------------------- Step 1. Initialize OpenVINO Runtime Core ------------------------------------------------
|
||||
log.info('Creating OpenVINO Runtime Core')
|
||||
core = Core()
|
||||
|
||||
if args.extension and args.device == 'CPU':
|
||||
log.info(f'Loading the {args.device} extension: {args.extension}')
|
||||
ie.add_extension(args.extension, args.device)
|
||||
|
||||
if args.config and args.device in ('GPU', 'MYRIAD', 'HDDL'):
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
# --------------------------- Step 2. Read a model --------------------------------------------------------------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
model = core.read_model(args.model)
|
||||
|
||||
if len(net.input_info) != 1:
|
||||
if len(model.inputs) != 1:
|
||||
log.error('Sample supports only single input topologies')
|
||||
return -1
|
||||
if len(net.outputs) != 1:
|
||||
|
||||
if len(model.outputs) != 1:
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
out_blob = next(iter(net.outputs))
|
||||
# --------------------------- Step 3. Set up input --------------------------------------------------------------------
|
||||
# Read input images
|
||||
images = [cv2.imread(image_path) for image_path in args.input]
|
||||
|
||||
# Set input and output precision manually
|
||||
net.input_info[input_blob].precision = 'U8'
|
||||
net.outputs[out_blob].precision = 'FP32'
|
||||
# Resize images to model input dims
|
||||
_, _, h, w = model.input().shape
|
||||
resized_images = [cv2.resize(image, (w, h)) for image in images]
|
||||
|
||||
# Get a number of input images
|
||||
num_of_input = len(args.input)
|
||||
# Get a number of classes recognized by a model
|
||||
num_of_classes = max(net.outputs[out_blob].shape)
|
||||
# Add N dimension
|
||||
input_tensors = [np.expand_dims(image, 0) for image in resized_images]
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# --------------------------- Step 4. Apply preprocessing -------------------------------------------------------------
|
||||
ppp = PrePostProcessor(model)
|
||||
|
||||
# 1) Set input tensor information:
|
||||
# - input() provides information about a single model input
|
||||
# - precision of tensor is supposed to be 'u8'
|
||||
# - layout of data is 'NHWC'
|
||||
ppp.input().tensor() \
|
||||
.set_element_type(Type.u8) \
|
||||
.set_layout(Layout('NHWC')) # noqa: N400
|
||||
|
||||
# 2) Here we suppose model has 'NCHW' layout for input
|
||||
ppp.input().model().set_layout(Layout('NCHW'))
|
||||
|
||||
# 3) Set output tensor information:
|
||||
# - precision of tensor is supposed to be 'f32'
|
||||
ppp.output().tensor().set_element_type(Type.f32)
|
||||
|
||||
# 4) Apply preprocessing modifing the original 'model'
|
||||
model = ppp.build()
|
||||
|
||||
# --------------------------- Step 5. Loading model to the device -----------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device, num_requests=num_of_input)
|
||||
compiled_model = core.compile_model(model, args.device)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
input_data = []
|
||||
_, _, h, w = net.input_info[input_blob].input_data.shape
|
||||
|
||||
for i in range(num_of_input):
|
||||
image = cv2.imread(args.input[i])
|
||||
|
||||
if image.shape[:-1] != (h, w):
|
||||
log.warning(f'Image {args.input[i]} is resized from {image.shape[:-1]} to {(h, w)}')
|
||||
image = cv2.resize(image, (w, h))
|
||||
|
||||
# Change data layout from HWC to CHW
|
||||
image = image.transpose((2, 0, 1))
|
||||
# Add N dimension to transform to NCHW
|
||||
image = np.expand_dims(image, axis=0)
|
||||
|
||||
input_data.append(image)
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# --------------------------- Step 6. Create infer request queue ------------------------------------------------------
|
||||
log.info('Starting inference in asynchronous mode')
|
||||
for i in range(num_of_input):
|
||||
exec_net.requests[i].async_infer({input_blob: input_data[i]})
|
||||
infer_queue = AsyncInferQueue(compiled_model, len(input_tensors))
|
||||
infer_queue.set_callback(completion_callback)
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
labels = [line.split(',')[0].strip() for line in f]
|
||||
# --------------------------- Step 7. Do inference --------------------------------------------------------------------
|
||||
for i, input_tensor in enumerate(input_tensors):
|
||||
infer_queue.start_async({0: input_tensor}, args.input[i])
|
||||
|
||||
# Create a list to control a order of output
|
||||
output_queue = list(range(num_of_input))
|
||||
|
||||
while True:
|
||||
for i in output_queue:
|
||||
# Immediately returns a inference status without blocking or interrupting
|
||||
infer_status = exec_net.requests[i].wait(0)
|
||||
|
||||
if infer_status == StatusCode.RESULT_NOT_READY:
|
||||
continue
|
||||
|
||||
log.info(f'Infer request {i} returned {infer_status}')
|
||||
|
||||
if infer_status != StatusCode.OK:
|
||||
return -2
|
||||
|
||||
# Read infer request results from buffer
|
||||
res = exec_net.requests[i].output_blobs[out_blob].buffer
|
||||
# Change a shape of a numpy.ndarray with results to get another one with one dimension
|
||||
probs = res.reshape(num_of_classes)
|
||||
# Get an array of args.number_top class IDs in descending order of probability
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top :][::-1]
|
||||
|
||||
header = 'classid probability'
|
||||
header = header + ' label' if args.labels else header
|
||||
|
||||
log.info(f'Image path: {args.input[i]}')
|
||||
log.info(f'Top {args.number_top} results: ')
|
||||
log.info(header)
|
||||
log.info('-' * len(header))
|
||||
|
||||
for class_id in top_n_idexes:
|
||||
probability_indent = ' ' * (len('classid') - len(str(class_id)) + 1)
|
||||
label_indent = ' ' * (len('probability') - 8) if args.labels else ''
|
||||
label = labels[class_id] if args.labels else ''
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}{label_indent}{label}')
|
||||
log.info('')
|
||||
|
||||
output_queue.remove(i)
|
||||
|
||||
if len(output_queue) == 0:
|
||||
break
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
infer_queue.wait_all()
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
@@ -2,121 +2,111 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import argparse
|
||||
|
||||
import logging as log
|
||||
import sys
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from openvino.inference_engine import IECore
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
args.add_argument('-i', '--input', required=True, type=str, help='Required. Path to an image file.')
|
||||
args.add_argument('-d', '--device', default='CPU', type=str,
|
||||
help='Optional. Specify the target device to infer on; CPU, GPU, MYRIAD, HDDL or HETERO: '
|
||||
'is acceptable. The sample will look for a suitable plugin for device specified. '
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
args.add_argument('-nt', '--number_top', default=10, type=int, help='Optional. Number of top results.')
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
from openvino.preprocess import PrePostProcessor, ResizeAlgorithm
|
||||
from openvino.runtime import Core, Layout, Type
|
||||
|
||||
|
||||
def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
# Parsing and validation of input arguments
|
||||
if len(sys.argv) != 4:
|
||||
log.info('Usage: <path_to_model> <path_to_image> <device_name>')
|
||||
return 1
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
model_path = sys.argv[1]
|
||||
image_path = sys.argv[2]
|
||||
device_name = sys.argv[3]
|
||||
|
||||
# --------------------------- Step 1. Initialize OpenVINO Runtime Core ------------------------------------------------
|
||||
log.info('Creating OpenVINO Runtime Core')
|
||||
core = Core()
|
||||
|
||||
# --------------------------- Step 2. Read a model --------------------------------------------------------------------
|
||||
log.info(f'Reading the network: {model_path}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
model = core.read_model(model_path)
|
||||
|
||||
if len(net.input_info) != 1:
|
||||
if len(model.inputs) != 1:
|
||||
log.error('Sample supports only single input topologies')
|
||||
return -1
|
||||
if len(net.outputs) != 1:
|
||||
|
||||
if len(model.outputs) != 1:
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
out_blob = next(iter(net.outputs))
|
||||
# --------------------------- Step 3. Set up input --------------------------------------------------------------------
|
||||
# Read input image
|
||||
image = cv2.imread(image_path)
|
||||
# Add N dimension
|
||||
input_tensor = np.expand_dims(image, 0)
|
||||
|
||||
# Set input and output precision manually
|
||||
net.input_info[input_blob].precision = 'U8'
|
||||
net.outputs[out_blob].precision = 'FP32'
|
||||
# --------------------------- Step 4. Apply preprocessing -------------------------------------------------------------
|
||||
ppp = PrePostProcessor(model)
|
||||
|
||||
# Get a number of classes recognized by a model
|
||||
num_of_classes = max(net.outputs[out_blob].shape)
|
||||
_, h, w, _ = input_tensor.shape
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# 1) Set input tensor information:
|
||||
# - input() provides information about a single model input
|
||||
# - precision of tensor is supposed to be 'u8'
|
||||
# - layout of data is 'NHWC'
|
||||
# - set static spatial dimensions to input tensor to resize from
|
||||
ppp.input().tensor() \
|
||||
.set_element_type(Type.u8) \
|
||||
.set_layout(Layout('NHWC')) \
|
||||
.set_spatial_static_shape(h, w) # noqa: ECE001, N400
|
||||
|
||||
# 2) Adding explicit preprocessing steps:
|
||||
# - apply linear resize from tensor spatial dims to model spatial dims
|
||||
ppp.input().preprocess().resize(ResizeAlgorithm.RESIZE_LINEAR)
|
||||
|
||||
# 3) Here we suppose model has 'NCHW' layout for input
|
||||
ppp.input().model().set_layout(Layout('NCHW'))
|
||||
|
||||
# 4) Set output tensor information:
|
||||
# - precision of tensor is supposed to be 'f32'
|
||||
ppp.output().tensor().set_element_type(Type.f32)
|
||||
|
||||
# 5) Apply preprocessing modifing the original 'model'
|
||||
model = ppp.build()
|
||||
|
||||
# --------------------------- Step 5. Loading model to the device -----------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
compiled_model = core.compile_model(model, device_name)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
original_image = cv2.imread(args.input)
|
||||
image = original_image.copy()
|
||||
_, _, h, w = net.input_info[input_blob].input_data.shape
|
||||
|
||||
if image.shape[:-1] != (h, w):
|
||||
log.warning(f'Image {args.input} is resized from {image.shape[:-1]} to {(h, w)}')
|
||||
image = cv2.resize(image, (w, h))
|
||||
|
||||
# Change data layout from HWC to CHW
|
||||
image = image.transpose((2, 0, 1))
|
||||
# Add N dimension to transform to NCHW
|
||||
image = np.expand_dims(image, axis=0)
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# --------------------------- Step 6. Create infer request and do inference synchronously -----------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: image})
|
||||
results = compiled_model.infer_new_request({0: input_tensor})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
labels = [line.split(',')[0].strip() for line in f]
|
||||
# --------------------------- Step 7. Process output ------------------------------------------------------------------
|
||||
predictions = next(iter(results.values()))
|
||||
|
||||
res = res[out_blob]
|
||||
# Change a shape of a numpy.ndarray with results to get another one with one dimension
|
||||
probs = res.reshape(num_of_classes)
|
||||
# Get an array of args.number_top class IDs in descending order of probability
|
||||
top_n_idexes = np.argsort(probs)[-args.number_top :][::-1]
|
||||
probs = predictions.reshape(-1)
|
||||
|
||||
header = 'classid probability'
|
||||
header = header + ' label' if args.labels else header
|
||||
# Get an array of 10 class IDs in descending order of probability
|
||||
top_10 = np.argsort(probs)[-10:][::-1]
|
||||
|
||||
log.info(f'Image path: {args.input}')
|
||||
log.info(f'Top {args.number_top} results: ')
|
||||
header = 'class_id probability'
|
||||
|
||||
log.info(f'Image path: {image_path}')
|
||||
log.info('Top 10 results: ')
|
||||
log.info(header)
|
||||
log.info('-' * len(header))
|
||||
|
||||
for class_id in top_n_idexes:
|
||||
probability_indent = ' ' * (len('classid') - len(str(class_id)) + 1)
|
||||
label_indent = ' ' * (len('probability') - 8) if args.labels else ''
|
||||
label = labels[class_id] if args.labels else ''
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}{label_indent}{label}')
|
||||
for class_id in top_10:
|
||||
probability_indent = ' ' * (len('class_id') - len(str(class_id)) + 1)
|
||||
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}')
|
||||
|
||||
log.info('')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
@@ -2,144 +2,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import argparse
|
||||
|
||||
import logging as log
|
||||
import os
|
||||
import sys
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from openvino.inference_engine import IECore
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
"""Parse and return command line arguments"""
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
args = parser.add_argument_group('Options')
|
||||
# fmt: off
|
||||
args.add_argument('-h', '--help', action='help', help='Show this help message and exit.')
|
||||
args.add_argument('-m', '--model', required=True, type=str,
|
||||
help='Required. Path to an .xml or .onnx file with a trained model.')
|
||||
args.add_argument('-i', '--input', required=True, type=str, help='Required. Path to an image file.')
|
||||
args.add_argument('-l', '--extension', type=str, default=None,
|
||||
help='Optional. Required by the CPU Plugin for executing the custom operation on a CPU. '
|
||||
'Absolute path to a shared library with the kernels implementations.')
|
||||
args.add_argument('-c', '--config', type=str, default=None,
|
||||
help='Optional. Required by GPU or VPU Plugins for the custom operation kernel. '
|
||||
'Absolute path to operation description file (.xml).')
|
||||
args.add_argument('-d', '--device', default='CPU', type=str,
|
||||
help='Optional. Specify the target device to infer on; CPU, GPU, MYRIAD, HDDL or HETERO: '
|
||||
'is acceptable. The sample will look for a suitable plugin for device specified. '
|
||||
'Default value is CPU.')
|
||||
args.add_argument('--labels', default=None, type=str, help='Optional. Path to a labels mapping file.')
|
||||
# fmt: on
|
||||
return parser.parse_args()
|
||||
from openvino.preprocess import PrePostProcessor
|
||||
from openvino.runtime import Core, Layout, PartialShape, Type
|
||||
|
||||
|
||||
def main():
|
||||
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
||||
args = parse_args()
|
||||
|
||||
# ---------------------------Step 1. Initialize inference engine core--------------------------------------------------
|
||||
log.info('Creating Inference Engine')
|
||||
ie = IECore()
|
||||
# Parsing and validation of input arguments
|
||||
if len(sys.argv) != 4:
|
||||
log.info('Usage: <path_to_model> <path_to_image> <device_name>')
|
||||
return 1
|
||||
|
||||
if args.extension and args.device == 'CPU':
|
||||
log.info(f'Loading the {args.device} extension: {args.extension}')
|
||||
ie.add_extension(args.extension, args.device)
|
||||
model_path = sys.argv[1]
|
||||
image_path = sys.argv[2]
|
||||
device_name = sys.argv[3]
|
||||
|
||||
if args.config and args.device in ('GPU', 'MYRIAD', 'HDDL'):
|
||||
log.info(f'Loading the {args.device} configuration: {args.config}')
|
||||
ie.set_config({'CONFIG_FILE': args.config}, args.device)
|
||||
# --------------------------- Step 1. Initialize OpenVINO Runtime Core ------------------------------------------------
|
||||
log.info('Creating OpenVINO Runtime Core')
|
||||
core = Core()
|
||||
|
||||
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation or ONNX format---------------
|
||||
log.info(f'Reading the network: {args.model}')
|
||||
# --------------------------- Step 2. Read a model --------------------------------------------------------------------
|
||||
log.info(f'Reading the network: {model_path}')
|
||||
# (.xml and .bin files) or (.onnx file)
|
||||
net = ie.read_network(model=args.model)
|
||||
model = core.read_model(model_path)
|
||||
|
||||
if len(net.input_info) != 1:
|
||||
if len(model.inputs) != 1:
|
||||
log.error('Sample supports only single input topologies')
|
||||
return -1
|
||||
if len(net.outputs) != 1:
|
||||
|
||||
if len(model.outputs) != 1:
|
||||
log.error('Sample supports only single output topologies')
|
||||
return -1
|
||||
|
||||
# ---------------------------Step 3. Configure input & output----------------------------------------------------------
|
||||
log.info('Configuring input and output blobs')
|
||||
# Get names of input and output blobs
|
||||
input_blob = next(iter(net.input_info))
|
||||
out_blob = next(iter(net.outputs))
|
||||
|
||||
# Set input and output precision manually
|
||||
net.input_info[input_blob].precision = 'U8'
|
||||
net.outputs[out_blob].precision = 'FP32'
|
||||
|
||||
original_image = cv2.imread(args.input)
|
||||
image = original_image.copy()
|
||||
|
||||
# Change data layout from HWC to CHW
|
||||
image = image.transpose((2, 0, 1))
|
||||
# Add N dimension to transform to NCHW
|
||||
image = np.expand_dims(image, axis=0)
|
||||
# --------------------------- Step 3. Set up input --------------------------------------------------------------------
|
||||
# Read input image
|
||||
image = cv2.imread(image_path)
|
||||
# Add N dimension
|
||||
input_tensor = np.expand_dims(image, 0)
|
||||
|
||||
log.info('Reshaping the network to the height and width of the input image')
|
||||
log.info(f'Input shape before reshape: {net.input_info[input_blob].input_data.shape}')
|
||||
net.reshape({input_blob: image.shape})
|
||||
log.info(f'Input shape after reshape: {net.input_info[input_blob].input_data.shape}')
|
||||
n, h, w, c = input_tensor.shape
|
||||
model.reshape({model.input().get_any_name(): PartialShape((n, c, h, w))})
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
# --------------------------- Step 4. Apply preprocessing -------------------------------------------------------------
|
||||
ppp = PrePostProcessor(model)
|
||||
|
||||
# 1) Set input tensor information:
|
||||
# - input() provides information about a single model input
|
||||
# - precision of tensor is supposed to be 'u8'
|
||||
# - layout of data is 'NHWC'
|
||||
ppp.input().tensor() \
|
||||
.set_element_type(Type.u8) \
|
||||
.set_layout(Layout('NHWC')) # noqa: N400
|
||||
|
||||
# 2) Here we suppose model has 'NCHW' layout for input
|
||||
ppp.input().model().set_layout(Layout('NCHW'))
|
||||
|
||||
# 3) Set output tensor information:
|
||||
# - precision of tensor is supposed to be 'f32'
|
||||
ppp.output().tensor().set_element_type(Type.f32)
|
||||
|
||||
# 4) Apply preprocessing modifing the original 'model'
|
||||
model = ppp.build()
|
||||
|
||||
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
||||
log.info('Loading the model to the plugin')
|
||||
exec_net = ie.load_network(network=net, device_name=args.device)
|
||||
compiled_model = core.compile_model(model, device_name)
|
||||
|
||||
# ---------------------------Step 5. Create infer request--------------------------------------------------------------
|
||||
# load_network() method of the IECore class with a specified number of requests (default 1) returns an ExecutableNetwork
|
||||
# instance which stores infer requests. So you already created Infer requests in the previous step.
|
||||
|
||||
# ---------------------------Step 6. Prepare input---------------------------------------------------------------------
|
||||
# This sample changes a network input layer shape instead of a image shape. See Step 4.
|
||||
|
||||
# ---------------------------Step 7. Do inference----------------------------------------------------------------------
|
||||
# --------------------------- Step 6. Create infer request and do inference synchronously -----------------------------
|
||||
log.info('Starting inference in synchronous mode')
|
||||
res = exec_net.infer(inputs={input_blob: image})
|
||||
results = compiled_model.infer_new_request({0: input_tensor})
|
||||
|
||||
# ---------------------------Step 8. Process output--------------------------------------------------------------------
|
||||
# Generate a label list
|
||||
if args.labels:
|
||||
with open(args.labels, 'r') as f:
|
||||
labels = [line.split(',')[0].strip() for line in f]
|
||||
|
||||
res = res[out_blob]
|
||||
|
||||
output_image = original_image.copy()
|
||||
h, w, _ = output_image.shape
|
||||
# ---------------------------Step 6. Process output--------------------------------------------------------------------
|
||||
predictions = next(iter(results.values()))
|
||||
|
||||
# Change a shape of a numpy.ndarray with results ([1, 1, N, 7]) to get another one ([N, 7]),
|
||||
# where N is the number of detected bounding boxes
|
||||
detections = res.reshape(-1, 7)
|
||||
detections = predictions.reshape(-1, 7)
|
||||
|
||||
for detection in detections:
|
||||
confidence = detection[2]
|
||||
|
||||
if confidence > 0.5:
|
||||
class_id = int(detection[1])
|
||||
label = labels[class_id] if args.labels else class_id
|
||||
|
||||
xmin = int(detection[3] * w)
|
||||
ymin = int(detection[4] * h)
|
||||
xmax = int(detection[5] * w)
|
||||
ymax = int(detection[6] * h)
|
||||
|
||||
log.info(f'Found: label = {label}, confidence = {confidence:.2f}, ' f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
log.info(f'Found: class_id = {class_id}, confidence = {confidence:.2f}, ' f'coords = ({xmin}, {ymin}), ({xmax}, {ymax})')
|
||||
|
||||
# Draw a bounding box on a output image
|
||||
cv2.rectangle(output_image, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
|
||||
cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
|
||||
|
||||
cv2.imwrite('out.bmp', image)
|
||||
|
||||
cv2.imwrite('out.bmp', output_image)
|
||||
if os.path.exists('out.bmp'):
|
||||
log.info('Image out.bmp was created!')
|
||||
else:
|
||||
log.error('Image out.bmp was not created. Check your permissions.')
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user