Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python

Логотип компании IT Resume

Учимся представлять фотографии в виде матриц, обрабатывать их, детектить лица и натравливать на них нейронку.

Рассказывает команда IT Resume

Детекция (т.е. нахождение) и распознавание лиц — очень популярная задача в современном мире: в метро уже давно следят за нашими передвижениями, а в загородных домах все чаще ставят «умные дверные глазки».

Так уж сложилось, что сейчас уже нельзя просто написать программу для распознавания лиц и присвоить себе должность Senior Data Scientist — таких знаний требуют даже от начинающих специалистов.

Если Вы еще не игрались с распознаванием лиц, но хотите развиваться в области нейронных сетей (ну или просто Вам интересна эта область), то эксперты IT Resume подготовили для вас этот гайд — давайте вместе пройдем все шаги:

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

Для работы нам потребуется:

  1. Google Colab — среда для работы с Python в браузере. Они еще доступ к GPU дают (а для нейронных сетей это очень нужно).
  2. И все ?

Итак, начнем.

Этап 1. Подключение модулей

Перед тем, как начать работу, давайте сменим среду выполнения на «Ускорение GPU». В будущем нам это понадобится для работы нейронной сети. Для этого в Google Colab нажимаем «Среда выполнения» → «Сменить среду выполнения» → «Аппаратный ускоритель GPU».

Теперь подключим необходимые библиотеки. В Colab большинство библиотек уже установлено, поэтому нам осталось их только импортировать:

  • cv2 — для загрузки и обработки изображений;
  • dlib — для детекции лиц;
  • numpy — для работы с матрицами.

Помимо этого, с помощью команды pip install face_recognition мы устанавливаем библиотеку face_recognition — с ее помощью мы будем обрабатывать лицо нейронной сетью.

Примечание Вообще сделать полную обработку можно всего за несколько строчек кода, потому что в библиотеке face_recognition многие процессы (например, детекция лиц) уже завернуты в функции. Но мы намеренно некоторые вещи будем делать «с нуля», чтобы вы лучше во всем разобрались.

Этап 2. Первичная настройка

Теперь нам нужно произвести небольшую настройку, чтобы потом полноценно использовать все инструменты и кодовую базу.

Начнем с настройки детектора лиц. Сначала скачиваем файл с готовой моделью с помощью команды wget (да, именно этой командой Цукерберг запустил Фэйсбук в фильме Социальная сеть) и распаковываем файл в формат .dat.

			wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
bunzip2 shape_predictor_68_face_landmarks.dat.bz2
		

Далее создаем детектор лиц и передаем скачанную модель в shape_predictor, который будет предсказывать ключевые точки человеческого лица — контур головы, глаза, нос и рот.

			face_detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
		

Отлично, теперь мы готовы переходить к содержательной части — обработке фотографий.

Этап 3. Загрузка и обработка фотографий

Перед тем, как загружать фотографию в переменную Python, ее надо загрузить в файловое хранилище Google Colab. Для этого достаточно нажать на иконку Папки на левом сайдбаре и выбрать Upload.

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 1

Мы, например, загрузим фотографию Конора МакГрегора.

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 2

Отлично, теперь надо «прочитать» изображение в переменную Python. Это можно сделать несколькими способами, но нам удобнее представить изображение сразу в виде матрицы. Это можно сделать с помощью функции imread из модуля cv2.

Если вы загружаете цветную картинку, то «матрица» будет иметь размерность 3*height*width, где 3 — количество цветовых каналов (RGB), а width и height — размерность картинки в пикселях. Проверить это можно с помощью метода shape. Каждое число в матрице — значение пикселя по конкретному цветовому каналу.

			img = cv2.imread('conor.jpg')
img.shape #проверяем размерность матрицы
#(434, 770, 3)
		

Кстати говоря, если вы хотите посмотреть на загруженную картинку, то вам нужно:

  1. Импортировать команду cv2_imshow: from google.colab.patches import cv2_imshow.
  2. Передать в функцию cv2_imshow нужную картинку: cv2_imshow(img).
Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 3

В некоторых задачах имеет смысл обрабатывать не цветное изображение, а черно-белое. Например, на детекцию лиц наличие цвета мало влияет — контуры лица и так хорошо видны. А вот для нейронной сети это может быть принципиальный момент — мало ли, люди выглядят одинаково, а цвет кожи разный.

Поэтому давайте переведем нашу цветную картинку в черно-белую:

			img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
		
Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 4

Теперь переходим к следующему этапу — детекция лица.

Этап 4. Детекция лица

Детектор лиц у нас уже настроен, поэтому можем переходить непосредственно к детекции. Делать это будем в 2 этапа:

  1. Ищем прямоугольники, в которых находятся лица.
  2. По этим прямоугольникам предсказываем контуры и ключевые точки лица.

