Лекция 3. Пример вывода обученной нейронной сети с использованием OpenVINO toolkit (Sync API)¶

1. Предварительная подготовка окружения¶

1.1. Загрузка пакетов¶

In [1]:
import openvino as ov
import cv2
import os
import numpy as np
from matplotlib import pyplot as plt

1.2. Создание и настройка окружения OpenVINO Runtime Core¶

In [2]:
device = 'CPU'


# Функция создания и настройки окружения
def create_core(device):
    # создание объекта окружения
    core = ov.Core()
    # проверка, что заданное устройство входит в число доступных устройств для запуска
    available_devices = core.available_devices
    if device not in available_devices:        
        print(f'Unsupported device \'{device}\'. Available devices: {available_devices}')
    print(f'{core}')
    return core


core = create_core(device)
<Core: available plugins[CPU, GPU]>

2. Загрузка и компиляция модели¶

Далее в качестве тестовых моделей используются DenseNet-121 и MobileNetV2. Для загрузки и конвертации указанных моделей предлагается использовать инструменты Model Downloader и Model Converter в составе OpenVINO toolkit - Open Model Zoo. Для подготовки моделей к выводу средствами OpenVINo toolkit необходимо выполнить последовательность команд, приведенную ниже. Предполагается, что сконвертированные тестовые модели находятся в директории ./trained_models.

conda create -n openvino_converter python=3.10
conda activate openvino_converter

pip install openvino-dev
pip install openvino-dev[tensorflow2]

mkdir trained_models
cd trained_models/

omz_downloader --name densenet-121-tf 
omz_converter --name densenet-121-tf

omz_downloader --name mobilenet-v2-1.4-224
omz_converter --name mobilenet-v2-1.4-224
conda deactivate

Вложенная директория public/<model_name> (<model_name> - название модели) создается автоматически инструментом Model Downloader. В результате конвертации модели внутри директории trained_models/public/<model_name> создаются вложенные директории FP16 и FP32, содержащие модель с названием <model_name>, сконвертированную в промежуточное представление OpenVINO с весами FP16 и FP32 соответственно.

In [3]:
#model_xml = './trained_models/public/densenet-121-tf/FP32/densenet-121-tf.xml'
#model_bin = './trained_models/public/densenet-121-tf/FP32/densenet-121-tf.bin'
model_xml = './trained_models/public/mobilenet-v2-1.4-224/FP32/mobilenet-v2-1.4-224.xml'
model_bin = './trained_models/public/mobilenet-v2-1.4-224/FP32/mobilenet-v2-1.4-224.bin'
batch_size = 3
input_shape = [batch_size, 224, 224, 3]


def prepare_model(model_xml, model_bin, input_shape):
    # чтение модели
    model = core.read_model(model=model_xml, weights=model_bin)
    # изменение размера входа в соответствии с размером пачки
    model.reshape(input_shape)
    # компиляция модели
    compiled_model = core.compile_model(model, device)
    return model, compiled_model


model, compiled_model = prepare_model(model_xml, model_bin, input_shape)
print(f'Model: {model}')
print(f'Compiled model: {compiled_model}')
Model: <Model: 'TensorFlow_Frontend_IR'
inputs[
<ConstOutput: names[input] shape[3,224,224,3] type: f32>
]
outputs[
<ConstOutput: names[MobilenetV2/Predictions/Reshape_1:0] shape[3,1001] type: f32>
]>
Compiled model: <CompiledModel:
inputs[
<ConstOutput: names[input] shape[3,224,224,3] type: f32>
]
outputs[
<ConstOutput: names[MobilenetV2/Predictions/Reshape_1:0] shape[3,1001] type: f32>
]>

3. Создание запроса на вывод¶

In [4]:
request = compiled_model.create_infer_request()
print(f'{request}')
<InferRequest:
inputs[
<ConstOutput: names[input] shape[3,224,224,3] type: f32>
]
outputs[
<ConstOutput: names[MobilenetV2/Predictions/Reshape_1:0] shape[3,1001] type: f32>
]>

4. Чтение данных и назначение входных тензоров¶

Для чтения и подготовки изображений используется функционал библиотеки компьютерного зрения OpenCV:

  1. cv2.read(...) - функция, обеспечивающая загрузку изображения.
  2. cv2.resize(...) - функция, обеспечивающая масштабирование изображения в соответствии с размерами входного тензора нейронной сети.
In [5]:
images_dir = '.\data'


def prepare_input(images_dir, input_image_resolution):
    files = [f for f in os.listdir(images_dir) if os.path.isfile(os.path.join(images_dir, f))]
    print(f'List of available images: {files}')
    images = []
    for file in files:
        print(f'{file}')
        image = cv2.imread(os.path.join(images_dir, file), cv2.IMREAD_COLOR)
        plt.imshow(image)
        plt.show()
        print(f'\tShape of the image {file} before resize: {image.shape}')
        image = cv2.resize(image, input_image_resolution)
        print(f'\tShape of the image {file} after resize: {image.shape}')
        images.append(image)
    return files, images


