Распознавание лиц служит жизненно важной целью безопасности. Его можно увидеть повсюду. Его можно найти в камере видеонаблюдения перед вашим домом и датчике на вашем телефоне. Более того, лицо является важнейшей сущностью для идентификации человека. Он отличает человека, поэтому распознавание лиц — важная техника. Системы распознавания лиц используются для разблокировки программного обеспечения на мобильных устройствах. Однако при определенных условиях, например, при плохом освещении, длинных волосах, солнцезащитных очках или когда другие объекты частично закрывают лицо, распознавание лиц не работает.
Распознавание лиц — это технология, которая включает в себя идентификацию лица человека с помощью различных методов, в том числе алгоритмов машинного обучения. K-Nearest Neighbours (KNN) — один из популярных алгоритмов, используемых для распознавания лиц. Это контролируемый подход к обучению, который используется для целей классификации. Он работает, обнаруживая ближайших соседей точки данных и классифицируя ее в соответствии с большинством ее соседей. При распознавании лиц KNN использует расстояние между точками черт лица для классификации лица.
В этой статье мы реализуем базовую форму распознавания лиц с использованием классификатора каскадов Хаара и алгоритма k-ближайших соседей.
Что такое каскад Хаара?
Это алгоритм обнаружения объектов на основе машинного обучения, используемый для поиска лиц на изображении или видео в реальном времени. Алгоритм работает путем сравнения прямоугольных элементов в разных положениях изображения и в разных масштабах. Исследовательская статья Быстрое обнаружение объектов с использованием усиленного каскада простых функций, написанная Полом Виолой и Майклом Джонсом в 2001 году, содержит функции обнаружения краев или линий, которые используются в этом методе. Алгоритму дается большое количество положительных фотографий с лицами и большое количество отрицательных изображений без лиц для обучения.
Почему мы используем KNN для распознавания лиц?
Алгоритм KNN использует классификацию соседей как прогностическое значение хорошего значения экземпляра. В KNN входные данные классифицируются на основе k ближайших точек данных. Для распознавания лиц можно использовать KNN для сравнения черт лица входного изображения с чертами лица ранее сохраненного изображения. KNN также прост в реализации и эффективен в вычислительном отношении. Кроме того, экспериментальные результаты показывают, что KNN обладает большей способностью распознавать незакрытые лица спереди с вероятностью успеха 90%.
Начало работы
Мы будем использовать VS Code для этого проекта, и мы будем запускать два (2) скрипта Python;
- Скрипт для добавления нового лица
- Скрипт для живого распознавания лиц
Скрипт для добавления нового лица
import os import numpy as np import cv2 import pickle face_data = [] i = 0 camera = cv2.VideoCapture(0) facecascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') name = input('Enter your name --> ') ret = True while(ret): ret, frame = camera.read() if ret == True: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) face_coordinates = facecascade.detectMultiScale(gray, 1.3, 4) for (a, b, w, h) in face_coordinates: faces = frame[b:b+h, a:a+w, :] resized_faces = cv2.resize(faces, (50, 50)) if i % 10 == 0 and len(face_data) < 10: face_data.append(resized_faces) cv2.rectangle(frame, (a, b), (a+w, b+h), (255, 0, 0), 2) i += 1 cv2.imshow('frames', frame) if cv2.waitKey(1) == 27 or len(face_data) >= 10: break else: print('error') break cv2.destroyAllWindows() camera.release() face_data = np.asarray(face_data) face_data = face_data.reshape(10, -1) if 'names.pkl' not in os.listdir('data/'): names = [name]*10 with open('data/names.pkl', 'wb') as file: pickle.dump(names, file) else: with open('data/names.pkl', 'rb') as file: names = pickle.load(file) names = names + [name]*10 with open('data/names.pkl', 'wb') as file: pickle.dump(names, file) if 'faces.pkl' not in os.listdir('data/'): with open('data/faces.pkl', 'wb') as w: pickle.dump(face_data, w) else: with open('data/faces.pkl', 'rb') as w: faces = pickle.load(w) faces = np.append(faces, face_data, axis=0) with open('data/faces.pkl', 'wb') as w: pickle.dump(faces, w)
Давайте рассмотрим, что делает приведенный выше блок кода, строка за строкой.
- Строка 1–4: Импорт библиотек
import os import numpy as np import cv2 import pickle
Здесь мы импортируем библиотеку numpy, потому что она используется для представления изображений в виде массивов, выполнения операций с этими массивами и управления векторами признаков, извлеченными из изображений лиц. Мы импортируем библиотеку ОС, поскольку она предоставляет способ взаимодействия с операционной системой независимо от платформы. Мы импортируем библиотеку cv2, потому что она используется для выполнения таких задач, как обнаружение лиц и выравнивание. Кроме того, мы импортируем библиотеку pickle, поскольку она используется для сохранения и загрузки обученных моделей.
- Строка 6–7: Инициализация переменных.
face_data = [] i = 0
Строка 9: здесь мы создаем объект захвата видео для доступа к веб-камере. Аргумент 0 передается, потому что мы хотим использовать встроенную веб-камеру нашего ноутбука. Используйте 1, если вы используете внешнюю камеру.
camera = cv2.VideoCapture(0)
Строка 11: Создание каскадного объекта Хаара для обнаружения лиц в кадре.
facecascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
Строка 13: Запрос имени человека, добавляющего свое лицо.
name = input('Enter your name --> ')
Строка 14: Установите ret = True (чтобы запустить бесконечный цикл).
ret = True
Переменная ret обычно используется в проектах по распознаванию лиц, чтобы показать, правильно ли считывается поток изображений. При считывании изображения с камеры важно убедиться, что кадры считываются правильно, так как неправильное считывание кадров может привести к ошибкам алгоритма распознавания лиц. Поэтому, когда мы устанавливаем ret = True, мы указываем, что поток изображения читается правильно и кадры захватываются успешно. Если для ret установлено значение False, это означает, что при чтении изображения произошла ошибка, и алгоритм распознавания лиц может работать не так, как ожидалось.
Давайте начнем цикл распознавания лиц с помощью KNN.
while(ret): ret, frame = camera.read() if ret == True: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) face_coordinates = facecascade.detectMultiScale(gray, 1.3, 4) for (a, b, w, h) in face_coordinates: faces = frame[b:b+h, a:a+w, :] resized_faces = cv2.resize(faces, (50, 50)) if i % 10 == 0 and len(face_data) < 10: face_data.append(resized_faces) cv2.rectangle(frame, (a, b), (a+w, b+h), (255, 0, 0), 2) i += 1 cv2.imshow('frames', frame) if cv2.waitKey(1) == 27 or len(face_data) >= 10: break else: print('error') break cv2.destroyAllWindows() camera.release() face_data = np.asarray(face_data) face_data = face_data.reshape(10, -1) if 'names.pkl' not in os.listdir('data/'): names = [name]*10 with open('data/names.pkl', 'wb') as file: pickle.dump(names, file) else: with open('data/names.pkl', 'rb') as file: names = pickle.load(file) names = names + [name]*10 with open('data/names.pkl', 'wb') as file: pickle.dump(names, file) if 'faces.pkl' not in os.listdir('data/'): with open('data/faces.pkl', 'wb') as w: pickle.dump(face_data, w) else: with open('data/faces.pkl', 'rb') as w: faces = pickle.load(w) faces = np.append(faces, face_data, axis=0) with open('data/faces.pkl', 'wb') as w: pickle.dump(faces, w)
Этот код считывает изображение с камеры и обнаруживает лица в каждом кадре с помощью каскадного классификатора Хаара, предоставленного OpenCV. Он делает это, перебирая кадры, пока ret имеет значение true, указывая на то, что видеопоток читается правильно. Для каждого кадра он преобразует изображение в оттенки серого, определяет координаты лица с помощью каскадного классификатора, обрезает область лица, изменяет ее размер до 50x50 пикселей, а затем каждые 10 кадров добавляет измененное лицо в список face_data. После того, как 10 лиц будут собраны или если пользователь нажмет клавишу «Esc», программа завершает цикл и сохраняет собранные данные о лицах в списке face_data в виде массива NumPy. Файлы names.pkl иfaces.pkl затем проверяются на существование. Если они не существуют, создаются новые файлы, и переменная имени сохраняется в named.pkl, а данные лица сохраняются в Faces.pkl. Если файлы уже существуют, код загружает существующие данные, добавляет новые данные и имена лиц и сохраняет их обратно в файлы. Это создает набор данных изображений лиц и соответствующих имен, которые используются для проекта.
Давайте посмотрим на результат:
После запуска кода на вашем терминале появится что-то вроде этого, чтобы вы могли сохранить свое имя.
Сразу после этого включается ваша камера, чтобы сохранить ваше лицо. Ваше изображение будет снято 10 раз, и камера выключится.
Давайте попробуем сохранить лицо другого человека: не забудьте перезапустить код, чтобы сохранить новое имя и лицо.
Скрипт для распознавания лиц в реальном времени с помощью knn
import cv2 from sklearn.neighbors import KNeighborsClassifier import pickle import numpy as np facecascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') with open('data/faces.pkl', 'rb') as w: faces = pickle.load(w) with open('data/names.pkl', 'rb') as file: labels = pickle.load(file) camera = cv2.VideoCapture(0) print('Shape of Faces matrix --> ', faces.shape) knn = KNeighborsClassifier(n_neighbors=4) knn.fit(faces,labels) while True: ret, frame = camera.read() if ret == True: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) face_coordinates = facecascade.detectMultiScale(gray, 1.3, 5) for (a, b, w, h) in face_coordinates: fc = frame[b:b + h, a:a + w, :] r = cv2.resize(fc, (50, 50)).flatten().reshape(1,-1) text = knn.predict(r) cv2.putText(frame, text[0], (a, b-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2) cv2.rectangle(frame, (a, b), (a + w, b + w), (0, 0, 255), 2) cv2.imshow('livetime face recognition', frame) if cv2.waitKey(1) == 27: break else: print("error") break cv2.destroyAllWindows() camera.release()
Давайте рассмотрим, что делает приведенный выше блок кода, построчно.
- Строка 1–4: Импорт необходимых библиотек.
import cv2 from sklearn.neighbors import KNeighborsClassifier import pickle import numpy as np
Здесь мы импортируем библиотеку numpy, потому что она используется для представления изображений в виде массивов и выполнения операций с этими массивами, а также для управления векторами признаков, извлеченными из изображений лиц.
Мы импортируем библиотеку ОС, потому что она обеспечивает способ взаимодействия с операционной системой независимым от платформы способом.
Мы импортируем библиотеку cv2, потому что она используется для выполнения реальных задач, таких как обнаружение лиц и выравнивание лиц.
Кроме того, мы импортируем библиотеку pickle, поскольку она используется для сохранения и загрузки обученных моделей, таких как классификаторы распознавания лиц.
- Строка 6–16:
facecascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') with open('data/faces.pkl', 'rb') as w: faces = pickle.load(w) with open('data/names.pkl', 'rb') as file: labels = pickle.load(file) camera = cv2.VideoCapture(0) print('Shape of Faces matrix --> ', faces.shape)
В приведенном выше коде каскадный классификатор Хаара для обнаружения лиц загружается с помощью функции cv2.CascadeClassifier(), а путь к XML-файлу классификатора предоставляется в качестве аргумента. Каскадный классификатор Хаара — это предварительно обученный классификатор, предоставляемый OpenCV, который может обнаруживать лица в потоке изображения или видео.
Далее код загружает ранее сохраненные данные о лицах и соответствующие метки (имена) из файлов «faces.pkl» и «names.pkl» с помощью функции «pickle.load()». Эти файлы были ранее созданы кодом, который собирал данные о лицах с камеры. Данные о лицах хранятся в массиве NumPy под названием «лица», а метки (имена) хранятся в списке, называемом метками.
Наконец, код инициализирует камеру с помощью функции cv2.VideoCapture() с аргументом 0, что означает, что будет использоваться камера по умолчанию. Затем он печатает форму матрицы лиц, чтобы проверить размер ранее собранных данных о лицах.
- Проверьте форму данных/матрицы лиц.
Строка 17–42:
knn = KNeighborsClassifier(n_neighbors=4) knn.fit(faces,labels) while True: ret, frame = camera.read() if ret == True: gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) face_coordinates = facecascade.detectMultiScale(gray, 1.3, 5) for (a, b, w, h) in face_coordinates: fc = frame[b:b + h, a:a + w, :] r = cv2.resize(fc, (50, 50)).flatten().reshape(1,-1) text = knn.predict(r) cv2.putText(frame, text[0], (a, b-10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2) cv2.rectangle(frame, (a, b), (a + w, b + w), (0, 0, 255), 2) cv2.imshow('livetime face recognition', frame) if cv2.waitKey(1) == 27: break else: print("error") break cv2.destroyAllWindows() camera.release()
В приведенном выше коде классификатор K-ближайших соседей (KNN) обучается с использованием ранее собранных данных о лицах (лица) и соответствующих меток (меток). Классификатор инициализируется с «n_neighbors=4» в качестве количества соседей, которые следует учитывать при классификации.
Затем код считывает кадры с камеры с помощью функции cv2.VideoCapture(), преобразует каждый кадр в оттенки серого с помощью функции cv2.cvtColor() и использует каскадный классификатор Хаара для обнаружения лиц в кадре. Для каждого обнаруженного лица код изменяет размер лица до 50x50 пикселей с помощью «cv2.resize()», сглаживает его с помощью «flatten()» и преобразует его в двумерный массив с помощью «reshape (1, -1)». Затем сплющенное и измененное лицо передается в метод predict() классификатора KNN для прогнозирования метки лица.
Прогнозируемая метка отображается в кадре с помощью «cv2.putText()», а прямоугольник рисуется вокруг обнаруженного лица с помощью «cv2.rectangle()». Кадр с предсказанными метками и прямоугольниками отображается на экране с помощью ‘cv2.imshow()’.
Код работает в бесконечном цикле, пока пользователь не нажмет клавишу «Esc» (cv2.waitKey(1) == 27)», после чего код уничтожает все окна и освобождает камеру с помощью «cv2.destroyALLWindows()» и 'camera.release()' соответственно.
Таким образом, этот код выполняет распознавание лиц в реальном времени с использованием предварительно обученного классификатора KNN и каскадного классификатора Хаара для обнаружения лиц в потоке изображений с камеры и отображает предсказанные метки и прямоугольники вокруг обнаруженных лиц в режиме реального времени.
Теперь давайте посмотрим на результат для сохраненных лиц.
- Я использовал лицо сестры и свое лицо.
Чтобы получить более точные результаты, мы сделали это вместе.
Вы всегда можете добавить больше лиц, чтобы улучшить результат.
Заключение
K-ближайшие соседи (KNN) — это мощный алгоритм, используемый для распознавания лиц благодаря своей простоте, эффективности и гибкости.
Его способность учиться на обучающих данных и точно классифицировать неизвестные экземпляры делает его популярным выбором для задач распознавания лиц. Это позволяет легко настраивать и настраивать параметры для оптимизации производительности для конкретных приложений.
KNN также устойчив к шуму и может обрабатывать большие объемы данных, что делает его пригодным для реальных приложений.
Посмотреть полный код этой статьи можно здесь