Найти в Дзене
Жонглер данными

Обнаружение объектов на изображении с помощью компьютерного зрения

Для многих людей обнаружение объектов на изображении кажется каким-то колдовством, однако существует огромное количество способов распознать на изображении определенные объекты. Одно только перечисление займет всю статью, а уж их сравнение вполне тянет на серьезное исследование. Для начала поставим задачу. Нужно посчитать количество людей, имеющихся на изображении. Делать это будем в бесплатном colab. Считать людей будем на публичном наборе изображений с людьми: https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip. Известные мне системы обнаружения объектов используют фреймворк Pytorch, поэтому право первой "брачной ночи" очереди за предобученными моделями этого фреймворка. Объявляем необходимые библиотеки. Объяснение функций torchvision будет непосредственно в коде: Загрузим датасет и распакуем его. Из всего датасета нам нужно только папка PennFudanPed/PNGImages: Получим веса нашей модели (третья объявленная функция) и саму модель (вторая объявленная функция), в модель передадим

Для многих людей обнаружение объектов на изображении кажется каким-то колдовством, однако существует огромное количество способов распознать на изображении определенные объекты. Одно только перечисление займет всю статью, а уж их сравнение вполне тянет на серьезное исследование.

Для начала поставим задачу. Нужно посчитать количество людей, имеющихся на изображении. Делать это будем в бесплатном colab. Считать людей будем на публичном наборе изображений с людьми: https://www.cis.upenn.edu/~jshi/ped_html/PennFudanPed.zip.

Известные мне системы обнаружения объектов используют фреймворк Pytorch, поэтому право первой "брачной ночи" очереди за предобученными моделями этого фреймворка.

Объявляем необходимые библиотеки. Объяснение функций torchvision будет непосредственно в коде:

Нужные нам библиотеки
Нужные нам библиотеки

Загрузим датасет и распакуем его. Из всего датасета нам нужно только папка PennFudanPed/PNGImages:

Получаем изображения с людьми
Получаем изображения с людьми

Получим веса нашей модели (третья объявленная функция) и саму модель (вторая объявленная функция), в модель передадим веса и нижний уровень точности определения объекта:

Получаем модель
Получаем модель

Инициализируем модель с помощью функции eval:

Инициализация модели
Инициализация модели

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

Функция конвертации входных данных
Функция конвертации входных данных

Первой объявленной функцией была read_image, которая загружает изображение из файла, и конвертирует его в тензор (что-то похожее на массив в numpy). Вот как она работает:

Тензор из графического файла
Тензор из графического файла

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

"Кусок, который умещается в рот"
"Кусок, который умещается в рот"

Теперь подготовленные данные передаем в модель и получаем предсказание (нас интересует только первая часть предсказания):

Предсказание модели
Предсказание модели

Нам нужны метки классов и рамки объектов, причем метки должны иметь значение 1 (person), остальные классы должны быть пропущены:

Полученные метки классов, маска по классу 1 и рамки полученных объектов
Полученные метки классов, маска по классу 1 и рамки полученных объектов

Чтобы получить рамки только людей мы используем маску, а чтобы нарисовать эти рамки мы объявили функцию draw_bounding_boxes (4 сверху). Рамки будут красными, шириной два пикселя. Но результат мы получим в виде тензора, который конвертируем в PIL-формат с помощью функции to_pil_image (5):

Получение изображения с рамками
Получение изображения с рамками

Выведем изображение с помощью функции imshow библиотеки matplotlib (последнее объявление):

Вывод изображения в блокноте
Вывод изображения в блокноте

На первом изображении модель обнаружила два человека:

FudanPed00001
FudanPed00001

На втором только одного, хотя глазами мы видим двух дюдей:

FudanPed00002
FudanPed00002

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

FudanPed00003
FudanPed00003

Для подсчета обнаруженных людей нам достаточно выполнить:

Количество меток с классом 1
Количество меток с классом 1

Задача нами решена, правда есть некоторые "шероховатости", но в целом предобученная модель вполне себе справляется с обнаружение людей, если они не перекрыты друг другом.