- •Об авторе
- •О научных редакторах
- •Благодарности
- •От издательства
- •Введение
- •Для кого эта книга?
- •Почему Python?
- •План книги
- •Версия Python, платформа и IDE
- •Установка Python
- •Запуск Python
- •Использование виртуальной среды
- •Вперед!
- •Глава 1. Спасение моряков с помощью теоремы Байеса
- •Теорема Байеса
- •Проект #1. Поиск и спасение
- •Стратегия
- •Установка библиотек Python
- •Код для теоремы Байеса
- •Время сыграть
- •Итоги
- •Дополнительная литература
- •Усложняем проект. Более грамотный поиск
- •Усложняем проект. Поиск лучшей стратегии с помощью MCS
- •Усложняем проект. Вычисление вероятности обнаружения
- •Глава 2. Установление авторства с помощью стилометрии
- •Проект #2: «Собака Баскервилей», «Война миров» и «Затерянный мир»
- •Стратегия
- •Установка NLTK
- •Корпусы текстов
- •Код стилометрии
- •Итоги
- •Дополнительная литература
- •Практический проект: охота на собаку Баскервилей с помощью распределения
- •Практический проект: тепловая карта пунктуации
- •Усложняем проект: фиксирование частотности
- •Глава 3. Суммаризация текста с помощью обработки естественного языка
- •Стратегия
- •Веб-скрапинг
- •Код для «У меня есть мечта»
- •Установка gensim
- •Код для суммаризации речи «Заправляйте свою кровать»
- •Проект #5. Суммаризация речи с помощью облака слов
- •Модули Word Cloud и PIL
- •Код для создания облака слов
- •Итоги
- •Дополнительная литература
- •Усложняем проект: ночные игры
- •Усложняем проект: суммаризация суммаризаций
- •Глава 4. Отправка суперсекретных сообщений с помощью книжного шифра
- •Одноразовый блокнот
- •Шифр «Ребекка»
- •Проект #6. Цифровой ключ к «Ребекке»
- •Стратегия
- •Код для шифрования
- •Отправка сообщений
- •Итоги
- •Дополнительная литература
- •Глава 5. Поиск Плутона
- •Проект #7. Воссоздание блинк-компаратора
- •Стратегия
- •Данные
- •Код блинк-компаратора
- •Использование блинк-компаратора
- •Проект #8. Обнаружение астрономических транзиентов путем дифференцирования изображений
- •Стратегия
- •Код для детектора транзиентов
- •Использование детектора транзиентов
- •Итоги
- •Дополнительная литература
- •Практический проект: представление орбитальной траектории
- •Практический проект: найди отличия
- •Усложняем проект: сосчитаем звезды
- •Глава 6. Победа в лунной гонке с помощью «Аполлона-8»
- •Цель миссии «Аполлон-8»
- •Траектория свободного возврата
- •Задача трех тел
- •Проект #9. На Луну с «Аполлоном-8»!
- •Использование модуля turtle
- •Стратегия
- •Код программы для расчета свободного возврата «Аполлона-8»
- •Выполнение симуляции
- •Итоги
- •Дополнительная литература
- •Практический проект: симуляция шаблона поисков
- •Практический проект: запусти меня!
- •Практический проект: останови меня!
- •Усложняем проект: симуляция в истинном масштабе
- •Усложняем проект: реальный «Аполлон-8»
- •Глава 7. Выбор мест высадки на Марсе
- •Посадка на Марс
- •Карта MOLA
- •Проект #10. Выбор посадочных мест на Марсе
- •Стратегия
- •Код для выбора мест посадки
- •Результаты
- •Итоги
- •Дополнительная литература
- •Практический проект: убедимся, что рисунки становятся частью изображения
- •Практический проект: визуализация профиля высот
- •Практический проект: отображение в 3D
- •Практический проект: совмещение карт
- •Усложняем проект: три в одном
- •Усложняем проект: перенос прямоугольников
- •Глава 8. Обнаружение далеких экзопланет
- •Транзитная фотометрия
- •Проект #11. Симуляция транзита экзопланеты
- •Стратегия
- •Код для транзита
- •Эксперименты с транзитной фотометрией
- •Проект #12. Получение изображений экзопланет
- •Стратегия
- •Код для пикселизатора
- •Итоги
- •Дополнительная литература
- •Практический проект: обнаружение инопланетных мегаструктур
- •Практический проект: обнаружение транзита астероидов
- •Практический проект: добавление эффекта потемнения к краю
- •Практический проект: обнаружение пятен на звездах
- •Практический проект: обнаружение инопланетной армады
- •Практический проект: обнаружение планеты с луной
- •Практический проект: измерение продолжительности экзопланетного дня
- •Усложняем проект: генерация динамической кривой блеска
- •Глава 9. Как различить своих и чужих
- •Обнаружение лиц на фотографиях
- •Проект #13. Программирование робота-часового
- •Стратегия
- •Результаты
- •Обнаружение лиц в видеопотоке
- •Итоги
- •Дополнительная литература
- •Практический проект: размытие лиц
- •Усложняем проект: обнаружение кошачьих мордочек
- •Глава 10. Ограничение доступа по принципу распознавания лиц
- •Распознавание лиц с помощью LBPH
- •Схема распознавания лиц
- •Извлечение гистограмм локальных бинарных шаблонов
- •Проект #14. Ограничение доступа к инопланетному артефакту
- •Стратегия
- •Поддержка модулей и файлов
- •Код для захвата видео
- •Код для обучения алгоритма распознавания лиц
- •Код для прогнозирования лиц
- •Результаты
- •Итоги
- •Дополнительная литература
- •Усложняем проект: добавление пароля и видеозахвата
- •Усложняем проект: похожие лица и близнецы
- •Усложняем проект: машина времени
- •Глава 11. Создание интерактивной карты побега от зомби
- •Проект #15. Визуализация плотности населения с помощью хороплетной карты
- •Стратегия
- •Библиотека анализа данных
- •Библиотеки bokeh и holoviews
- •Установка pandas, bokeh и holoviews
- •Работа с данными по уровню безработицы и плотности населения в округах и штатах
- •Разбираем код holoviews
- •Код для отрисовки хороплетной карты
- •Планирование маршрута
- •Итоги
- •Дополнительная литература
- •Усложняем проект: отображение на карте изменения численности населения США
- •Глава 12. Находимся ли мы в компьютерной симуляции?
- •Проект #16. Жизнь, Вселенная и пруд черепахи Йертл
- •Код симуляции пруда
- •Следствия симуляции пруда
- •Измерение затрат на пересечение строк или столбцов сетки
- •Результаты
- •Стратегия
- •Итоги
- •Дополнительная литература
- •Дополнение
- •Усложняем проект: поиск безопасного места в космосе
- •Усложняем проект: а вот и Солнце
- •Усложняем проект: взгляд глазами собаки
- •Усложняем проект: кастомизированный поиск слов
- •Усложняем проект: что за сложную паутину мы плетем
- •Усложняем проект: идем вещать с горы
- •Решения для практических проектов
- •Глава 2. Определение авторства с помощью стилометрии
- •Охота на собаку Баскервилей с помощью распределения
- •Тепловая карта пунктуации
- •Глава 4. Отправка суперсекретных сообщений с помощью книжного шифра
- •Составление графика символов
- •Отправка секретов шифром времен Второй мировой войны
- •Глава 5. Поиск Плутона
- •Представление орбитальной траектории
- •Глава 6. Победа в лунной гонке с помощью «Аполлона-8»
- •Симуляция шаблона поисков
- •Заведи меня!
- •Останови меня!
- •Глава 7. Выбор мест высадки на Марсе
- •Убеждаемся, что рисунки становятся частью изображения
- •Визуализация профиля высоты
- •Отображение в 3D
- •Совмещение карт
- •Глава 8. Обнаружение далеких экзопланет
- •Обнаружение инопланетных мегаструктур
- •Обнаружение транзита астероидов
- •Добавление эффекта потемнения к краю
- •Обнаружение инопланетной армады
- •Обнаружение планеты с луной
- •Измерение продолжительности экзопланетного дня
- •Глава 9. Как различить своих и чужих
- •Размытие лиц
- •Глава 10. Ограничение доступа по принципу распознавания лиц
- •Усложняем проект: добавление пароля и видеозахвата
302 Глава 10. Ограничение доступа по принципу распознавания лиц
Даже если лицо капитана Демминга при идентификации будет всегда расслабленным, с нейтральным выражением, использование различных выражений при обучении программы позволит добиться более устойчивых результатов. Кстати, весьма полезно, если пользователь в фазе захвата слегка покачает головой из стороны в сторону.
Далее проверяем, достигнуто ли заданное количество кадров; при положительном результате цикл завершается . Обратите внимание, если пользователь в камеру не смотрит, то цикл будет выполняться бесконечно, так как он отсчитывает кадры, только если каскадный классификатор обнаруживает лицо и возвращает обрамляющую его рамку.
Сообщаем пользователю о выключении камеры выводом сообщения и звуковым сигналом. Затем завершаем программу, освобождая камеру и закрывая все окна изображений.
На данном этапе в каталоге trainer должно находиться 30 изображений лица пользователя. В следующем разделе, используя эти изображения или изображения из каталога demming_trainer, мы с помощью OpenCV займемся обучением алгоритма распознавания лиц.
Код для обучения алгоритма распознавания лиц
Используем OpenCV для создания алгоритма распознавания лиц на основе LBPH, его обучения на подготовленных изображениях и сохранения результатов в файле. При использовании вашего лица укажите каталог trainer. В ином случае будет использован каталог demming_trainer, который вместе с содержащим код файлом 2_train.py находится в доступной для скачивания директории Chapter_10.
Код листинга 10.3 настраивает пути к каскадам Хаара, используемым для обнаружения лиц, и к обучающим изображениям, захваченным предыдущей программой. OpenCV отслеживает лица с помощью целочисленных меток, а не строк имен. Код также инициализирует списки для хранения этих меток и связанных с ними изображений. Затем выполняются перебор обучающих изображений, их загрузка, извлечение ID пользователя из имени файла и обнаружение лиц. В завершение происходит обучение алгоритма распознавания и сохранение результата в файл.
Листинг 10.3. Обучение и сохранение алгоритма распознавания лиц LBPH
2_train.py
import os
import numpy as np import cv2 as cv
cascade_path = "C:/Python372/Lib/site-packages/cv2/data/"
Проект #14. Ограничение доступа к инопланетному артефакту 303
face_detector = cv.CascadeClassifier(cascade_path + 'haarcascade_frontalface_default.xml')
train_path = './demming_trainer' # Используйте для лица Демминга
#train_path = './trainer' # Раскомментируйте для использования своего лица image_paths = [os.path.join(train_path, f) for f in os.listdir(train_path)] images, labels = [], []
for image in image_paths:
train_image = cv.imread(image, cv.IMREAD_GRAYSCALE)
label = int(os.path.split(image)[-1].split('.')[1]) name = os.path.split(image)[-1].split('.')[0] frame_num = os.path.split(image)[-1].split('.')[2]
faces = face_detector.detectMultiScale(train_image) for (x, y, w, h) in faces: images.append(train_image[y:y + h, x:x + w]) labels.append(label)
print(f"Preparing training images for {name}.{label}.{frame_num}") cv.imshow("Training Image", train_image[y:y + h, x:x + w]) cv.waitKey(50)
cv.destroyAllWindows()
recognizer = cv.face.LBPHFaceRecognizer_create() recognizer.train(images, np.array(labels)) recognizer.write('lbph_trainer.yml') print("Training complete. Exiting...")
Код, выполняющий импорт и распознавание лиц, вы уже видели. В программе 1_capture.py мы вырезали из обучающих изображений рамки с лицами, но нелишне повторить эту процедуру. Поскольку 2_train.py является автономной программой, лучше ничего не принимать без подтверждения.
Далее необходимо выбрать набор обучающих изображений: либо свои из каталога trainer, либо заранее подготовленные из каталога demming_trainer . Закомментируйте или удалите строку для тех, которые не используете. Напомню, так как мы не предоставляем полный путь к каталогу, то нужно запускать программу из папки, где она хранится. Она должна располагаться на один уровень выше каталогов trainer и demming_trainer.
Далее с помощью спискового включения создаем список image_paths. В нем мы сохраним путь и имена файлов всех изображений в обучающем каталоге. После создаем пустой список для изображений и их меток.
Начинаем перебирать пути к изображениям циклом for. Считываем изображение в оттенках серого, после чего извлекаем из его имени файла числовую метку и преобразуем ее в целое число . Напомню, что метка соответствует ID пользователя, введенному через программу 1_capture.py перед захватом видеокадров.
304 Глава 10. Ограничение доступа по принципу распознавания лиц
Давайте подробнее остановимся на процессе извлечения и конвертации. Метод os.path.split() получает путь к каталогу и возвращает кортеж из этого пути
иимени файла, как показано в следующем фрагменте:
>>>import os
>>>path = 'C:\demming_trainer\demming.1.5.jpg'
>>>os.path.split(path)
('C:\\demming_trainer', 'demming.1.5.jpg')
Затем, используя индекс -1, мы выбираем последний элемент кортежа и разделяем его по точкам. В итоге получается список из четырех элементов (имя пользователя, его ID, номер кадра и расширение файла).
>>> os.path.split(path)[-1].split('.') ['demming', '1', '5', 'jpg']
Чтобы извлечь значение метки, мы выбираем в этом списке второй элемент
спомощью индекса 1.
>>>os.path.split(path)[-1].split('.')[1]
'1'
Повторяем этот процесс для извлечения name и frame_num для каждого изображения. В данный момент все они представлены строками, поэтому ID пользователя нужно преобразовать в целое число, чтобы можно было использовать его в качестве метки.
Теперь вызываем детектор лиц для каждого обучающего изображения . В ответ мы получим numpy.ndarray, который назовем faces. Начинаем перебор этого массива, содержащего координаты обнаруженных рамок с лицами. Добавляем изображение в рамке в созданный ранее список images, а также ID пользователя с этого изображения в список labels.
Сообщаем пользователю о происходящем, выводя сообщение в оболочку. Затем в качестве проверки показываем каждое обучающее изображение в течение 50 мс. Если вы смотрели популярный клип Питера Гэбриэла «Sledgehammer» 1986 года, то должны оценить подобный видеоряд.
Теперь пора обучать алгоритм распознавания лиц. Как и в случае с детектором лиц OpenCV, сначала мы инстанцируем объект распознавателя . Далее вызываем метод train(), которому передаются списки images и labels, преобразуемые в массив NumPy.
Мы не хотим заниматься обучением алгоритма распознавания при каждой проверке чьего-либо лица, поэтому записываем результаты обучения в файл lbph_trainer.yml и сообщаем пользователю о завершении программы.
Проект #14. Ограничение доступа к инопланетному артефакту 305
Код для прогнозирования лиц
Время переходить к распознаванию лиц. Этот процесс называется прогнозированием ввиду того, что в нем все сводится к вероятности. Программа 3_predict.py сначала вычисляет конкатенированную гистограмму для каждого лица, после чего находит расстояние между этой гистограммой и всеми гистограммами в обу чающем наборе. Затем она присваивает новому лицу метку и имя контрольного лица с наибольшим соответствием, но только если расстояние между ними впишется в заданный пороговый диапазон.
Импорт модулей и подготовка алгоритма распознавания лиц
Код листинга 10.4 импортирует модули, подготавливает словарь для хранения ID и имен пользователей, настраивает детектор и алгоритм распознавания лиц, а также определяет путь к тестовым данным. Тестовые данные состоят из изображений лица капитана Демминга и нескольких других людей. Изображение капитана из обучающего каталога включено с целью проверки результатов. Если все сработает верно, то алгоритм должен положительно определить это изображение с низким показателем расстояния.
Листинг 10.4. Импорт модулей и подготовка к обнаружению и распознаванию лиц
3_predict.py, часть 1
import os
from datetime import datetime import cv2 as cv
names = {1: "Demming"}
cascade_path = "C:/Python372/Lib/site-packages/cv2/data/" face_detector = cv.CascadeClassifier(cascade_path +
'haarcascade_frontalface_default.xml')
recognizer = cv.face.LBPHFaceRecognizer_create() recognizer.read('lbph_trainer.yml')
#test_path = './tester'
test_path = './demming_tester'
image_paths = [os.path.join(test_path, f) for f in os.listdir(test_path)]
После нескольких уже знакомых нам операций импорта мы создаем словарь для связывания ID пользователей с их именами. Несмотря на то что сейчас в нем будет всего одна запись, этот словарь name в дальнейшем позволит без проблем добавить и другие. Если вы используете собственное лицо, то фамилию можете тоже поменять, но в качестве ID необходимо оставить 1.
Далее повторяем код, настраивающий объект face_detector. При этом введите собственный cascade_path (см. листинг 10.1 на с. 298).
306 Глава 10. Ограничение доступа по принципу распознавания лиц
Теперь создаем объект распознавателя, как делали это в коде 2_train.py . Затем с помощью метода read() загружаем файл .yml, содержащий информацию для обучения.
Алгоритм распознавания нужно протестировать при помощи изображений лиц из отдельного каталога. Если вы используете заранее подготовленные снимки лица капитана Демминга, то укажите путь к каталогу demming_tester . В ином случае укажите путь к созданному ранее каталогу tester, куда можете добавить собственные изображения. Если вы выбрали свой снимок, то не нужно повторно использовать здесь обучающие изображения, хотя одно можно взять в качестве проверочного. Используйте программу 1_capture.py для создания новых изображений. Если вы носите очки, включите ряд фото в очках и без них. При этом также следует добавить сюда несколько снимков из каталога demming_tester.
Распознавание лиц и обновление журнала доступа
Код листинга 10.5 перебирает изображения в тестовом каталоге, обнаруживает на них лица, сравнивает гистограммы этих лиц с содержащимися в файле обучения, именует лицо, присваивает ему значение уверенности, а затем регистрирует его имя и время доступа в текстовом файле. При положительном совпадении ID программа теоретически должна разблокировать вход в лабораторию, но так как лаборатории у нас нет, эту часть мы пропустим.
Листинг 10.5. Выполнение распознавания лиц и обновление журнала доступа
3_predict.py, часть 2
for image in image_paths:
predict_image = cv.imread(image, cv.IMREAD_GRAYSCALE) faces = face_detector.detectMultiScale(predict_image,
scaleFactor=1.05,
minNeighbors=5)
for (x, y, w, h) in faces:
print(f"\nAccess requested at {datetime.now()}.")
face = cv.resize(predict_image[y:y + h, x:x + w], (100, 100)) predicted_id, dist = recognizer.predict(face)
if predicted_id == 1 and dist <= 95: name = names[predicted_id]
print("{} identified as {} with distance={}"
.format(image, name, round(dist, 1)))
print(f"Access granted to {name} at {datetime.now()}.", file=open('lab_access_log.txt', 'a'))
else:
name = 'unknown' print(f"{image} is {name}.")
cv.rectangle(predict_image, (x, y), (x + w, y + h), 255, 2) cv.putText(predict_image, name, (x + 1, y + h - 5),
Проект #14. Ограничение доступа к инопланетному артефакту 307
cv.FONT_HERSHEY_SIMPLEX, 0.5, 255, 1) cv.imshow('ID', predict_image)
cv.waitKey(2000)
cv.destroyAllWindows()
Начинаем с перебора изображений в тестовом каталоге — в demming_tester либо в tester. Считываем каждое изображение в оттенках серого и присваиваем получающийся массив переменной predict_image, после чего выполняем для него обнаружение лиц.
Теперь перебираем рамки лиц, как делали это ранее. Выводим сообщение о запросе доступа, а затем с помощью OpenCV изменяем размер подмассива face до 100 × 100 пикселей . Это значение близко к размеру обучающих изображений из каталога demming_trainer. Синхронизировать размер изображений не обязательно, но это улучшит результаты. Если вы используете собственные изображения в качестве изображений капитана Демминга, то следует убедиться, что размеры обучающего и тестового изображений близки.
Теперь пора прогнозировать личность того, чье лицо идентифицируется. Для этого потребуется всего одна строка. В ней мы просто вызываем для объекта recognizer метод predict(), передавая ему подмассив face. Этот метод вернет ID и значение расстояния.
Чем меньше значение расстояния, тем выше вероятность того, что лицо спро гнозировано верно. Это значение можно использовать в качестве порога: все изображения, спрогнозированные как капитан Демминг и имеющие показатель, равный или ниже порога, будут определены как капитан Демминг. Все остальные получат обозначение 'unknown'.
Порог задаем с помощью инструкции if . Если вы используете собственные обучающие и тестовые изображения, то при первом запуске программы установите значение расстояния как 1000. Просмотрите эти значения для всех изображений в тестовом каталоге, включая известные и 'unknown'. Найдите пороговое значение, ниже которого все лица верно распознаются как принадлежащие капитану Деммингу. В дальнейшем это будет ваш дискриминатор. Для изображений в каталогах demming_trainer и demming_tester пороговое расстояние должно равняться 95.
Далее получаем имя для изображения, используя в качестве ключа в словаре names значение predicted_id. Выводим в оболочке сообщение о распознавании изображения, включая имя соответствующего файла, имя из словаря и значение расстояния.
Для журнала выводим сообщение о том, что name (в данном случае капитан Демминг) получил доступ в лабораторию, и с помощью модуля datetime указываем время доступа .