С помощью detector мы получим координаты нужного прямоугольника. Если лиц несколько, то и наборов точек будет несколько. Чтобы выбрать конкретное лицо, нужно указать индекс (в нашем случае — ноль).

			face_rect = detector(img, 1)[0]
		

Чтобы посмотреть на результат, можно нарисовать рамку вокруг лица с помощью метода rectangle и посмотреть фото с помощью cv2_imshow. Только будьте осторожны — рамка останется на фото навсегда, так что лучше потом загрузить изображение заново.

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 5

Теперь по найденным квадратам нужно «предсказать» ключевые точки лица. Для этого используем predictor, а потом извлекаем координаты точек.

			points = predictor(img, face_rect)
landmarks = np.array([*map(lambda p: [p.x, p.y], points.parts())])
		
Здесь, чтобы получить координаты точек, мы использовали сразу несколько полезных — операций Python:
— лямбда-функции;
— функцию map;
— распаковку.
Если вы планируете связать свою работу с Python, то обязательно освойте все эти приемы — они сильно упростят вам жизнь.

На выходе у нас получилось 68 точек. Не будем сильно в этом гайде заморачиваться с тем, как нанести это на фото, но получится что-то в таком духе:

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 6

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

Этап 5. Обработка нейронной сетью

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

Итак, получить итоговый вектор очень просто — достаточно вызвать функцию face_encodings.

			vector = face_recognition.face_encodings(img)[0]
		

Примечание Обратите внимание, что в качестве аргументов мы передали только изображение, а полученные ранее ключевые точки мы не использовали. Причина очень проста — функция face_encodings делает все те же самые действия, которые мы с вами проделали вручную ранее для понимания процесса «изнутри».

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

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

Этап 6. Сравнение векторов

Чтобы сравнивать лица между собой, мы будем действовать следующим образом:

  1. Загружаем новое фото и производим обработку, которую уже разобрали на предыдущих этапах. На выходе получаем вектор.
  2. Сравниваем вектора между собой.
  3. На основании расстояния принимаем решение — один и тот же человек на фото или разные.

Встает вопрос — что значит «сравнить вектора»? Самый простой способ — посчитать расстояние в некоторой метрике. Мы выберем обычную евклидову метрику. Вычислять ее без лишнего кода нам позволит функция pdist из scipy.spatial.distance.

Итак, сначала загрузим еще одну фотографию Конора.

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 7

Сохраняем полученный вектор для первой фотографии в vector1, для второй — в vector2 и вычисляем расстояние:

			from scipy.spatial.distance import pdist

pdist([vector1, vector2], 'euclidean')
		

Получаем ответ — 0,48. Это достаточно близкое расстояние, из чего делаем вывод, что это один и тот же человек. Сеть справилась отлично!

Ну хорошо, еще пару экспериментов — давайте возьмем снова Конора, но усложним задачу — пусть он будет в очках.

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 8

Результат — 0,56. Снова в яблочко (разработчик библиотеки face_recognition рекомендует придерживаться порога 0,6 — если больше 0,6, то это другой человек).

Ну что ж, а может сеть просто всех определяет как Конора? Давайте подсунем ей другого бойца — Хабиба Нурмагомедова. Что наша сеть на это скажет?

Кейс: Хабиб vs МакГрегор или Распознавание лиц на Python 9

Снова проводим уже известную процедуру и ответ… — 0.72. По утвержденному ранее порогу, делаем вывод: Хабиб — не Конор. Сеть снова нас не подвела, и мы со спокойной душой можем переходить к более сложным проектам.

Эпилог

Мы с вами разобрали основной инструментарий, который вам понадобится для старта в области face recognition (да и в нейронных сетях, в целом). Однако это далеко не предел — мы затронули лишь верхушку айсберга, опустив очень много моментов как программных, так и математических.

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

  • Научитесь выстраивать процесс распознавания с нуля, без использования оберток (чем является библиотека face_recognition). Начните хотя бы с изучения исходников этой библиотеки на GitHub — там ничего сверхсложного нет.
  • Попробуйте разные нейронные сети. Погуглите state-of-the-art решения и посмотрите — чем будет различаться результат.
  • Изучите структуру нейронных сетей (например, сверточных) с математической точки зрения. Это можно сделать с помощью многочисленных туториалов и официальной документации библиотек (например, PyTorch).

Есть много и других точек роста, но начните с этих — остальные мысли придут в процессе ?

Желаем удачи и будем рады помочь в комментариях!

P.S. Наш ноутбук с кодом в Google Colab Вы можете найти здесь.

Python
Компьютерное зрение
Машинное обучение
Нейронные сети
12637