В этом руководстве мы увидим, как мы можем использовать предварительно обученный модуль Tensorflow в модуле OpenCV DNN. OpenCV ≥ 3.4.3 имеет модуль Deep Neural Netowork, который можно использовать для вывода с использованием предварительно обученной модели. OpenCV поддерживает следующие фреймворки: Caffe, Tensorflow, Darknet и PyTorch. Но вы не можете напрямую использовать предварительно обученную модель Tensorflow с модулем OpenCV DNN. Ниже мы увидим, какие шаги мы должны выполнить, чтобы модуль Tensorflow работал с модулем OpenCV DNN.

Технические характеристики системы:

  1. Tensorflow 1.13
  2. OpenCV 4.0.1

Описание модели Tensorflow:

В этой статье я использовал свою предварительно обученную модель распознавания текста. Используемые слои:

  1. Набор данных и итераторы (я использовал OneShotIterator)
  2. Заполнители
  3. Сверточные слои с пакетной нормализацией
  4. MaxPool
  5. Полностью связанные слои с пакетной нормализацией
  6. Выбывать
  7. Функция активации Relu, Softmax

Необходимые шаги:

  1. График замораживания
  2. Преобразование графа
  3. Замена заполнителей на константы
  4. Оптимизация блоков пакетной нормализации
  5. Удаление блоков отсева

Шаг 1: замораживание графика

После того, как вы закончите обучение своей модели, у вас будут файлы .meta и файлы контрольных точек. Как видно из приведенного выше графика, в нашем графике есть множество обучаемых переменных и узлов. Все это не требуется во время вывода. Таким образом, мы можем удалить их из нашего графика. Также мы преобразуем переменные контрольной точки в операцию Const. Мы будем использовать инструмент freeze_graph.py от Tensorflow.

python3 freeze_graph.py --input_meta_graph alpha_digit_ocr_engine-171439.meta --input_checkpoint alpha_digit_ocr_engine-171439 --output_graph frozen_inference_graph.pb --output_node_names predicated_output --input_binary True

Шаг 2: преобразование графика

После замораживания графа у нас все еще есть некоторые узлы, специфичные для Tensorflow, такие как набор данных, итераторы, обучающий блок пакетной нормализации и которые не нужны во время вывода. Мы воспользуемся инструментом Преобразование графика от Tensorflow.

В TransformGraph правильно укажите входной и выходной узел, чтобы он оставил только узлы, связанные с входом и выходом.

Мы применили следующее преобразование.

  1. Strip_unused_nodes: удалить неиспользуемые узлы для вывода
  2. Remove_nodes: удалить любые определенные узлы, такие как узлы идентификации.
  3. Fold_constants: ищет любые подграфы в модели, которые всегда вычисляются как константные выражения, и заменяет их этими константами.
  4. Fold_batch_norms: Оптимизировать блок пакетной нормализации. Это преобразование необходимо, если вы использовали пакетную нормализацию во время обучения.
  5. Fold_old_batch_norms: для нормализации старого пакета.
  6. Sort_by_execution_order: расположите узлы в топологическом порядке. Это важное преобразование, потому что OpenCV проанализирует граф в топологическом порядке. И если граф не в топологическом порядке, это приведет к ошибке некоторых недостающих узлов.

Шаг 3. Замена заполнителей на константы

У нас должен быть только один заполнитель ввода. Поэтому мы заменим другие заполнители, такие как keep_prob (используется в выпадении), is_training (используется при пакетной нормализации) на узел Constant.

Шаг 4. Оптимизация блока нормализации пакета

Не все операции (операции) Tensorflow определены в OpenCV. Такие операции, как Switch и Merge (используются внутри batch_normalization), RandomUniform (используются внутри dropout), не определены в OpenCV. Поэтому мы должны проверить всех этих операторов и упростить эти блоки.

После того, как обучение завершено, нам больше не понадобится такой сложный блок для вывода. Мы можем заменить весь блок пакетной нормализации операциями FusedBatchNorm. Мы также должны изменить вход для этого узла. И вход в следующий сверточный узел или узел MaxPool должен быть выходом этого узла.

Блок пакетных норм в Полносвязном слое мало отличается от блока в сверточном слое. Мы можем удалить блоки moment, cond_1 и cond и изменить вход блока batchnorm.

Важно: прежде чем перейти к следующему шагу, вызовите функцию transform_graph (), определенную на шаге 2. Это дополнительно оптимизирует узел пакетной нормализации.

Шаг 5. Снятие блокировки отсева

Бросить школу нужно только во время тренировки. Во время вывода мы передаем 1 в keep_prob, который проверяет наличие всех нейронов. Таким образом, мы можем удалить выпадающий слой и напрямую подключить выход полностью подключенного слоя fc1 к входу полностью подключенного слоя fc2. Блок выпадения имеет операцию RandomUniform, которая не определена в OpenCV. Так что это вызовет ошибку.

Наконец, вызовите transform_graph (), чтобы убедиться, что все константы свернуты, и, что более важно, чтобы убедиться, что граф находится в топологическом порядке. Файл графика, созданный последней transform_graph (), используется в модуле OpenCV DNN.

Тестирование:

Полный код:

Важные моменты:

  1. Убедитесь, что граф находится в топологическом порядке.
  2. Заморозьте график, чтобы преобразовать переменные в константы.
  3. Операции Tensorflow, определенные в модуле OpenCV DNN: Conv2D, SpaceToBatchND, DepthwiseConv2dNative, Pad, BiasAdd, Add, Sub, MatMul, Reshape, Flatten, Squeeze, Transpose, Const, LRN, Concat, ConcatV2, MaxPool, AvgPool, Placeholder, Split, Slit Mul, FusedBatchNorm, Conv2DBackpropInput, BlockLSTM, ResizeNearestNeighbor, ResizeBilinear, L2Normalize, PriorBox, Softmax, CropAndResize, Mean, ClipByValue, Abs, Tanh, Sigmoid, Relu, Elu, Identity, Relu6.
  4. Убедитесь, что ваш график содержит операции, упомянутые в пункте №3.
  5. Если у вас есть операция, которой нет в № 3, проверьте, относятся ли эти операции к обучению. Если да, удалите их с графика.
  6. Используйте тензорную доску для визуализации вашего графика и попытайтесь оптимизировать его, где это возможно.

Заключение:

В этой статье мы узнали, как мы можем использовать предварительно обученный граф Tensorflow с модулем OpenCV DNN. Также он оптимизирует график, что сократит время вывода. Надеюсь, вам понравилась эта длинная статья, и вы узнали что-то новое и полезное.