В этой статье я делюсь пошаговой методологией создания простого детектора объектов с использованием YOLO и веб-камеры вашего ноутбука для идентификации конкретного объекта.

Примечание. Базовые знания о модели YOLO помогут лучше понять эту статью. Кроме того, код написан на Python.

Что такое YOLO?

YOLO, аббревиатура от «You Only Look Once» (навеяно знаменитой цитатой «You Only Live Once»).

YOLO — это алгоритм обнаружения объектов, который использует сверточные нейронные сети (CNN) для обнаружения объектов в режиме реального времени. Как следует из названия, это одноэтапная модель обнаружения объектов, которая требует только одного прямого распространения через нейронную сеть для обнаружения объектов. Чтобы узнать больше о YOLO и его истории, я нашел эту статью от pyimagesearch весьма полезной, но вы можете обратиться ко многим другим полезным ресурсам, доступным в Интернете.

Исходные требования

Для этого проекта мы НЕ будем обучать модель с нуля, а вместо этого будем использовать предварительно обученную конфигурацию и веса YOLOv4. Для этого сначала необходимо загрузить следующие файлы:

  • Файл конфигурации: в этом файле хранится архитектура модели.
  • Файл весов: веса предварительно обученной модели. Они были обучены с использованием базы кода DarkNet на наборе данных MS COCO.
  • Файл классов: содержит названия 80 категорий объектов в наборе данных COCO.

Теперь мы завершаем первоначальную настройку, загружая модель YOLO с помощью функции OpenCV DNN cv2.dnn.readNetFromDarknet. Затем мы читаем файл классов coco.names, который содержит список из 80 различных классов объектов, на которых обучается модель YOLO, и сохраняем их в списке Python. Далее мы определяем объект, который необходимо обнаружить. В данном конкретном случае мы хотим обнаружить сотовый телефон с камеры.

Функция обнаружения объектов

Вот где происходит «волшебство». Далее мы определяем функцию обнаружения объекта. Эта функция берет кадр изображения с вашей камеры, а затем обнаруживает предполагаемый объект. Фрагмент кода с камерой будет объяснен позже. Но пока давайте просто предположим, что эта функция получает на вход одно изображение.

Во-первых, мы получаем высоту и ширину входного изображения. Затем нам нужно преобразовать изображение в блоб (который представляет собой объект массива 4D NumPy — изображения, каналы, ширину, высоту) с помощью функции cv2.dnn.blobFromImage. Это необходимо для подготовки входного изображения в требуемом формате для приема модели. Чтобы узнать больше о том, что такое блоб и как работает функция cv2.dnn.blobFromImage, обратитесь к этому блогу. Входные параметры этой функции зависят от используемой модели. Для YOLO используются следующие параметры:

the image to transform
the scale factor (1/255 to scale the pixel values to [0..1])
the size, here a 416x416 square image
the mean value (default=0)
the option swapBR=True (since OpenCV uses BGR)

Затем объект blob устанавливается в качестве входных данных для сети, и выполняется прямой проход через сеть YOLO после определения выходных слоев из модели YOLO.

Нам также необходимо визуализировать результаты после обнаружения объекта. Но сначала давайте инициализируем несколько списков для хранения необходимой информации:

  • boxes: Ограничивающие рамки вокруг объекта.
  • confidences: показатель достоверности, который модель YOLO присваивает объекту. Мы устанавливаем минимальную оценку вероятности 0.5 для фильтрации слабых обнаружений. Более низкие значения достоверности указывают на то, что объект может быть не таким, каким его считает сеть.
  • class_ids : Метка обнаруженного класса объектов.

Затем мы перебираем каждый из layeroutput, а затем зацикливаем каждый detection в output. Затем извлеките оценки достоверности для всех классов объектов из 5-го элемента в списке detection и выберите идентификатор класса объекта с максимальной оценкой достоверности. Если идентификатор обнаруженного класса равен идентификатору желаемого объекта (например, мобильного телефона в этом примере), а показатель достоверности больше порогового значения (чтобы отфильтровать слабые обнаружения), мы пытаемся визуализировать желаемый обнаруженный объект, рисуя ограничивающий объект. поле и добавив метку этого объекта.

Модель YOLO возвращает координаты центра (x, y) ограничивающей рамки, за которыми следуют ширина и высота рамки. Но прежде чем мы сможем их использовать, нам нужно сначала масштабировать эти значения относительно размера изображения. После масштабирования мы используем координаты центра, ширину и высоту ограничительной рамки для получения верхних левых координат ограничительной рамки. Затем обновите списки boxes, confidences и class_ids.

YOLO не применяет немаксимальное подавление по умолчанию, поэтому нам нужно явно применить его с помощью функции cv2.dnn.NMSBoxes. Эта функция просто подавляет значительно перекрывающиеся ограничивающие рамки, оставляя только достоверные и исключая любые избыточные рамки. Входными параметрами являются поля, достоверность, порог достоверности (т. е. 0.5) и порог NMS.

Предполагая, что предполагаемый объект (например, сотовый телефон в этом примере) был обнаружен, мы перебираем indexes, определяемый немаксимальным подавлением, чтобы нарисовать ограничивающую рамку и текст на изображении, используя случайные цвета класса. Затем, наконец, мы отображаем наше полученное изображение.

Захват видео с камеры и определение предполагаемого объекта

Поскольку целью этого проекта является идентификация конкретного объекта с камеры, нам сначала нужно захватить живые потоки с помощью камеры (веб-камеры). Для этого нам нужно создать объект класса VideoCapture из библиотеки OpenCV. В качестве входных данных класс VideoCapture получает индекс устройства, которое мы хотим использовать. Если у нас есть одна камера, подключенная к компьютеру, мы можем передать значение 0.

После этого внутри цикла while мы можем начать покадровое чтение видео с камеры. Мы используем метод read для объекта VideoCapture для чтения каждого кадра. Этот метод не принимает аргументов и возвращает кортеж. Первое возвращаемое значение — это логическое значение, указывающее, правильно ли был прочитан кадр (True) или нет (False), а второе — это кадр с камеры. Далее мы передаем каждый кадр нашей функции обнаружения объектов imgRead. Если предполагаемый объект (например, сотовый телефон в этом примере) появляется в кадре с камеры, то вокруг него будет ограничивающая рамка вместе с меткой объекта (что-то вроде изображения, показанного ниже). Метод cv2.imshow() отображает видео или изображение в окне.

Теперь, если мы хотим закрыть трансляцию с камеры, мы можем просто нажать клавишу q на клавиатуре.

Использованная литература:

  1. https://pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/
  2. https://opencv-tutorial.readthedocs.io/en/latest/yolo/yolo.html