Это 9-й день моего участия в ноябрьском испытании обновлений, подробности о событии:Вызов последнего обновления 2021 г.
В этом руководстве вы узнаете, как выполнять распознавание лиц с помощью OpenCV, Python и Deep Learning.
Сначала мы кратко обсудим, как работает распознавание лиц на основе глубокого обучения, включая концепцию «глубокого метрического обучения». Оттуда я помогу вам установить библиотеки, необходимые для фактического распознавания лиц. Наконец, мы реализуем распознавание лиц для неподвижных изображений и видеопотоков.
Понимание встраивания глубокого обучения распознаванию лиц
Итак, как работает глубокое обучение + распознавание лиц?
Секрет заключается в технике, называемой глубоким метрическим обучением. Если у вас есть предыдущий опыт глубокого обучения, вы знаете, что мы обычно обучаем сеть: брать одно входное изображение и выводить классификацию/метку для этого изображения. Однако глубокое метрическое обучение отличается.
Вместо того, чтобы пытаться вывести отдельные метки (или даже координаты/граничные рамки объектов на изображении), мы выводим векторы признаков с действительными значениями.
Для сети распознавания лиц dlib выходным вектором признаков является 128-d (то есть список из 128 реальных значений), используемый для количественной оценки лиц. Обучение сети выполняется с помощью троек:
Здесь мы предоставляем сети три изображения: Два изображения являются примерами лиц одного и того же человека. Третье изображение — это случайное лицо в нашем наборе данных, а не тот же человек, что и на двух других изображениях.
В качестве примера давайте снова рассмотрим рисунок 1, где мы предоставляем три изображения: одно с Чадом Смитом и два с Уиллом Ферреллом. Наша сеть квантует лица, строя 128-мерное вложение (квантование) для каждого человека.
Исходя из этого, общая идея состоит в том, что мы настроим веса нашей нейронной сети так, чтобы два 128-мерных измерения Уилла Феррела были ближе друг к другу и дальше друг от друга, чем измерения Чада Смита.
Наша сетевая архитектура для распознавания лиц основана на ResNet-34 из статьи He et al. Deep Residual Learning for Image Recognition, но с меньшим количеством слоев и уменьшенным вдвое количеством фильтров.
Сама сеть была обучена Дэвисом Кингом на наборе данных из ≈3 миллионов изображений. В наборе данных Labeled Faces in the Wild (LFW) сеть достигает точности 99,38% по сравнению с другими современными методами. Дэвис Кинг (создатель dlib) и Адам Гейтги (автор модуля face_recognition, который мы скоро будем использовать) написали подробные статьи о том, как работает распознавание лиц на основе глубокого обучения:
- Высококачественное распознавание лиц с использованием глубокого метрического обучения (Дэвис)dlib C++ Library: High Quality Face Recognition with Deep Metric Learning
- Глубокое обучение для современного распознавания лиц (Адам)medium.com/@ah дайте мне немного масла/нет…
Я настоятельно рекомендую прочитать приведенную выше статью для получения более подробной информации о том, как работают встраивания лиц с помощью глубокого обучения.
Установите библиотеку распознавания лиц
Чтобы выполнить распознавание лиц с помощью Python и OpenCV, нам нужно установить две дополнительные библиотеки:
Библиотека dlib, поддерживаемая Дэвисом Кингом, содержит нашу реализацию «глубокого метрического обучения» для создания вложений лиц для фактического процесса распознавания.
Библиотека face_recognition, созданная Адамом Гейтгеем, объединяет возможности dlib по распознаванию лиц, чтобы упростить ее использование.
установить dlib
pip install dlib
Или вы можете скомпилировать из исходников:
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build
cd build
cmake .. -DUSE_AVX_INSTRUCTIONS=1
cmake --build .
cd ..
python setup.py install --yes USE_AVX_INSTRUCTIONS
Если установка не удалась, попробуйте:
pip install dlib-bin
Эффект тот же, но таким образом можно установить только версию CPU, а недостаток в том, что она медленная.
Установите dlib с поддержкой графического процессора (необязательно)
Если у вас есть CUDA-совместимый графический процессор, вы можете установить dlib с поддержкой графического процессора, чтобы сделать распознавание лиц более быстрым и эффективным. Для этого я рекомендую установить dlib из исходников, так как у вас больше контроля над сборкой:
$ git clone https://github.com/davisking/dlib.git
$ cd dlib
$ mkdir build
$ cd build
$ cmake .. -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1
$ cmake --build .
$ cd ..
$ python setup.py install --yes USE_AVX_INSTRUCTIONS --yes DLIB_USE_CUDA
Рекомендуется использовать версию для графического процессора.Если установка не удалась, обратитесь к этой статье:
Установите пакет face_recognition
Модуль face_recognition можно установить с помощью простой команды pip:
pip install face_recognition
установить imutils
Вам также понадобится мой удобный пакет imutils. Вы можете установить его в виртуальной среде Python через pip:
pip install imutils
набор данных распознавания лиц
Поскольку «Парк Юрского периода» (1993) — мой любимый фильм всех времен, в честь «Мира Юрского периода: Павшее королевство» (2018), который выходит в кинотеатрах США в эту пятницу, мы собираемся выполнить распознавание лиц на образце персонажей из фильм: Алан Грант, палеонтолог (22 фото) Клэр Диринг, управляющая парком (53 фото) Элли Сэттлер, палеоботаник (31 фото) Ян Малкольм, математик (41 фото) Джон Хаммонд, торговец/владелец Парка Юрского периода (36 фото) Оуэн Грейди, исследователь динозавров (35 фото)
Учитывая этот набор данных изображения, мы будем:
- Создайте 128-мерное вложение для каждого лица в наборе данных.
- Используйте эти вложения для идентификации лиц людей на изображениях и в видеопотоках.
Как сделать набор данных:
- Загрузите фильм «Парк Юрского периода», создайте новую папку и скопируйте в нее фильм.
- Преобразование видео в изображение с помощью ffmpeg. Если вы не знаете, как использовать ffmeg, обратитесь к:Ван Хао.blog.CSDN.net/article/decent…
- Выберите подходящее изображение и поместите его в соответствующую папку.
Структура проекта распознавания лиц
myface
├── dataset
│ ├── alan_grant [22 entries]
│ ├── claire_dearing [53 entries]
│ ├── ellie_sattler [31 entries]
│ ├── ian_malcolm [41 entries]
│ ├── john_hammond [36 entries]
│ └── owen_grady [35 entries]
├── examples
│ ├── example_01.png
│ ├── example_02.png
│ └── example_03.png
├── output
│ └── lunch_scene_output.avi
├── videos
│ └── lunch_scene.mp4
├── encode_faces.py
├── recognize_faces_image.py
├── recognize_faces_video.py
├── recognize_faces_video_file.py
└── encodings.pickle
В нашем проекте есть 4 каталога верхнего уровня:
- dataset/ : Содержит изображения лиц из шести символов, организованные в подкаталоги в соответствии с их соответствующими именами.
- examples/ : содержит три изображения лица для тестирования, которых нет в наборе данных.
- output/ : Здесь вы можете хранить обработанные видео с распознаванием лиц. Я оставляю в папке одну из своих — классическую «сцену обеда» из оригинального фильма «Парк Юрского периода».
- video/ : входные видео должны храниться в этой папке. Эта папка также содержит видео «сцена обеда», но оно еще не прошло через нашу систему распознавания лиц.
У нас есть еще 6 файлов в корневом каталоге:
- encode_faces.py : с помощью этого скрипта создается кодировка лиц (128-мерный вектор).
- identity_faces_image.py : идентифицируйте лица на одном изображении (на основе кодировок в наборе данных).
- identity_faces_video.py : идентифицируйте лица в живом видеопотоке с веб-камеры и выводите видео.
- identity_faces_video_file.py : определить лица в видеофайле, находящемся на диске, и вывести обработанное видео на диск. Я не буду обсуждать этот файл сегодня, потому что кости взяты из того же скелета, что и файл видеопотока.
- encodings.pickle : кодировки распознавания лиц генерируются из вашего набора данных с помощью encode_faces.py, а затем сериализуются на диск.
После создания набора данных изображения (с помощью search_bing_api.py) мы запустим encode_faces.py для создания вложений. Затем мы запустим скрипт распознавания, чтобы на самом деле распознавать лица.
Кодирование человеческих лиц с помощью OpenCV и глубокого обучения
Прежде чем идентифицировать лица на изображениях и видео, нам сначала нужно количественно определить лица в обучающем наборе. Помните, что мы на самом деле не обучаем сеть здесь — сеть была обучена создавать 128-мерные вложения в наборе данных примерно из 3 миллионов изображений.
Конечно, мы могли бы обучить сеть с нуля и даже точно настроить веса существующих моделей, но для многих проектов это, вероятно, будет излишним.
Также вам понадобится много изображений для обучения сети с нуля. Вместо этого проще использовать предварительно обученную сеть, а затем использовать ее для построения 128-мерного встраивания для каждой из 218 граней в нашем наборе данных.
Затем в процессе классификации мы можем использовать простую модель k-NN + голосование для окончательной классификации лица. Здесь можно использовать и другие традиционные модели машинного обучения. Чтобы построить наше встраивание лица,
Пожалуйста, создайте новый encode_faces.py:
# import the necessary packages
from imutils import paths
import face_recognition
import argparse
import pickle
import cv2
import os
Во-первых, нам нужно импортировать необходимые пакеты. Еще раз обратите внимание, что этот скрипт требует установки imutils, face_recognition и OpenCV. Прокрутите вверх до «Установите библиотеки распознавания лиц», чтобы убедиться, что эти библиотеки готовы к использованию в вашей системе. Давайте обработаем аргументы командной строки, обрабатываемые во время выполнения, с помощью argparse:
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--dataset", required=True,
help="path to input directory of faces + images")
ap.add_argument("-e", "--encodings", required=True,
help="path to serialized db of facial encodings")
ap.add_argument("-d", "--detection-method", type=str, default="cnn",
help="face detection model to use: either `hog` or `cnn`")
args = vars(ap.parse_args())
Давайте перечислим флаги параметров и обсудим их:
- --dataset : путь к набору данных (мы создали его с помощью search_bing_api.py, описанного в методе № 2 статьи в блоге на прошлой неделе).
- --encodings: наши кодировки лиц записываются в файл, на который указывает этот параметр.
- --detection-method : прежде чем мы будем кодировать лица на изображении, нам сначала нужно их обнаружить. Или два метода обнаружения лиц, включая hog или cnn. Эти два флага единственные, которые применяются к --detection-method.
Теперь, когда мы определили наши параметры, давайте получим путь к файлу в наборе данных (а также выполним две инициализации):
# grab the paths to the input images in our dataset
print("[INFO] quantifying faces...")
imagePaths = list(paths.list_images(args["dataset"]))
# initialize the list of known encodings and known names
knownEncodings = []
knownNames = []
Введите путь к каталогу набора данных, чтобы создать список всех путей к изображениям, содержащимся в нем.
Нам также необходимо инициализировать два списка knownEncodings и knownNames соответственно перед циклом. Эти два списка будут содержать коды лиц и соответствующие имена каждого человека в наборе данных. Пришло время прокатиться на велосипеде по лицам наших персонажей из «Парка Юрского периода»!
# loop over the image paths
for (i, imagePath) in enumerate(imagePaths):
# extract the person name from the image path
print("[INFO] processing image {}/{}".format(i + 1,
len(imagePaths)))
name = imagePath.split(os.path.sep)[-2]
# load the input image and convert it from BGR (OpenCV ordering)
# to dlib ordering (RGB)
image = cv2.imread(imagePath)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
Этот цикл повторится 218 раз, что соответствует нашим 218 изображениям лиц в наборе данных.
Пройдите путь каждого изображения. Оттуда мы извлечем имя человека из imagePath (поскольку наш подкаталог назван соответствующим образом). Затем давайте загрузим изображение, передав imagePath в cv2.imread. OpenCV заказывает цветовые каналы в BGR, но dlib фактически ожидает RGB. Модуль face_recognition использует dlib, поэтому, прежде чем двигаться дальше, давайте поменяем местами цветовые пространства в строке 37, назвав новое изображение rgb. Затем давайте найдем лицо и вычислим кодировку:
# detect the (x, y)-coordinates of the bounding boxes
# corresponding to each face in the input image
boxes = face_recognition.face_locations(rgb,
model=args["detection_method"])
# compute the facial embedding for the face
encodings = face_recognition.face_encodings(rgb, boxes)
# loop over the encodings
for encoding in encodings:
# add each encoding + name to our set of known names and
# encodings
knownEncodings.append(encoding)
knownNames.append(name)
Это самая интересная часть сценария!
Для каждой итерации цикла мы будем обнаруживать лицо (или, возможно, несколько лиц) и предполагать, что это один и тот же человек в нескольких местах на изображении — предположение, которое может или не может быть выполнено в вашем собственном изображении, поэтому будьте осторожны) . Например, предположим, что rgb содержит одно (или несколько) изображение лица Элли Саттлер. Ее лицо было найдено/расположено, в результате чего был составлен список лицевых ящиков. В метод face_recognition.face_locations мы передаем два параметра:
-
rgb : Наше RGB-изображение.
-
модель: cnn или hog (значение содержится в словаре аргументов командной строки, связанном с ключом "detection_method"). Методы CNN более точны, но медленнее. HOG быстрее, но менее точен.
Затем мы преобразуем ограничивающую рамку лица Элли Саттлер в список из 128 чисел. Это называется кодированием лица в вектор, и метод face_recognition.face_encodings обрабатывает это за нас. Оттуда нам просто нужно добавить кодировку и имя Элли Саттлер в соответствующие списки (knownEncodings и knownNames). Мы продолжим делать это для всех 218 изображений в наборе данных. Какой смысл кодировать изображения, если мы не можем использовать кодирование в другом скрипте, который обрабатывает распознавание? Теперь исправим это:
# dump the facial encodings + names to disk
print("[INFO] serializing encodings...")
data = {"encodings": knownEncodings, "names": knownNames}
f = open(args["encodings"], "wb")
f.write(pickle.dumps(data))
f.close()
Словарь состоит из двух ключей — «кодировки» и «имена».
Скопируйте имя и кодировку на диск для дальнейшего использования. Как запустить скрипт encode_faces.py в терминале? Чтобы создать наше встраивание лица, откройте терминал и выполните следующие команды:
python encode_faces.py --dataset dataset --encodings encodings.pickle
[INFO] quantifying faces...
[INFO] processing image 1/218
[INFO] processing image 2/218
[INFO] processing image 3/218
...
[INFO] processing image 216/218
[INFO] processing image 217/218
[INFO] processing image 218/218
[INFO] serializing encodings...
$ ls -lh encodings*
-rw-r--r--@ 1 adrian staff 234K May 29 13:03 encodings.pickle
Как видно из нашего вывода, теперь у нас есть файл с именем encodings.pickle — этот файл содержит 128-мерные вложения лиц для каждого лица в нашем наборе данных.
На моем графическом процессоре Titan X обработка всего набора данных заняла чуть больше минуты, но если у вас есть процессор, будьте готовы дождаться завершения этого скрипта!
На моем Macbook Pro (без графического процессора) кодирование 218 изображений заняло 21 минуту и 20 секунд.
Если у вас есть графический процессор и скомпилированный dlib поддерживает его, вы должны ожидать более высоких скоростей.
Распознавать лица на изображениях
Теперь, когда мы создали 128-мерные встраивания лиц для каждого изображения в наборе данных, теперь мы можем использовать OpenCV, Python и глубокое обучение для идентификации лиц на изображениях. Откройте cognize_faces_image.py и вставьте следующий код:
# import the necessary packages
import face_recognition
import argparse
import pickle
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-e", "--encodings", required=True,
help="path to serialized db of facial encodings")
ap.add_argument("-i", "--image", required=True,
help="path to input image")
ap.add_argument("-d", "--detection-method", type=str, default="cnn",
help="face detection model to use: either `hog` or `cnn`")
args = vars(ap.parse_args())
Разберите три аргумента командной строки:
--encodings : путь к файлу рассола, содержащему наши кодировки лиц.
--image : это изображение, которое выполняет распознавание лиц.
--detection-method : вы уже должны быть знакомы с этим — в зависимости от возможностей вашей системы мы используем либо метод hog, либо метод cnn. Для скорости выберите hog , для точности выберите cnn .
Затем давайте загрузим предварительно вычисленную кодировку + имя лица и создадим 128-мерную кодировку лица для входного изображения:
# load the known faces and embeddings
print("[INFO] loading encodings...")
data = pickle.loads(open(args["encodings"], "rb").read())
# load the input image and convert it from BGR to RGB
image = cv2.imread(args["image"])
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# detect the (x, y)-coordinates of the bounding boxes corresponding
# to each face in the input image, then compute the facial embeddings
# for each face
print("[INFO] recognizing faces...")
boxes = face_recognition.face_locations(rgb,
model=args["detection_method"])
encodings = face_recognition.face_encodings(rgb, boxes)
# initialize the list of names for each face detected
names = []
Загрузите с диска нашу замаринованную кодировку и имена лиц. Эти данные понадобятся нам позже на этапе фактического распознавания лиц.
Затем мы загружаем входное изображение и преобразовываем его в порядок цветовых каналов rgb (как мы делали в сценарии encode_faces.py).
Затем мы приступаем к обнаружению всех лиц на входном изображении и вычислению их 128-мерных кодов (линии также должны выглядеть знакомыми).
Теперь самое время инициализировать список имен для каждого обнаруженного лица — этот список будет заполнен на следующем шаге.
Далее, давайте повторим кодировку лица:
# loop over the facial embeddings
for encoding in encodings:
# attempt to match each face in the input image to our known
# encodings
matches = face_recognition.compare_faces(data["encodings"],
encoding)
name = "Unknown"
Начнем с обхода кодировки лица, вычисленной на основе входного изображения. Затем происходит волшебство распознавания лиц! Мы пытаемся использовать face_recognition.compare_faces для сопоставления каждого лица во входном изображении (кодировке) с нашим известным набором данных кодирования (сохраненным в data["encodings"] ).
Эта функция возвращает список значений True/False, по одному для каждого изображения в наборе данных. В нашем примере с Парком Юрского периода в наборе данных 218 изображений, поэтому в возвращаемом списке будет 218 логических значений.
Внутри функция compare_faces вычисляет евклидово расстояние между вложениями-кандидатами и всеми лицами в нашем наборе данных:
- Если расстояние ниже определенного допуска (чем меньше допуск, тем жестче будет наша система распознавания лиц), то мы возвращаем True, указывая на совпадение лица.
- В противном случае, если расстояние выше порога допуска, мы вернем False, поскольку грани не совпадают.
По сути, мы используем «причудливую» модель k-NN для классификации. Обязательно обратитесь к реализации compare_faces для более подробной информации. Переменная имени в конечном итоге будет содержать строку имени человека — пока мы оставим ее как «Неизвестно» на случай, если «голоса» не будет.
Учитывая наш список совпадений, мы можем подсчитать количество «голосов» для каждого имени (количество истинных значений, связанных с каждым именем), подсчитать голоса и выбрать имя человека с наибольшим количеством голосов:
# check to see if we have found a match
if True in matches:
# find the indexes of all matched faces then initialize a
# dictionary to count the total number of times each face
# was matched
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
# loop over the matched indexes and maintain a count for
# each recognized face face
for i in matchedIdxs:
name = data["names"][i]
counts[name] = counts.get(name, 0) + 1
# determine the recognized face with the largest number of
# votes (note: in the event of an unlikely tie Python will
# select first entry in the dictionary)
name = max(counts, key=counts.get)
# update the list of names
names.append(name)
Если в матче есть какие-либо истинные голоса, нам нужно определить индекс того, где эти истинные значения находятся в матче. Именно это мы и сделали, составив простой список совпадающих идентификаторов, который может выглядеть так для примера example_01.png:
(Pdb) matchedIdxs
[35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75]
Затем мы инициализируем словарь counts, в котором имена персонажей будут ключами, а количество голосов — значениями. Оттуда давайте пройдемся по соответствующим идентификаторам Idx и установим значение, связанное с каждым именем, увеличивая его в счетчиках по мере необходимости. Для большого количества голосов Яна Малкольма словарь counts может выглядеть так:
(Pdb) counts
{'ian_malcolm': 40}
Напомним, что у нас в наборе данных только 41 фотография Яна, поэтому без голосования за кого-либо еще 40 баллов — это очень много. Извлеките имя с наибольшим количеством голосов из counts , в данном случае 'ian_malcolm' . Второй цикл основного цикла кодирования лица (поскольку у нас есть два лица в нашем примере изображения) производит для counts следующее:
(Pdb) counts
{'alan_grant': 5}
Это определенно меньшее количество голосов, но в словаре все еще есть только одно имя, так что мы могли бы найти Алана Гранта.
Как показано на рис. 5 ниже, Иэн Малкольм и Алан Грант идентифицированы правильно, поэтому эта часть скрипта работает нормально. Давайте продолжим и пройдемся по ограничительной рамке и именам маркеров каждого человека и нанесем их на наше выходное изображение для визуализации:
# loop over the recognized faces
for ((top, right, bottom, left), name) in zip(boxes, names):
# draw the predicted face name on the image
cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)
y = top - 15 if top - 15 > 15 else top + 15
cv2.putText(image, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 255, 0), 2)
# show the output image
cv2.imshow("Image", image)
cv2.waitKey(0)
Мы начинаем перебирать обнаруженные ограничивающие рамки лиц и предсказанные имена.
Чтобы создать итерируемый объект, чтобы мы могли легко перебирать значения, мы вызываем zip(boxes, name) для создания кортежа, из которого мы можем извлечь координаты и имена блоков.
Мы рисуем зеленый прямоугольник, используя координаты блока. Мы также используем координаты, чтобы вычислить, где должен быть отрисован текст имени человека, а затем фактически поместим текст имени на изображение. Если рамка, ограничивающая лицо, находится в самом верху изображения, нам нужно переместить текст ниже верхней части рамки, иначе текст будет обрезан. Затем мы продолжаем отображать изображение до тех пор, пока не будет нажата клавиша. Как запустить скрипт Python для распознавания лиц? Используя свой терминал, сначала убедитесь, что вы находитесь в соответствующей виртуальной среде Python (если вы используете виртуальную среду, конечно), используя команду workon.
Затем запустите сценарий, указав как минимум два аргумента командной строки. Если вы решите использовать метод HoG, не забудьте также передать --detection-method hog (в противном случае по умолчанию будет использоваться детектор глубокого обучения).
Ну давай же! Чтобы распознавать лица с помощью OpenCV и Python, откройте терминал и выполните наш скрипт:
python recognize_faces_image.py --encodings encodings.pickle \
--image examples/example_01.png
Второй пример распознавания лиц выглядит следующим образом:
Распознавать лица в видео
Теперь, когда мы применили распознавание лиц к изображениям, давайте также применим распознавание лиц к видео (в реальном времени).
Важное примечание о производительности: Распознаватель лиц CNN можно использовать в режиме реального времени только при использовании графического процессора (вы можете использовать его с ЦП, но ожидайте менее 0,5 кадров в секунду, что приведет к прерывистому видео).
В качестве альтернативы (вы используете ЦП) вы должны использовать метод HoG (или даже каскад OpenCV Haar, описанный в следующем сообщении в блоге) и рассчитывать на адекватную скорость. Следующий скрипт имеет много общего с предыдущим скриптом identity_faces_image.py.
Поэтому я пропущу то, что мы уже рассмотрели, и просто взгляну на видео компонент, чтобы вы могли видеть, что происходит.
Создайте новый файл identity_faces_video.py и вставьте следующий код:
# import the necessary packages
from imutils.video import VideoStream
import face_recognition
import argparse
import imutils
import pickle
import time
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-e", "--encodings", required=True,
help="path to serialized db of facial encodings")
ap.add_argument("-o", "--output", type=str,
help="path to output video")
ap.add_argument("-y", "--display", type=int, default=1,
help="whether or not to display output frame to screen")
ap.add_argument("-d", "--detection-method", type=str, default="cnn",
help="face detection model to use: either `hog` or `cnn`")
args = vars(ap.parse_args())
Импортируйте пакет и продолжите синтаксический анализ наших аргументов командной строки. У нас есть четыре аргумента командной строки, два из которых вы должны распознать выше (--encodings и --detection-method). Два других параметра:
--output : Путь к выходному видео.
--display : флаг, указывающий сценарию отображать кадр на экране. Значение 1 отображает, значение 0 не отображает выходной кадр на наш экран.
Загрузите нашу кодировку и запустите наш VideoStream:
# load the known faces and embeddings
print("[INFO] loading encodings...")
data = pickle.loads(open(args["encodings"], "rb").read())
# initialize the video stream and pointer to output video file, then
# allow the camera sensor to warm up
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
writer = None
time.sleep(2.0)
Чтобы получить доступ к нашей камере, мы используем класс VideoStream imutils.
Запустить поток. Если в вашей системе несколько камер (например, встроенная веб-камера и внешняя USB-камера), вы можете изменить src=0 на src=1 и так далее. Позже мы будем выборочно записывать обработанные видеокадры на диск, поэтому мы инициализируем средство записи None. Сон в течение 2 секунд позволяет нашей камере согреться. Оттуда мы запустим цикл while и начнем захватывать и обрабатывать кадры:
# loop over frames from the video file stream
while True:
# grab the frame from the threaded video stream
frame = vs.read()
# convert the input frame from BGR to RGB then resize it to have
# a width of 750px (to speedup processing)
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
rgb = imutils.resize(frame, width=750)
r = frame.shape[1] / float(rgb.shape[1])
# detect the (x, y)-coordinates of the bounding boxes
# corresponding to each face in the input frame, then compute
# the facial embeddings for each face
boxes = face_recognition.face_locations(rgb,
model=args["detection_method"])
encodings = face_recognition.face_encodings(rgb, boxes)
names = []
Первый шаг, который мы делаем, — захват кадра из видеопотока. Приведенный выше блок кода почти идентичен строке в предыдущем скрипте, за исключением того, что это видеокадр, а не неподвижное изображение. По сути, мы считываем кадры, предварительно обрабатываем их, затем обнаруживаем ограничивающие рамки лица + вычисляем кодировку для каждой ограничивающей рамки.
Далее, давайте переберем кодировки лиц, связанные с лицами, которые мы только что нашли:
# loop over the facial embeddings
for encoding in encodings:
# attempt to match each face in the input image to our known
# encodings
matches = face_recognition.compare_faces(data["encodings"],
encoding)
name = "Unknown"
# check to see if we have found a match
if True in matches:
# find the indexes of all matched faces then initialize a
# dictionary to count the total number of times each face
# was matched
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
# loop over the matched indexes and maintain a count for
# each recognized face face
for i in matchedIdxs:
name = data["names"][i]
counts[name] = counts.get(name, 0) + 1
# determine the recognized face with the largest number
# of votes (note: in the event of an unlikely tie Python
# will select first entry in the dictionary)
name = max(counts, key=counts.get)
# update the list of names
names.append(name)
В этом блоке кода мы проходим каждую кодировку и пытаемся сопоставить лица. Если совпадение найдено, мы подсчитываем голоса для каждого имени в наборе данных. Затем мы извлекаем самые высокие голоса, имена, связанные с лицами. Эти строки такие же, как и в предыдущем скрипте, который мы рассмотрели, так что продолжим.
В следующем блоке мы перебираем распознанные лица и продолжаем рисовать рамку вокруг лица и отображать имя человека над лицом:
# loop over the recognized faces
for ((top, right, bottom, left), name) in zip(boxes, names):
# rescale the face coordinates
top = int(top * r)
right = int(right * r)
bottom = int(bottom * r)
left = int(left * r)
# draw the predicted face name on the image
cv2.rectangle(frame, (left, top), (right, bottom),
(0, 255, 0), 2)
y = top - 15 if top - 15 > 15 else top + 15
cv2.putText(frame, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 255, 0), 2)
Строки также одинаковы, поэтому давайте сосредоточимся на коде, связанном с видео. Как вариант, записываем кадры на диск, посмотрим, как записать видео на диск с помощью OpenCV:
# if the video writer is None *AND* we are supposed to write
# the output video to disk initialize the writer
if writer is None and args["output"] is not None:
fourcc = cv2.VideoWriter_fourcc(*"MJPG")
writer = cv2.VideoWriter(args["output"], fourcc, 20,
(frame.shape[1], frame.shape[0]), True)
# if the writer is not None, write the frame with recognized
# faces to disk
if writer is not None:
writer.write(frame)
Предполагая, что мы предоставили путь к выходному файлу в аргументах командной строки, и мы еще не инициализировали средство записи видео, давайте продолжим и инициализируем его. Мы инициализируем VideoWriter_fourcc. FourCC — это 4-символьный код, в нашем случае мы будем использовать 4-символьный код «MJPG». Оттуда мы передаем этот объект в VideoWriter вместе с нашим путем к выходному файлу, кадрами в секунду и размерами кадров. Наконец, если модуль записи существует, мы можем продолжить запись кадров на диск.
Давайте обработаем, должны ли видеокадры распознавания лиц отображаться на экране:
# check to see if we are supposed to display the output frame to
# the screen
if args["display"] > 0:
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
Если параметр командной строки display установлен, мы продолжаем отображать кадр и проверяем, нажата ли клавиша escape («q»), после чего мы прервем цикл. Наконец, давайте выполним наши обязанности по уборке:
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()
# check to see if the video writer point needs to be released
if writer is not None:
writer.release()
Очищаем и освобождаем дисплей, видеопоток и видеозапись. Готовы увидеть сценарий в действии?
Чтобы продемонстрировать распознавание лиц в реальном времени с использованием OpenCV и Python, откройте терминал и выполните следующие команды:
python recognize_faces_video.py --encodings encodings.pickle \
--output output/webcam_face_recognition_output.avi --display 1
[INFO] loading encodings...
[INFO] starting video stream...
Распознавание лиц в видеофайлах
Как я упоминал в разделе «Структура проекта по распознаванию лиц», в разделе «Загрузка» этой записи в блоге содержится дополнительный скрипт —cognition_faces_video_file.py.
Этот файл в основном такой же, как файл веб-камеры, который мы только что рассмотрели, но он берет входной видеофайл и создает выходной видеофайл, если хотите.
Я применил наш код распознавания лиц к популярной «сцене обеда» из оригинального фильма «Парк Юрского периода», в которой актеры сидят за столом и делятся своими проблемами с парком:
python recognize_faces_video_file.py --encodings encodings.pickle \
--input videos/lunch_scene.mp4 --output output/lunch_scene_output.avi \
--display 0
Суммировать
В этом руководстве вы узнали, как выполнять распознавание лиц с помощью OpenCV, Python и глубокого обучения. Кроме того, мы используем библиотеку dlib Дэвиса Кинга и модуль face_recognition Адама Гейтги, который основан на глубоком обучении метрик dlib, чтобы упростить реализацию распознавания лиц. Как мы обнаружили,
Наша реализация распознавания лиц:
- точный
- Возможность выполнения в реальном времени через GPU
Надеюсь, вам понравился сегодняшний пост о распознавании лиц!
Полный код и набор данных:download.CSDN.net/download/Хе-хе…