OpenCV - серия учебных пособий по Node.js

Добро пожаловать в еще один учебник по Node.js - OpenCV. Сегодня мы рассмотрим модуль Deep Neural Networks OpenCV.

Если вы хотите раскрыть возможности нейронных сетей для распознавания и классификации объектов на изображениях, но, как и я, не имеете абсолютно никакого представления о том, как работает глубокое обучение, не говоря уже о том, как самостоятельно построить и обучить нейронную сеть, тогда у меня есть хорошие новости для вас!

Итак, что мы будем строить сегодня?

В этом руководстве мы узнаем, как загружать предварительно обученные модели из Tensorflow и Caffe с помощью модуля DNN OpenCV, и мы рассмотрим два примера распознавания объектов с помощью Node.js и OpenCV.

Сначала мы будем использовать модель Inception Tensorflow для распознавания объекта, показанного на изображении, а после этого мы будем использовать модель COCO SSD для обнаружения и распознавания нескольких различных объектов на одном изображении. .

Посмотрим, как это работает! Как всегда, исходный код примеров можно найти в моем репозитории github.

Эта статья является частью серии руководств OpenCV - Node.js. Обязательно ознакомьтесь с другими моими статьями:

Начало тензорного потока

Модель Tensorflow Inception обучена распознавать объекты классов ~ 1000. Если вы загрузите изображение в сеть, оно покажет вероятность каждого класса для объекта, показанного на изображении.

Чтобы использовать модель Inception с OpenCV, мы должны загрузить двоичный файл tensorflow_inception_graph.pb и список имен классов из imagenet_comp_graph_label_strings.txt. Вы можете получить эти файлы, загрузив и распаковав inception5h.zip (см. Ссылку образец кода).

Классификация объектов на изображении

Чтобы классифицировать объект изображения, мы напишем следующую вспомогательную функцию:

Эта функция выполняет следующие функции:

Подготовьте входное изображение

Прежде всего, мы должны знать, что сеть Tensorflow Inception принимает входные изображения размером 224x224. Вот почему мы изменяем размер изображения так, чтобы его наибольший размер составлял 224, а оставшийся размер изображения дополняем белыми пикселями, так что ширина = высота (padToSquare).

Передайте изображение по сети

Мы можем просто создать большой двоичный объект из изображения и вызвать net.forward () для пересылки входных данных и получения выходных двоичных объектов.

Извлеките результат из выходного большого двоичного объекта

В целях обобщения выходной BLOB-объект просто выражается в виде матрицы (cv.Mat), и его размерность зависит от модели. С Inception это просто. Большой двоичный объект представляет собой матрицу размером 1xN (где N равно количеству классов), которая описывает распределение вероятностей для всех классов. Каждая запись содержит плавающее число, представляющее степень достоверности для соответствующего класса. Сумма записей составляет 1,0 (100%).

Мы хотим внимательнее изучить наиболее вероятные классы для нашего изображения, поэтому мы ищем классы с уверенностью, большей, чем minConfidence (5% в этом примере ).

Этого легко добиться, мы просто установим пороговое значение для всех значений в матрице с точностью 0,05 и найдем все записи, которые не равны нулю (findNonZero). Наконец, мы отсортируем результат по достоверности и вернем пары className с достоверностью.

Попробуй это!

Теперь мы прочитаем некоторые образцы данных, которые мы хотим, чтобы сеть распознала:

Если мы запустим прогноз для каждого изображения, мы получим следующий результат (или увидим изображение заголовка):

banana:
banana (0.95)
husky:
Siberian husky (0.78)
Eskimo dog (0.21)
car:
sports car (0.57)
racer (0.12)
lenna:
sombrero (0.34)
cowboy hat (0.3)

Довольно интересно. Мы получаем довольно точное описание содержимого изображения хаски и банана. Для автомобиля мы можем получить разные категории автомобилей, но мы можем определенно сказать, что это автомобиль, показанный на изображении. Конечно, сеть не может быть обучена на бесконечных классах, поэтому она не возвращает какое-то описание типа «женщина» для последнего изображения. Однако он узнает шляпу.

COCO SSD

Хорошо, это сработало очень хорошо, но как нам поступать с изображениями, на которых изображено несколько объектов? Чтобы распознать несколько объектов на одном изображении, мы будем использовать так называемый Single Shot Multibox Detector (SSD). Во втором примере мы рассмотрим модель SSD, обученную с помощью набора данных COCO (общий объект в контексте). Используемая нами модель была обучена на 84 различных классах.

Поскольку эта модель является моделью Caffe, мы должны загрузить двоичный файл «VGG_coco_SSD_300x300_iter_400000.caffemodel», а также файл протокола «deploy.prototxt»:

Классификация с COCO

Наша функция classify выглядит в основном так же, как и с Inception, но на этот раз на входе будет 300x300 изображений, а на выходе будет матрица 1x1xNx7.

Я не совсем уверен, почему на выходе получается матрица 1x1xNx7, но на самом деле нас интересует только часть Nx7. Чтобы отобразить 3-е и 4-е измерения в 2D-матрицу, мы можем использовать утилиту flattenFloat. Сравнивая это с выходной матрицей Inception, на этот раз N соответствует не каждому классу, а каждому обнаруженному объекту. Кроме того, теперь у нас есть 7 записей для каждого объекта.

Почему 7 записей?

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

0. На самом деле я понятия не имею.
1. метку класса объекта
2. уверенность < br /> 3. крайний левый x прямоугольника
4. нижний y прямоугольника
5. крайний правый x прямоугольника
6. вверху y прямоугольника

Выходная матрица дает нам довольно неплохую информацию о результате. Мы можем снова отфильтровать результат по достоверности и нарисовать прямоугольники на изображении для каждого распознанного объекта.

Давайте посмотрим на это в действии!

Для простоты я пропущу код для рисования прямоугольников и все остальные элементы для визуализации. Если вы хотите знать, как это сделать, вы можете посмотреть пример кода.

Давайте загрузим изображение с автомобилями в сеть и отфильтруем результат для обнаружения с помощью className ‘car’:

Отлично! А теперь кое-что посложнее. Давай попробуем эээ ... стол для завтрака?

Итак, мы идем!

Несколько заключительных слов

Вот как вы можете использовать OpenCV и Node.js для распознавания объектов на изображениях с помощью нейронных сетей. Если вы хотите поиграть с этим, я бы порекомендовал проверить Зоопарк моделей кафе, который предлагает набор обученных моделей для различных сценариев использования, которые вы можете просто загрузить.

Если вы сделали что-то потрясающее с DNN в OpenCV, я хотел бы знать об этом! Не стесняйтесь, чтобы оставить комментарий ниже.

Если вам понравилась эта статья, не стесняйтесь аплодировать и комментировать. Я также был бы весьма признателен за поддержку проекта opencv4nodejs , оставив звездочку на github. Кроме того, не стесняйтесь вносить свой вклад или связываться, если вам интересно :).

Opencv4nodejs - это пакет npm, который обеспечивает привязку Node.js к OpenCV и OpenCV-contrib через асинхронный API. Пакет обеспечивает все преимущества производительности собственной библиотеки OpenCV для вашего приложения Node.js и позволяет легко реализовывать многопоточные задачи CV с помощью Promises.