Как использовать Google Colaboratory для обработки видео
Знаете ли вы, что набор компьютерных алгоритмов может обрабатывать видеопоток таким образом, чтобы они могли обнаруживать преступную деятельность, контролировать пробки и даже автоматически обнаруживать события в спортивных трансляциях? Благодаря применению машинного обучения (ML) идея получения такого большого количества данных из простого видео не кажется такой уж нереальной. В этой статье мы обсудим применение готовой логики алгоритма машинного обучения для обнаружения и сегментации объектов к видео.
В частности, мы поговорим о том, как настроить Google Colaboratory для решения задач обработки видео с помощью машинного обучения. Вы узнаете, как использовать этот сервис Google и бесплатный графический процессор NVIDIA Tesla K80, который он предоставляет для достижения ваших собственных целей в обучении нейронных сетей. Эта статья будет полезна людям, которые знакомятся с машинным обучением и рассматривают возможность работы с распознаванием изображений и обработкой видео.
Обработка изображений с ограниченными аппаратными ресурсами
Задача - распознавать людей на видеозаписи с помощью алгоритмов машинного обучения (ML). Мы решили начать с основ. Во-первых, давайте рассмотрим, что на самом деле представляет собой видеозапись.
С технической точки зрения любая видеозапись состоит из серии неподвижных изображений в определенном формате, сжатых с помощью видеокодека. Следовательно, распознавание объектов в видеопотоке сводится к разделению потока на отдельные изображения или кадры и применению к ним предварительно обученного алгоритма распознавания изображений ML.
Для этого мы решили использовать нейронную сеть из репозитория Mask_R-CNN для классификации одиночных изображений. Репозиторий содержит реализацию сверточной нейронной сети на Python3, TensorFlow и Keras. Посмотрим, что получилось из этого плана.
Образец Mask_RCNN
Мы разработали и реализовали простой образец Mask_RCNN, который получает изображение на входе и распознает в нем объекты. Мы создали образец на основе описания demo.ipynb взято из репозитория Mask_R-CNN. Вот код нашего образца:
import os, sys random import import math import numpy as np import skimage.io import matplotlib import matplotlib.pyplot as plt os.chdir( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) sys.path.append( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) # Root directory of the project ROOT_DIR = os.path.abspath( "." ) # Import Mask RCNN sys.path.append(ROOT_DIR) # To find local version of the library from mrcnn import utils import mrcnn.model as modellib from mrcnn import visualize # Import COCO config sys.path.append(os.path.join(ROOT_DIR, "samples/coco/" )) # To find local version import coco # Directory to save logs and trained model MODEL_DIR = os.path.join(ROOT_DIR, "logs" ) # Local path to trained weights file COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5" ) # Download COCO trained weights from Releases if needed if not os.path.exists(COCO_MODEL_PATH): utils.download_trained_weights(COCO_MODEL_PATH) # Directory of images to run detection on IMAGE_DIR = os.path.join(ROOT_DIR, "images" ) class InferenceConfig(coco.CocoConfig): # Set batch size to 1 since we'll be running inference on # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU GPU_COUNT = 1 IMAGES_PER_GPU = 1 config = InferenceConfig() config.display() # Create model object in inference mode. model = modellib.MaskRCNN(mode = "inference" , model_dir = MODEL_DIR, config = config) # Load weights trained on MS-COCO model.load_weights(COCO_MODEL_PATH, by_name = True ) # COCO Class names # Index of the class in the list is its ID. For example, to get ID of # the teddy bear class, use: class_names.index('teddy bear') class_names = [ 'BG' , 'person' , 'bicycle' , 'car' , 'motorcycle' , 'airplane' , 'bus' , 'train' , 'truck' , 'boat' , 'traffic light' , 'fire hydrant' , 'stop sign' , 'parking meter' , 'bench' , 'bird' , 'cat' , 'dog' , 'horse' , 'sheep' , 'cow' , 'elephant' , 'bear' , 'zebra' , 'giraffe' , 'backpack' , 'umbrella' , 'handbag' , 'tie' , 'suitcase' , 'frisbee' , 'skis' , 'snowboard' , 'sports ball' , 'kite' , 'baseball bat' , 'baseball glove' , 'skateboard' , 'surfboard' , 'tennis racket' , 'bottle' , 'wine glass' , 'cup' , 'fork' , 'knife' , 'spoon' , 'bowl' , 'banana' , 'apple' , 'sandwich' , 'orange' , 'broccoli' , 'carrot' , 'hot dog' , 'pizza' , 'donut' , 'cake' , 'chair' , 'couch' , 'potted plant' , 'bed' , 'dining table' , 'toilet' , 'tv' , 'laptop' , 'mouse' , 'remote' , 'keyboard' , 'cell phone' , 'microwave' , 'oven' , 'toaster' , 'sink' , 'refrigerator' , 'book' , 'clock' , 'vase' , 'scissors' , 'teddy bear' , 'hair drier' , 'toothbrush' ] # Load a random image from the images folder file_names = next (os.walk(IMAGE_DIR))[ 2 ] image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names))) # Run detection results = model.detect([image], verbose = 1 ) # Visualize results r = results[ 0 ] visualize.display_instances(image, r[ 'rois' ], r[ 'masks' ], r[ 'class_ids' ],class_names, r[ 'scores' ]) |
В этом примере / content / drive / My Drive / Colab Notebooks / MRCNN_pure - это путь к нашему репозиторию с Mask_R-CNN. В результате мы получили следующее:
Эта часть демонстрационного кода просматривает папку изображений, случайным образом выбирает изображение и загружает его в нашу модель нейронной сети для классификации:
# Load a random image from the images folder file_names = next (os.walk(IMAGE_DIR))[ 2 ] image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names))) # Run detection results = model.detect([image], verbose = 1 ) |
Давайте изменим образец Mask_R-CNN, чтобы он распознавал все изображения в папке изображений:
# Load a random image from the images folder file_names = next (os.walk(IMAGE_DIR))[ 2 ] for file_name in file_names: image = skimage.io.imread(os.path.join(IMAGE_DIR, file_name)) # Run detection results = model.detect([image], verbose = 1 ) # Visualize results r = results[ 0 ] visualize.display_instances(image, r[ 'rois' ], r[ 'masks' ], r[ 'class_ids' ],class_names, r[ 'scores' ]) |
После запуска демонстрационного кода в течение пяти минут консоль отобразила следующий вывод:
…
Processing 1 images
image shape: (415, 640, 3) min: 0.00000 max: 255.00000 uint8
molded_images shape: (1, 1024, 1024, 3) min: -123.70000 max: 151.10000 float64
image_metas shape: (1, 93) min: 0.00000 max: 1024.00000 float64
anchors shape: (1, 261888, 4) min: -0.35390 max: 1.29134 float32
Segmentation fault (core dumped)
Первоначально мы запускали демонстрационный код на компьютере с Intel Core i5 и 8 ГБ ОЗУ без дискретной видеокарты. Код падал каждый раз в разных местах, но чаще всего он падал в фреймворке TensorFlow во время выделения памяти. Более того, любые попытки запустить какое-либо другое программное обеспечение во время процесса распознавания изображений замедляли работу компьютера до такой степени, что становились бесполезными.
Таким образом, мы столкнулись с серьезной проблемой: любые эксперименты по знакомству с ML требовали мощной видеокарты и большего количества аппаратных ресурсов. Без этого мы не могли бы запускать другие задачи при распознавании большого количества изображений.
Расширение наших аппаратных ресурсов с помощью Google Colaboratory
Мы решили расширить наши аппаратные ресурсы с помощью службы Colaboratory от Google, также известной как Colab. Google Colab - это бесплатная облачная служба, которая обеспечивает использование ЦП и ГП, а также предварительно настроенного экземпляра виртуальной машины. В частности, Google предлагает графический процессор NVIDIA Tesla K80 с 12 ГБ выделенной видеопамяти, что делает Colab идеальным инструментом для экспериментов с нейронными сетями.
Прежде чем объяснять, как работать с этой службой Google, мы хотели бы выделить другие полезные функции Colaboratory.
Выбрав Colab для своих экспериментов с машинным обучением, вы получите:
- поддержка Python 2.7 и Python 3.6, чтобы вы могли улучшить свои навыки программирования;
- возможность работать с блокнотом Jupyter, чтобы вы могли создавать, редактировать и публиковать свои файлы .ipynb;
- возможность подключиться к среде выполнения Jupyter с вашего локального компьютера;
- множество предустановленных библиотек, включая TensorFlow, Keras и OpenCV, а также возможность взаимодействия с вашими пользовательскими библиотеками в Google Colaboratory;
- возможность загрузки, чтобы вы могли добавить свою обученную модель;
- интеграция с GitHub, чтобы вы могли загружать общедоступные записные книжки GitHub или сохранять копию файла Colab на GitHub;
- простая визуализация с помощью таких популярных библиотек, как matplotlib;
- формы, которые можно использовать для параметризации кода;
- возможность хранить записные книжки Google Colab на вашем Google Диске.
Чтобы начать использовать графический процессор Google Colab, вам просто нужно предоставить доступ к вашему скрипту .ipynb, который реализован в контейнере Docker. Контейнер Docker закреплен за вами только на 12 часов. Все созданные вами скрипты по умолчанию хранятся на вашем Google Диске в разделе Colab Notebooks, который создается автоматически при подключении к Colaboratory. По истечении 12 часов все ваши данные в контейнере будут удалены. Вы можете избежать этого, установив свой Google Диск в свой контейнер и работая с ним. В противном случае файловая система образа Docker будет доступна только в течение ограниченного периода времени.
Настройка Google Colab
Давайте сначала объясним, как создать записную книжку .ipynb. Откройте здесь Google Colaboratory, выберите раздел Google Drive и нажмите НОВЫЙ НОУТБУК PYTHON 3:
Переименуйте записную книжку, как хотите, щелкнув имя файла. Теперь вам нужно выбрать свое оборудование. Для этого просто перейдите в раздел «Редактировать», найдите «Настройки ноутбука», выберите «GPU» в качестве аппаратного ускорителя и сохраните изменения, нажав «СОХРАНИТЬ».
После сохранения новых настроек вам станет доступен контейнер Docker с дискретной видеокартой. Вы будете уведомлены об этом сообщением «Подключено» в правом верхнем углу страницы:
Если вы не видите это сообщение, выберите «Подключиться к размещенной среде выполнения».
Теперь вы можете подключить свой Google Диск к этому контейнеру, чтобы переместить исходный код и сохранить результаты своей работы в контейнере. Для этого просто скопируйте приведенный ниже код в первую ячейку таблицы и нажмите кнопку Play (или Shift + Enter).
Смонтируйте Google Диск, запустив этот код:
# from google.colab import drive drive.mount( '/content/drive' ) |
Вы получите запрос на авторизацию. Щелкните ссылку, авторизуйтесь, скопируйте код подтверждения, вставьте его в текстовое поле в своем скрипте .ipynb и нажмите Enter. Если авторизация прошла успешно, ваш Google Диск будет смонтирован по пути / content / drive / My Drive. Чтобы следить за деревом файлов, выберите «Файлы» в левом меню.
Теперь у вас есть контейнер Docker с графическим процессором Tesla K80, ваш Google Диск в качестве хранилища файлов и записная книжка .ipynb для выполнения скриптов.
Использование Google Colab для распознавания объектов
Теперь мы опишем, как запустить наш пример Mask_R-CNN для распознавания объектов в Google Colab. Мы загружаем репозиторий Mask_RCNN на наш Google Диск по пути / content / drive / My Drive / Colab Notebooks /.
Затем мы добавляем наш пример кода в скрипт .ipynb. Когда вы это сделаете, не забудьте изменить свой путь к папке Mask_RCNN следующим образом:
os.chdir( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) sys.path.append( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) |
Если вы все сделаете правильно, результаты выполнения кода предоставят вам изображение, на котором обнаружены и распознаны все объекты.
Вы также можете изменить пример кода, чтобы он обрабатывал все тестовые изображения:
import os, sys import random import math import numpy as np import skimage.io import matplotlib import matplotlib.pyplot as plt os.chdir( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) sys.path.append( "/content/drive/My Drive/Colab Notebooks/MRCNN_pure" ) # Root directory of the project ROOT_DIR = os.path.abspath( "." ) # Import Mask RCNN sys.path.append(ROOT_DIR) # To find local version of the library from mrcnn import utils import mrcnn.model as modellib from mrcnn import visualize # Import COCO config sys.path.append(os.path.join(ROOT_DIR, "samples/coco/" )) # To find local version import coco # Directory to save logs and trained model MODEL_DIR = os.path.join(ROOT_DIR, "logs" ) # Local path to trained weights file COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5" ) # Download COCO trained weights from Releases if needed if not os.path.exists(COCO_MODEL_PATH): utils.download_trained_weights(COCO_MODEL_PATH) # Directory of images to run detection on IMAGE_DIR = os.path.join(ROOT_DIR, "images" ) class InferenceConfig(coco.CocoConfig): # Set batch size to 1 since we'll be running inference on # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU GPU_COUNT = 1 IMAGES_PER_GPU = 1 config = InferenceConfig() config.display() # Create model object in inference mode. model = modellib.MaskRCNN(mode= "inference" , model_dir=MODEL_DIR, config=config) # Load weights trained on MS-COCO model.load_weights(COCO_MODEL_PATH, by_name=True) # COCO Class names # Index of the class in the list is its ID. For example, to get ID of # the teddy bear class, use: class_names.index('teddy bear') class_names = [ 'BG' , 'person' , 'bicycle' , 'car' , 'motorcycle' , 'airplane' , 'bus' , 'train' , 'truck' , 'boat' , 'traffic light' , 'fire hydrant' , 'stop sign' , 'parking meter' , 'bench' , 'bird' , 'cat' , 'dog' , 'horse' , 'sheep' , 'cow' , 'elephant' , 'bear' , 'zebra' , 'giraffe' , 'backpack' , 'umbrella' , 'handbag' , 'tie' , 'suitcase' , 'frisbee' , 'skis' , 'snowboard' , 'sports ball' , 'kite' , 'baseball bat' , 'baseball glove' , 'skateboard' , 'surfboard' , 'tennis racket' , 'bottle' , 'wine glass' , 'cup' , 'fork' , 'knife' , 'spoon' , 'bowl' , 'banana' , 'apple' , 'sandwich' , 'orange' , 'broccoli' , 'carrot' , 'hot dog' , 'pizza' , 'donut' , 'cake' , 'chair' , 'couch' , 'potted plant' , 'bed' , 'dining table' , 'toilet' , 'tv' , 'laptop' , 'mouse' , 'remote' , 'keyboard' , 'cell phone' , 'microwave' , 'oven' , 'toaster' , 'sink' , 'refrigerator' , 'book' , 'clock' , 'vase' , 'scissors' , 'teddy bear' , 'hair drier' , 'toothbrush' ] # Load a random image from the images folder file_names = next(os.walk(IMAGE_DIR))[2] for file_name in file_names: image = skimage.io.imread(os.path.join(IMAGE_DIR, file_name)) # Run detection results = model.detect([image], verbose=1) # Visualize results r = results[0] visualize.display_instances(image, r[ 'rois' ], r[ 'masks' ], r[ 'class_ids' ],class_names, r[ 'scores' ]) |
Используя обнаружение объектов в Google Colab, мы быстро получали результаты с распознанными объектами, в то время как наш компьютер продолжал работать, как обычно, даже во время процесса распознавания изображений.
Использование Google Colab для обработки видео
Посмотрим, как мы применили этот метод для распознавания людей в видеопотоке. Мы загрузили тестовый видеофайл на наш Google Диск. Чтобы обучить наш скрипт работе с видеопотоком, мы использовали OpenCV, популярную библиотеку компьютерного зрения с открытым исходным кодом.
Нам не нужен весь код, который считывает и реализует модель распознавания на одном изображении. Поэтому вместо того, чтобы открывать видеофайл, мы запускаем видеопоток и перемещаем его указатель на 1000-й кадр, поскольку во вступлении к записи нет объектов для распознавания.
import cv2 ... VIDEO_STREAM = "/content/drive/My Drive/Colab Notebooks/Millery.avi" VIDEO_STREAM_OUT = "/content/drive/My Drive/Colab Notebooks/Result.avi" ... # initialize the video stream and pointer to output video file vs = cv2.VideoCapture(VIDEO_STREAM) writer = None vs.set(cv2.CAP_PROP_POS_FRAMES, 1000); |
Затем мы обрабатываем 20 000 кадров с помощью нашей модели нейронной сети. Объект OpenCV позволяет нам получать изображения по кадрам из видеофайла с помощью метода read (). Полученное изображение передается в метод model.detect (), а результаты визуализируются с помощью функции visualize.display_instances ().
Однако мы столкнулись с проблемой: функция display_instances () из репозитория Mask_RCNN отражает обнаруженные объекты на изображении, но изображение не возвращается. Мы решили упростить функцию display_instances () и заставить ее возвращать изображение с отображаемыми объектами:
def display_instances(image, boxes, masks, ids, names, scores): """ take the image and results and apply the mask, box, and Label """ n_instances = boxes.shape[ 0 ] colors = visualize.random_colors(n_instances) if not n_instances: print ( 'NO INSTANCES TO DISPLAY' ) else : assert boxes.shape[ 0 ] = = masks.shape[ - 1 ] = = ids.shape[ 0 ] for i, color in enumerate (colors): if not np. any (boxes[i]): continue y1, x1, y2, x2 = boxes[i] label = names[ids[i]] score = scores[i] , scores is not None else None if scores is not None else None caption = '{} {:.2f}' . format (label, score) if score else label mask = masks[:, :, i] image = visualize.apply_mask(image, mask, color) image = cv2.rectangle(image, (x1, y1), (x2, y2), color, 2 ) image = cv2.putText( image, caption, (x1, y1), cv2.FONT_HERSHEY_COMPLEX, 0.7 , color, 2 ) return image |
После обработки кадры должны быть снова связаны в новый видеофайл. Мы также можем сделать это с помощью библиотеки OpenCV. Все, что нам нужно сделать, это выделить объект VideoWriter из библиотеки OpenCV:
fourcc = cv2.VideoWriter_fourcc( * "XVID" ) writer = cv2.VideoWriter(VIDEO_STREAM_OUT, fourcc, 30 , (masked_frame.shape[ 1 ], masked_frame.shape[ 0 ]), True ) |
используя тип видео, который мы предоставили для ввода. Тип видеофайла получаем с помощью команды ffprobe :
ffprobe Result.avi
…
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0: Video: mpeg4 (Simple Profile) (XVID / 0x44495658), yuv420p, 640×272 [SAR 1:1 DAR 40:17], 30 fps, 30 tbr, 30 tbn, 30 tbc
Полученный объект можно использовать для покадровой записи: writer.write (masked_frame).
В начале скрипта нам нужно указать пути к целевым видеофайлам для обработки: VIDEO_STREAM и VIDEO_STREAM_OUT.
Вот полный сценарий, который мы разработали для распознавания видео:
from drive import РЕКОМЕНДУЕМЫЕ СТАТЬИ |