Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Воган Ли - Python для хакеров (Библиотека программиста) - 2023.pdf
Скачиваний:
5
Добавлен:
07.04.2024
Размер:
14.76 Mб
Скачать

296      Глава 10. Ограничение доступа по принципу распознавания лиц

Проект #14. Ограничение доступа к инопланетному артефакту

Ваш взвод прорвался в лабораторию, где находится портал, рождающий монстров. Капитан Демминг приказал немедленно заблокировать эту лабораторию, оставив доступ только для него одного. Один из техников изменит текущие параметры системы с помощью военного ноутбука. В результате капитан Демминг получит доступ через этот ноутбук, используя два уровня безопасности: ввод пароля и верификацию лица. Зная о ваших навыках работы с OpenCV, он приказал вам реализовать распознавание лица.

ЗАДАЧА

Написать программу на Python, которая распознает лицо капитана Демминга.

Стратегия

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

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

Поддержка модулей и файлов

Большую часть работы в этом проекте мы проделаем с помощью OpenCV и NumPy. Если вы еще не установили эти библиотеки, обратитесь к разделу «Установка библиотек Python» на с. 31. Вам также понадобятся пакеты playsound для проигрывания звуков и pyttsx3 для реализации функциональности синтеза речи по тексту. Подробнее об этих модулях, включая инструкции по их установке, можете почитать в разделе «Код» на с. 269.

Код и сопутствующие файлы находятся в каталоге Chapter_10 на сайте книги https://nostarch.com/real-world-python/. Не меняйте структуру каталогов и имена

Проект #14. Ограничение доступа к инопланетному артефакту      297

файлов после их загрузки (рис. 10.7). Обратите внимание, что каталоги tester и trainer будут созданы позже, в скачиваемых материалах вы их не найдете.

И а а а а а а а а

а а а а а

И а а а а а а а а а а

П а а : а а а а

а а а а а а

П а а : а а

а а а а а

К а

П •а а а а а а •

А •а

Фа YAML а а а

Рис. 10.7. Файловая структура для проекта 14

Каталоги demming_trainer и demming_tester содержат изображения лица капитана Демминга и других людей, которые можно использовать для этого проекта. В текущем виде код ссылается именно на эти каталоги.

Если же вы решите предоставить собственные изображения — например, вы захотите попробовать себя в роли капитана Демминга, — то используйте каталоги с названиями trainer и tester. Первый будет создан автоматически приведенным ниже кодом, а вот каталог tester придется создать самостоятельно, после чего добавить в него собственные фотографии — об этом далее. Естественно, также потребуется скорректировать код, чтобы он ссылался на эти каталоги.

Код для захвата видео

Первый шаг (выполняемый кодом из 1_capture.py) — захват изображений лиц, которые потребуются для обучения алгоритма распознавания. Его можно

298      Глава 10. Ограничение доступа по принципу распознавания лиц

пропустить, если вы планируете использовать изображения из каталога demming_trainer.

Если вы хотите попробовать себя в роли капитана Демминга, сделайте через веб-камеру ПК с десяток снимков своего лица с разным выражением и без очков. Если веб-камеры у вас нет, пропустите этот шаг и сделайте несколько селфи с помощью телефона, после чего сохраните их в каталог trainer, как показано на рис. 10.7.

Импорт модулей, настройка аудио, веб-камеры, инструкций и путей файлов

Код листинга 10.2 импортирует модули, инициализирует и настраивает аудио­ движок, а также каскадный классификатор, инициализирует камеру и предоставляет инструкции для пользователя. Каскадный классификатор нам потребуется, так как прежде, чем распознать лицо, его необходимо обнаружить. Чтобы вспомнить об этих классификаторах и обнаружении лиц, обратитесь к разделу «Обнаружение лиц на фотографиях» на с. 264.

Листинг 10.1. Импорт модулей, указание файлов аудио и детектора лиц, а также настройка камеры и инструкций

1_capture.py, часть 1

import os import pyttsx3

import cv2 as cv

from playsound import playsound

engine = pyttsx3.init()

engine.setProperty('rate', 145) engine.setProperty('volume', 1.0)

root_dir = os.path.abspath('.')

tone_path = os.path.join(root_dir, 'tone.wav')

path = "C:/Python372/Lib/site-packages/cv2/data/" face_detector = cv.CascadeClassifier(path +

'haarcascade_frontalface_default.xml')

cap = cv.VideoCapture(0) if not cap.isOpened():

print("Could not open video device.")

cap.set(3, 640) # Frame width. cap.set(4, 480) # Frame height.