print(f'Input shape {input_shape}')
files, images = prepare_input(images_dir, input_shape[1:3])
Input shape [3, 224, 224, 3]
List of available images: ['ILSVRC2012_val_00000023.JPEG', 'ILSVRC2012_val_00000247.JPEG', 'ILSVRC2012_val_00018592.JPEG']
ILSVRC2012_val_00000023.JPEG
No description has been provided for this image
	Shape of the image ILSVRC2012_val_00000023.JPEG before resize: (510, 709, 3)
	Shape of the image ILSVRC2012_val_00000023.JPEG after resize: (224, 224, 3)
ILSVRC2012_val_00000247.JPEG
No description has been provided for this image
	Shape of the image ILSVRC2012_val_00000247.JPEG before resize: (500, 500, 3)
	Shape of the image ILSVRC2012_val_00000247.JPEG after resize: (224, 224, 3)
ILSVRC2012_val_00018592.JPEG
No description has been provided for this image
	Shape of the image ILSVRC2012_val_00018592.JPEG before resize: (500, 333, 3)
	Shape of the image ILSVRC2012_val_00018592.JPEG after resize: (224, 224, 3)
In [6]:
input_tensor = ov.Tensor(np.array(images[0:batch_size], dtype=np.float32))
print(f'Input tensor: {input_tensor}')

request.set_input_tensor(input_tensor)
Input tensor: <Tensor: shape[3,224,224,3] type: f32>

5. Запуск вывода¶

In [7]:
request.infer()
Out[7]:
{<ConstOutput: names[MobilenetV2/Predictions/Reshape_1:0] shape[3,1001] type: f32>: array([[6.08656555e-05, 3.97727017e-05, 1.43538527e-05, ...,
        2.33261708e-05, 2.65984545e-05, 7.20818571e-05],
       [1.19825680e-04, 8.69854484e-05, 3.97518415e-05, ...,
        4.31691442e-05, 5.21289185e-05, 3.87148233e-04],
       [9.49560417e-05, 5.01317991e-05, 1.08858934e-04, ...,
        5.93451841e-05, 6.60463047e-05, 5.97883882e-05]], dtype=float32)}

6. Получение и обработка выхода запроса¶

В качестве тестовых нейронных сетей используются модели, обеспечивающие решение задачи классификации с большим числом категорий на наборе данных ImageNet. На выходе этих сетей формируется вектор достоверностей принадлежности входного изоображения каждому из допустимых 1000 классов, представленных в наборе ImageNet (перечень классов доступен в файле ./labels/image_net_synset.txt). Отметим, что некоторые модели строят на выходе вектор из 1001 элемента, поскольку учитывается класс фона (перечень классов доступен в файле ./labels/image_net_synset_first_class_base.txt).

Обработка выходного вектора достоверностей состоит в выборе K классов, для которых получена максимальная достоверность, и вывод названий этих классов.

In [8]:
#labels_file_name = './labels/image_net_synset.txt'
labels_file_name = './labels/image_net_synset_first_class_base.txt'
topk = 5


# функция загрузки меток классов
def load_labels_map(labels_file_name):
   with open(labels_file_name, 'r') as f:
       labels_map = [line.strip() for line in f]
   return labels_map    

# функция печати topk-классов и соответствующих достоверностей
def process_output(files, output_data, labels_file_name, topk=5):
    labels_map = load_labels_map(labels_file_name)
    for i in range(len(output_data)):
        file_name = files[i]
        probs_ = np.squeeze(output_data[i])
        top_ind = np.argsort(probs_)[-topk:][::-1]
        print(f'{file_name}')
        for id_ in top_ind:
            det_label = labels_map[id_] if labels_map else '#{0}'.format(id_)
            print('\t{}\t{:.7f}\t{}'.format(id_, probs_[id_], det_label))


output_data = request.get_output_tensor().data
process_output(files, output_data, labels_file_name, topk)
ILSVRC2012_val_00000023.JPEG
	949	0.8810009	Granny Smith
	953	0.0252363	fig
	956	0.0074155	jackfruit, jak, jack
	957	0.0054692	custard apple
	952	0.0037351	lemon
ILSVRC2012_val_00000247.JPEG
	14	0.8708091	junco, snowbird
	15	0.0020907	indigo bunting, indigo finch, indigo bird, Passerina cyanea
	21	0.0017842	water ouzel, dipper
	11	0.0014236	brambling, Fringilla montifringilla
	20	0.0013358	chickadee
ILSVRC2012_val_00018592.JPEG
	626	0.8931448	lifeboat
	511	0.0078882	container ship, containership, container vessel
	629	0.0038566	liner, ocean liner
	537	0.0020695	dock, dockage, docking facility
	725	0.0017923	pirate, pirate ship

7. Удаление рабочих объектов¶

In [9]:
del model
del compiled_model
del core