engine.say("Enter your information when prompted on screen. \ Then remove glasses and look directly at webcam. \

Make multiple faces including normal, happy, sad, sleepy. \ Continue until you hear the tone.")

engine.runAndWait()

Проект #14. Ограничение доступа к инопланетному артефакту      299

name = input("\nEnter last name: ")

user_id = input("Enter assigned ID Number: ") print("\nCapturing face. Look at the camera now!")1

Выполняем импорт, как и при обнаружении лиц в предыдущей главе. Операционную систему (через модуль os) мы будем использовать для управления путями файлов, pyttsx3 для воспроизведения аудиоинструкций, cv для работы с изображениями, запуска алгоритма обнаружения лиц и их распознавания, а playsound для проигрывания звука, оповещающего о завершении захвата изображения программой.

Далее настраиваем движок синтеза речи по тексту. С его помощью мы сообщаем пользователю, как выполнять программу. Голос по умолчанию уже определен в вашей операционной системе. В Windows на данный момент это голос Дэвида с американским акцентом , его задает параметр rate. Если вы захотите изменить его, то загляните в инструкции в листинге 9.1 на с. 270.

С помощью звукового сигнала мы будем уведомлять пользователя о завершении процесса захвата видео. Настройте путь к аудиофайлу tone.wav, как в главе 9.

Теперь укажите путь к файлу каскадного классификатора и присвойте этот классификатор переменной face_detector. Путь, указанный здесь, взят из моего компьютера с Windows, так что ваш может отличаться. К примеру, в macOS эти файлы находятся в opencv/data/haarcascades. Также вы найдете их онлайн по адресу https://hithub.com/opencv/tree/master/fata/haarcascades/.

Вглаве 9 вы узнали, как делать захват лиц с помощью веб-камеры компьютера.

Вэтой программе мы будем использовать аналогичный код, начиная с вызова cv.VideoCapture(0). Аргумент 0 относится к активной камере. Если у вас их несколько, то, возможно, потребуется опытным путем подобрать другое значение,

например 1. С помощью условия проверяем, запустилась ли камера. Если да, то устанавливаем ширину и высоту рамки . Первый аргумент в обоих методах относится к параметру ширины или высоты в списке аргументов.

Из соображений безопасности мы будем контролировать фазу видеозахвата. Для этого используем движок pyttsx3, чтобы объяснить эту процедуру пользователю (таким образом, запоминать ее не придется). Чтобы распознавание было точным, при съемке лица нужно снять очки или другие закрывающие лицо предметы.

1Перевод текста аудио: «Введите информацию, когда появится запрос на экране. Затем снимите очки и смотрите прямо в веб-камеру. Сделайте несколько фото лица, включая нейтральное, счастливое, грустное, сонное. Продолжайте, пока не услышите звуковой сигнал». Перевод текста на экране: «Введите свою фамилию: Введите присвоенный ID-номер: Съемка лица. Посмотрите на камеру!»

300      Глава 10. Ограничение доступа по принципу распознавания лиц

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

В завершение вам, как капитану Деммингу, придется выполнять ряд инструкций, выведенных на экране. Прежде всего ввести свою фамилию . В данном случае о повторах беспокоиться не нужно, так как капитан Демминг будет единственным пользователем. Кроме того, мы присвоим ему уникальный номер ID. OpenCV будет использовать эту переменную user_id, чтобы отследить все лица в ходе обучения и прогнозирования. Позже мы создадим словарь для сопоставления ID пользователей с конкретными людьми, предполагая, что в будущем доступ в лабораторию получит не только капитан Демминг.

Как только капитан введет свой ID и нажмет enter, камера активируется и начнет выполнять захват изображений, о чем нужно сообщить входящему через еще один вызов print(). Вспомните, в предыдущей главе я говорил, что каскадный детектор лиц чувствителен к ориентации головы. Для его корректной работы пользователь должен смотреть точно в камеру и держать голову максимально прямо.

Захват изображений для обучения

Листинг 10.2 выполняет захват указанного количества изображений лиц с помощью веб-камеры и цикла while. Код сохраняет полученные изображения в каталог, после чего подает сигнал завершения операции.

Листинг 10.2. Захват изображений видео с помощью цикла

1_capture.py, часть 2

if not os.path.isdir('trainer'): os.mkdir('trainer')

os.chdir('trainer')

frame_count = 0

while True:

# Поочередный захват 30 кадров.

_, frame = cap.read()

gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

face_rects = face_detector.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5)

for (x, y, w, h) in face_rects: frame_count += 1

cv.imwrite(str(name) + '.' + str(user_id) + '.'

+ str(frame_count) + '.jpg', gray[y:y+h, x:x+w]) cv.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv.imshow('image', frame)

cv.waitKey(400)if frame_count >= 30:

break

Проект #14. Ограничение доступа к инопланетному артефакту      301

print("\nImage collection complete. Exiting...") playsound(tone_path, block=False)

cap.release()

cv.destroyAllWindows()

Проверим наличие каталога trainer. Если он отсутствует, создадим его с помощью метода mkdir() модуля операционной системы. Далее меняем текущий рабочий каталог на trainer.

Теперь инициализируем переменную frame_count как 0. Код будет захватывать и сохранять видеокадр только при обнаружении в нем лица. Чтобы определить момент завершения программы, нужно отслеживать количество захваченных кадров.

Далее запускаем цикл while, установленный как True. После вызываем метод read() объекта cap. Как говорилось в предыдущей главе, этот метод возвращает кортеж из логического кода возврата и объекта numpy ndarray, представляющего текущий кадр. Код возврата обычно используется для проверки окончания кадров при считывании из файла. Поскольку здесь считывание мы не делаем, то добавляем к названию файла нижнее подчеркивание, что означает неиспользуемую переменную.

И обнаружение, и распознавание лиц работает с изображениями в оттенках серого, поэтому конвертируем кадр в эту цветовую схему и называем получившийся массив gray. Далее вызываем метод detectMultiscale() для обнаружения лиц на изображении . Принцип работы этого метода вы найдете в описании листинга 9.2 на с. 273. Поскольку мы контролируем условия получения снимка, заставляя пользователя посмотреть в веб-камеру ноутбука, то в верности работы алгоритма можно не сомневаться, хотя проверить результаты все же нужно.

Предыдущий метод должен вывести координаты очерчивающей лицо прямоугольной рамки. Выполняем цикл for для каждого набора координат и тут же увеличиваем переменную frame_count на 1.

С помощью метода OpenCV imwrite() сохраняем изображение в каталоге trainer. Каталоги именуются согласно следующей логике: name.user.id.frame_count.jpg — например, demming.1.9.jpg. Сохраняем только часть изображения, попадающую в прямоугольник, очерчивающий лицо, чтобы в обучающий алгоритм не попали лишние фоновые признаки.

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