Распознавание лиц при помощи Python и OpenCV
В этой статье мы разберемся, что такое распознавание лиц и чем оно отличается от определения лиц на изображении. Мы кратко рассмотрим теорию распознавания лиц, а затем перейдем к написанию кода. В конце этой статьи вы сможете создать свою собственную программу распознавания лиц на изображениях, а также в прямом эфире с веб-камеры.
Что такое обнаружение лиц?
Одной из основных задач компьютерного зрения является автоматическое обнаружение объекта без вмешательства человека. Например, определение человеческих лиц на изображении.
Лица людей отличаются друг от друга. Но в целом можно сказать, что всем им присущи определенные общие черты.
Существует много алгоритмов обнаружения лиц. Одним из старейших является алгоритм Виолы-Джонса. Он был предложен в 2001 году и применяется по сей день. Чуть позже мы тоже им воспользуемся. После прочтения данной статьи вы можете изучить его более подробно.
Обнаружение лиц обычно является первым шагом для решения более сложных задач, таких как распознавание лиц или верификация пользователя по лицу. Но оно может иметь и другие полезные применения.
Вероятно самым успешным использованием обнаружения лиц является фотосъемка. Когда вы фотографируете своих друзей, встроенный в вашу цифровую камеру алгоритм распознавания лиц определяет, где находятся их лица, и соответствующим образом регулирует фокус.
Что такое распознавание лиц?
Итак, в создании алгоритмов обнаружения лиц мы (люди) преуспели. А можно ли также распознавать, чьи это лица?
Распознавание лиц — это метод идентификации или подтверждения личности человека по его лицу. Существуют различные алгоритмы распознавания лиц, но их точность может различаться. Здесь мы собираемся описать распознавание лиц при помощи глубокого обучения.
Итак, давайте разберемся, как мы распознаем лица при помощи глубокого обучения. Для начала мы производим преобразование, или, иными словами, эмбеддинг (embedding), изображения лица в числовой вектор. Это также называется глубоким метрическим обучением.
Для облегчения понимания давайте разобьем весь процесс на три простых шага:
Обнаружение лиц
Наша первая задача — это обнаружение лиц на изображении или в видеопотоке. Далее, когда мы знаем точное местоположение или координаты лица, мы берем это лицо для дальнейшей обработки.
Извлечение признаков
Вырезав лицо из изображения, мы должны извлечь из него характерные черты. Для этого мы будем использовать процедуру под названием эмбеддинг.
Нейронная сеть принимает на вход изображение, а на выходе возвращает числовой вектор, характеризующий основные признаки данного лица. (Более подробно об этом рассказано, например, в нашей серии статей про сверточные нейронные сети — прим. переводчика). В машинном обучении данный вектор как раз и называется эмбеддингом.
Теперь давайте разберемся, как это помогает в распознавании лиц разных людей.

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

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

Здесь мы не будем заниматься обучением подобной сети. Это требует значительных вычислительных мощностей и большого объема размеченных данных. Вместо этого мы используем уже предобученную Дэвисом Кингом нейронную сеть. Она обучалась приблизительно на 3000000 изображений. Эта сеть выдает вектор длиной 128 чисел, который и определяет основные черты лица.
Познакомившись с принципами работы подобных сетей, давайте посмотрим, как мы будем использовать такую сеть для наших собственных данных.
Мы передадим все наши изображения в эту предобученную сеть, получим соответствующие вектора (эмбеддинги) и затем сохраним их в файл для следующего шага.
Сравнение лиц
Теперь, когда у нас есть вектор (эмбеддинг) для каждого лица из нашей базы данных, нам нужно научиться распознавать лица из новых изображений. Таким образом, нам нужно, как и раньше, вычислить вектор для нового лица, а затем сравнить его с уже имеющимися векторами. Мы сможем распознать лицо, если оно похоже на одно из лиц, уже имеющихся в нашей базе данных. Это означает, что их вектора будут расположены вблизи друг от друга, как показано на примере ниже:

Итак, мы передали в сеть две фотографии, одна Владимира Путина, другая Джорджа Буша. Для изображений Буша у нас были вектора (эмбеддинги), а для Путина ничего не было. Таким образом, когда мы сравнили эмбеддинг нового изображения Буша, он был близок с уже имеющимися векторам,и и мы распознали его. А вот изображений Путина в нашей базе не было, поэтому распознать его не удалось.
Что такое OpenCV?
В области искусственного интеллекта задачи компьютерного зрения — одни из самых интересных и сложных.
Компьютерное зрение работает как мост между компьютерным программным обеспечением и визуальной картиной вокруг нас. Оно дает ПО возможность понимать и изучать все видимое в окружающей среде.
Например, на основе цвета, размера и формы плода мы определяем разновидность определенного фрукта. Эта задача может быть очень проста для человеческого разума, однако в контексте компьютерного зрения все выглядит иначе.
Сначала мы собираем данные, затем выполняем определенные действия по их обработке, а потом многократно обучаем модель, как ей распознавать сорт фрукта по размеру, форме и цвету его плода.
В настоящее время существуют различные пакеты для выполнения задач машинного обучения, глубокого обучения и компьютерного зрения. И безусловно, модуль, отвечающий за компьютерное зрение, проработан лучше других.
OpenCV — это библиотека с открытым программным кодом. Она поддерживает различные языки программирования, например R и Python. Работать она может на многих платформах, в частности — на Windows, Linux и MacOS.
Основные преимущества OpenCV :
- имеет открытый программный код и абсолютно бесплатна
- написана на C/C++ и в сравнении с другими библиотеками работает быстрее
- не требует много памяти и хорошо работает при небольшом объеме RAM
- поддерживает большинство операционных систем, в том числе Windows, Linux и MacOS.
Установка
Здесь мы будем рассматривать установку OpenCV только для Python. Мы можем установить ее при помощи менеджеров pip или conda (в случае, если у нас установлен пакет Anaconda).
1. При помощи pip
При помощи pip процесс установки может быть выполнен с использованием следующей команды:
pip install opencv-python
2. Anaconda
Если вы используете Anaconda, то выполните следующую команду в окружении Anaconda:
conda install -c conda-forge opencv
Распознавание лиц с использованием Python
В этой части мы реализуем распознавание лиц при помощи Python и OpenCV. Для начала посмотрим, какие библиотеки нам потребуются и как их установить:
- OpenCV
- dlib
- Face_recognition
OpenCV — это библиотека обработки изображений и видео, которая используется для их анализа. Ее применяют для обнаружения лиц, считывания номерных знаков, редактирования фотографий, расширенного роботизированного зрения, оптического распознавания символов и многого другого.
Библиотека dlib , поддерживая Дэвисом Кингом, содержит реализацию глубокого метрического обучения. Мы ее будем использовать для конструирования векторов (эмбеддингов) изображений, играющих ключевую роль в процессе распознавания лиц.
Библиотека face_recognition , созданная Адамом Гейтгеем, включает в себя функции распознавания лиц dlib и является по сути надстройкой над ней. С ней очень легко работать, и мы будем ее использовать в нашем коде. Имейте ввиду, что ее нужно устанавливать после библиотеки dlib .
Для установки OpenCV наберите в командной строке:
pip install opencv-python
Мы перепробовали множество способов установки dlib под WIndows и простейший способ это сделать — при помощи Anaconda. Поэтому для начала установите Anaconda (вот здесь подробно рассказано, как это делается). Затем введите в терминале следующую команду:
conda install -c conda-forge dlib
Далее, для установки библиотеки face_recognition наберите в командной строке следующее:
pip install face_recognition
Теперь, когда все необходимые модули установлены, приступим к написанию кода. Нам нужно будет создать три файла.
Первый файл будет принимать датасет с изображениями и выдавать эмбеддинг для каждого лица. Эти эмбеддинги будут записываться во второй файл. В третьем файле мы будем сравнивать лица с уже существующими изображениями. А затем мы сделаем тоже самое в стриме с веб-камеры.
Извлечение признаков лица
Для начала вам нужно достать датасет с лицами или создать свой собственный. Главное, убедитесь, что все изображения находятся в папках, причем в каждой папке должны быть фотографии одного и того же человека.
Затем разместите датасет в вашей рабочей директории, то есть там, где выбудете создавать собственные файлы.
from imutils import paths import face_recognition import pickle import cv2 import os # в директории Images хранятся папки со всеми изображениями imagePaths = list(paths.list_images('Images')) knownEncodings = [] knownNames = [] # перебираем все папки с изображениями for (i, imagePath) in enumerate(imagePaths): # извлекаем имя человека из названия папки name = imagePath.split(os.path.sep)[-2] # загружаем изображение и конвертируем его из BGR (OpenCV ordering) # в dlib ordering (RGB) image = cv2.imread(imagePath) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #используем библиотеку Face_recognition для обнаружения лиц boxes = face_recognition.face_locations(rgb,model='hog') # вычисляем эмбеддинги для каждого лица encodings = face_recognition.face_encodings(rgb, boxes) # loop over the encodings for encoding in encodings: knownEncodings.append(encoding) knownNames.append(name) # сохраним эмбеддинги вместе с их именами в формате словаря data = # для сохранения данных в файл используем метод pickle f = open("face_enc", "wb") f.write(pickle.dumps(data)) f.close()
Сейчас мы сохранили все эмбеддинги в файл под названием face_enc . Теперь мы можем их использовать для распознавания лиц на изображениях или во время видеострима с веб-камеры.
Распознавание лиц во время прямой трансляции веб-камеры
Вот код для распознавания лиц из прямой трансляции веб-камеры:
import face_recognition import imutils import pickle import time import cv2 import os # find path of xml file containing haarcascade file cascPathface = os.path.dirname( cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" # load the harcaascade in the cascade classifier faceCascade = cv2.CascadeClassifier(cascPathface) # load the known faces and embeddings saved in last file data = pickle.loads(open('face_enc', "rb").read()) print("Streaming started") video_capture = cv2.VideoCapture(0) # loop over frames from the video file stream while True: # grab the frame from the threaded video stream ret, frame = video_capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) # convert the input frame from BGR to RGB rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # the facial embeddings for face in input encodings = face_recognition.face_encodings(rgb) names = [] # loop over the facial embeddings incase # we have multiple embeddings for multiple fcaes for encoding in encodings: # Compare encodings with encodings in data["encodings"] # Matches contain array with boolean values and True for the embeddings it matches closely # and False for rest matches = face_recognition.compare_faces(data["encodings"], encoding) # set name =inknown if no encoding matches name = "Unknown" # check to see if we have found a match if True in matches: #Find positions at which we get True and store them 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: # Check the names at respective indexes we stored in matchedIdxs name = data["names"][i] # increase count for the name we got counts[name] = counts.get(name, 0) + 1 # set name which has highest count name = max(counts, key=counts.get) # update the list of names names.append(name) # loop over the recognized faces for ((x, y, w, h), name) in zip(faces, names): # rescale the face coordinates # draw the predicted face name on the image cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(frame, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2) cv2.imshow("Frame", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows()
В данном примере для обнаружения лиц использовался метод cv2.CascadeClassifier() из библиотеки OpenCV. Но вы с таким же успехом можете пользоваться и методом face_recognition.face_locations() , как мы уже делали в предыдущем примере.
Распознавание лиц на изображениях
Код для обнаружения и распознавания лиц на изображениях почти аналогичен тому, что вы видели выше. Убедитесь в этом сами:
import face_recognition import imutils import pickle import time import cv2 import os # find path of xml file containing haarcascade file cascPathface = os.path.dirname( cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" # load the harcaascade in the cascade classifier faceCascade = cv2.CascadeClassifier(cascPathface) # load the known faces and embeddings saved in last file data = pickle.loads(open('face_enc', "rb").read()) # Find path to the image you want to detect face and pass it here image = cv2.imread(Path-to-img) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # convert image to Greyscale for haarcascade gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60), flags=cv2.CASCADE_SCALE_IMAGE) # the facial embeddings for face in input encodings = face_recognition.face_encodings(rgb) names = [] # loop over the facial embeddings incase # we have multiple embeddings for multiple fcaes for encoding in encodings: # Compare encodings with encodings in data["encodings"] # Matches contain array with boolean values and True for the embeddings it matches closely # and False for rest matches = face_recognition.compare_faces(data["encodings"], encoding) # set name =inknown if no encoding matches name = "Unknown" # check to see if we have found a match if True in matches: # Find positions at which we get True and store them 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: # Check the names at respective indexes we stored in matchedIdxs name = data["names"][i] # increase count for the name we got counts[name] = counts.get(name, 0) + 1 # set name which has highest count name = max(counts, key=counts.get) # update the list of names names.append(name) # loop over the recognized faces for ((x, y, w, h), name) in zip(faces, names): # rescale the face coordinates # draw the predicted face name on the image cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(image, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2) cv2.imshow("Frame", image) cv2.waitKey(0)
Результат:


На этом наша статья подошла к концу. Мы надеемся, что вы получили общее представление о задачах распознавания лиц и способах их решения.
Распознавание лиц на python c отправкой в телеграмм или как защититься от недоброжелателей
Что за программы? Представим такую ситуацию, вам в инстаграме угрожает не очень умный человек и каким то ЧУДЕСНЫМ образом он узнал ваш адрес. К вашему счастью он сглупил и оказалось, что он ставил в ленту свое фото с лицом. Вы боитесь этого человека. Что можно сделать? Определенно не писать скрипт по распознаванию лица, но мы тут с вами Pyhton-исты. Так вот, у нас будет папка (назовем ее img) в которой будет лицо нашего злоумышленника (я не зря говорил, что он ставил фото),скрипт будет получать видео с камеры (которую можно повесить у двери своего дома). Если вдруг на видео будет замечено человеческое лицо, оно будет сверяться на схожесть с лицом нашего злоумышленника (по фотке с лицом которое в папке img). Если лица совпадают, то это значит, что у вашей двери стоит тот самый злоумышленник, в такой ситуации у нас просто будет выводиться что то в консоль. Вы же можете сделать к примеру телеграмм бота, который при такой ситуации будет вам писать.
Вторая будет как помощь. Я уже говорил, что злоумышленник поставил фото в инстаграм. Надо будет скачать ее (в папку img). Наша программа будет принимать на вход путь к фотке, читать ее, пытаться найти лица, и в случае, если лицо найдено, она будет обрезать его и сохранять уже только лицо (так удобнее).
Для программ нам понадобятся модули opencv, face recognition.
OpenCV качайте так pip install opencv-python . Самая сложная часть для меня была в установке face-recognition, так как при его установке вылезала ошибка. Однако у вас может ее не быть. Попробуйте скачать этот модуль. В консоли напишите: pip install dlib & pip install face-recognition
Если же появилась, необходимо установить Visual Studio и там выбрать и установить Python и C++. Может сейчас не понятно, но скачав Visual Studio до вас дойдет о чем я. После установки VisualStudio можете смело качать этот модуль. Так же необходимо скачать натренированную нейронную модель. Вот. Я сохранил это все дело как faces.xml
Начнем со второй программы, так как первая более трудная, надо же понять основы.
import cv2 #Импортировали модуль opencv path_to_img = input("Введите путь до картинки (полное название файла, с форматом)>>> ") #Получаем путь к картинке из которой надо обрезать лицо img = cv2.imread(path_to_img) #Методом imread мы как бы читаем наше фото, после этого можем производить манипуляции над ним face_recog = cv2.CascadeClassifier('faces.xml') #Методом CascadeClassifier мы подключаем уже натренированную нейронную модель. face_result = face_recog.detectMultiScale(img, scaleFactor=2, minNeighbors=3) #Метод detectMultiScale выполняет поиск лица на фото которые мы указали в качестве первого аргумента #Аргумент scaleFactor это как бы шаг масштабирования (насколько большое лицо) #Аргумент minNeighbors это что то вроде указания о том, сколько лиц может быть рядом #Значение этим аргументам я взял с воздуха, но все же это работает #Вы можете поиграться с ними, главное не ставьте scaleFactor=1 так как будет ошибка if len(face_result) != 0: #Функция, выполнение которой мы записали в face_result (detectMultiScale), возвращает список, если он пуст, значит лиц на фото нет for index, (x,y,w,h) in enumerate(face_result): #Мы проходимся по всем элементам списка, и получаем позицию x,y и ширину с высотой(w,h) img = img[x:y+h] #Тут думаю все понятно, мы обрезаем картинку (она у нас как список с цветами) с точки x до точки y+h cv2.imwrite(f'images/to_recog/practice/.jpg', img) #Этот метод записывает получившуюся картинку по опр. пути, принимает путь и само изображение cv2.imshow("Result", img) #Этот метод выводит результат на экран. Первый аргумент - что то по типу комментария к картинке, второй - сама картинка cv2.waitKey(0) #От этого, зависит какое кол-во времени наша картинка будет отображаться на экране. Если передаем 0 то будет отображаться пока не закроем(бесконечно)ся
И так. Запустим ее и передадим фото Рами Малека


Как видим все круто и не очень трудно. Главное понять принцип. Давайте теперь займемся главной (первой) программой которая будет сравнивать лица. Она немножко труднее, но не бойтесь, все равно будет просто.
import cv2 import face_recognition import os #Импортируем все модули cap = cv2.VideoCapture(0) #Методом VideoCapture мы получаем видео, тут можно указать путь к mp4 файлу и прочитать его #Указав 0 мы получаем видео с ВЕБ КАМЕРЫ image_to_recognition = face_recognition.load_image_file('images/to_recog/practice/0.jpg') #Теперь начинаем работать с face_recognition, метод load_image_file получает изображение #В данном случае то фото рами малека которые мы обрезали второй программой image_enc = face_recognition.face_encodings(image_to_recognition)[0] #Тут методом face_encodings мы получаем КОДИРОВКУ ЛИЦА рами малека. #Просто у каждого фото с лицом (да и не только) есть КОДИРОВКА. #Если у нас есть 2 фото с лицами и если их кодировки совпадают, значит на фото один и тот же человвек recognizer_cc = cv2.CascadeClassifier('faces.xml') #Про это уже говорил #Любое видео, это быстро меняющиеся картинки, от того и создается эффект анимации #Здесь тот же принцип, в бесконечном цикле мы очень быстро меняем изображения и получаем видео while True: success,img = cap.read() #Получаем изображение которое будем быстро показывать, если изображение не получено success будет равен False recognize = recognizer_cc.detectMultiScale(img, scaleFactor=2, minNeighbors=3) #Про это уже говорил if len(recognize) != 0: #Если на фото есть лицо, делаем то, что ниже print("Лицо нашел") unknown_face = face_recognition.face_encodings(img) #Получем кодировку неизвестного лица (лица которое на видео) compare = face_recognition.compare_faces([unknown_face], image_enc) #Сравниваем две кодировки (кодировку рами малека и кодировку неизвестного лица) #Первый параметр надо передать как список (за это и обернули в []) #Второй это кодировка рами малека (этот аргумент передаем просто) if compare == True: #Если мы зашли сюда, значит лица одинаковые print('Рами приблизился к вашему дому!') else: print('Все ок.')
Думаю вы поняли, на место лица рами можно поставить лицо нашего злоумышленника и если он подойдет к вашей двери программа найдет его лицо и сравнит с тем что вы уже заготовили.
Не судите строго, это моя первая статья, если есть какие то ошибки напишите об этом ниже 🙂
Как написать программу для распознавания лиц


Александр Белозеров Эксперт в разработке ПО.

Выясняем, как устроено распознавание лиц на видео и фото, и пробуем самостоятельно создать собственный детектор вместе с программистом Александром Белозеровым.
Где нужно распознавание лиц?
- Государство: видеоаналитика используется службами безопасности стран для пограничного контроля, а в Москве так находили нарушителей карантина. Службы безопасности организаций, имеющих дело с секретностью, также используют алгоритмы идентификации для контроля доступа сотрудников к секретным объектам.
- IT-индустрия: Microsoft, Google, Яндекс, ВКонтакте тоже разрабатывают собственные алгоритмы.
- Медицина: технология помогает выявить болезни и отслеживать прогресс в лечении.
- Банкинг: банки используют идентификацию по лицу, чтобы снять деньги в банкомате или получить кредит.
- Образование: распознавание лица помогает поймать тех, кто списывает, — сервисы подключаются к камере на компьютере студента и отслеживают его поведение и движение глаз.
- Персональные портативные устройства: на смартфонах помимо идентификации пользователя распознавание лица выполняет и развлекательную функцию — у приложений Samsung и Snapchat оно лежит в основе AR-фильтров и масок для лица.

Освойте профессию
«Fullstack-разработчик на Python»
Fullstack-разработчик на Python
Fullstack-разработчики могут в одиночку сделать IT-проект от архитектуры до интерфейса. Их навыки востребованы у работодателей, особенно в стартапах. Научитесь программировать на Python и JavaScript и создавайте сервисы с нуля.

Профессия / 12 месяцев
Fullstack-разработчик на Python
Создавайте веб-проекты самостоятельно

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

В алгоритме Виолы-Джонса маски накладываются на разные части кадра, а программа определяет, может ли в них находиться объект. Работает это так:
- Классификатор (алгоритм, который будет искать объект в кадре) обучают на фотографиях лиц и получают пороговое значение — его превышение будет сигнализировать о том, что в кадре есть лицо.
- В классификатор загружают изображение, на котором будут искать лицо.
- Классификатор накладывает на него маски и отдельно складывает яркость пикселей, попавших в белую часть маски, и яркость пикселей, попавших в черную часть маски. Потом из первого значения он вычитает второе.
Результат сравнивается с пороговой величиной.
Если результат меньше пороговой величины, значит, в части кадра нет лица, и алгоритм заканчивает свою работу. А если больше, он переходит к следующей части кадра.

На практике маски находят лицо на фотографии так:

Для разработки мы советуем кроссплатформенную среду разработки PyCharm — в ней есть полезные инструменты для управления версиями пакетов, анализа кода и его отладки. Скачать ее можно тут.
Шаг 3. Создайте новый проект на Python, мы назвали его opencv_face_recognition.
Шаг 4. По правому клику на названии проекта в дереве каталогов добавьте новый файл main.py.
Шаг 5. Установите библиотеку. Для этого в настройках (Settings) проекта нужно найти вкладку с управлением конфигурацией интерпретатора, нажать на «+», вбить в поиск последовательно «opencv-python» и «opencv-contrib-python» и установить эти пакеты.
Это облегченная версия, которая использует для расчетов только процессор, но процесс установки все равно может занять до 15 минут.
Шаг 6. Чтобы использовать установленную библиотеку OpenCV, импортируйте модуль cv2:
До тех пор пока мы не обратимся к каким-либо именам из него, он будет подсвечиваться серым, как неиспользуемый.
Шаг 7. Поместите ранее скачанный классификатор haarcascade_frontalface_default.xml в папку проекта

и загрузите его следующим образом:
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
Обратите внимание, что в PyCharm для его корректной подсветки синтаксиса нам пришлось переписать первую строку с импортом.
Шаг 8. Загрузите изображение, на котором мы будем искать лицо, в режиме оттенков серого — информация о цвете алгоритму не важна, только его интенсивность:
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
img = cv2.imread(‘xfiles4.jpg’)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Мы будем использовать кадр из сериала «Секретные материалы» с Малдером и Скалли; вы можете поместить в папку проекта любое другое фото.

Шаг 9. Напишите код. Для поиска лиц на изображении мы используем метод с сигнатурой (его именем и списком параметров)
cv2.CascadeClassifier.detectMultiScale (image [, scaleFactor [, minNeighbors [, flags [, minSize [, maxSize]]]]]):
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
img = cv2.imread(‘xfiles4.jpg’)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
Нам хватит первых трех параметров.
- В image надо будет передать 8-битную матрицу изображения.
- scaleFactor показывает, во сколько раз мы будем уменьшать исходное изображение, пытаясь обнаружить объект: это делается потому, что мы изначально не знаем, какого размера будет лицо. Чем меньше будет этот коэффициент, тем дольше будет работать алгоритм.
- minNeighbors влияет на качество обнаружения: чем больше его значение, тем меньше образов сможет обнаружить алгоритм, но тем точнее будет его работа.
Дефолтные значения для последних двух параметров — 1.1 и 3. Их можно заменить на любые другие и подобрать для конкретного случая, если на дефолтных значениях алгоритм будет работать плохо.
Шаг 10. Если лица будут обнаружены, функция вернет набор объектов типа Rect (x, y, w, h) — прямоугольников, начало которых задано парой координат (x, y), а ширина и высота — как w и h. В цикле for добавим эти прямоугольники в исходное изображение image при помощи cv2.rectangle(image, start_point, end_point, color, thickness) по координатам их противоположных вершин (x, y) и (x+w, y+h):
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
img = cv2.imread(‘xfiles4.jpg’)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
Шаг 11. Для отображения результата и закрытия программы по нажатию клавиши добавим еще несколько строк: вывод картинки, ожидание нажатия любой клавиши и последующее закрытие окна. В итоге весь наш проект будет выглядеть так:
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
img = cv2.imread(‘xfiles4.jpg’)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow(‘img’, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Шаг 12. Сочетанием клавиш Ctrl-Shift-F10 (Ctrl-Shift-R на MacOS) запустим скрипт:

Инструкция: распознаем лицо в видеопотоке с веб-камеры
Модернизируем наш код так, чтобы в реальном времени обнаруживать лица в кадре, например, на видео с веб-камеры.
Шаг 1. Создайте объект для захвата видеострима:
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
capture_io = cv2.VideoCapture(2)
Число для cv2.VideoCapture() придется поперебирать, индексом нашей внешней веб-камеры оказалась двойка.
Шаг 2. Считывать кадры с видеоустройства будем в вечном цикле: cv2.VideoCapture.read() возвращает булево значение об успешном считывании из потока (оно нам не нужно) в паре с самой картинкой. Преобразуем ее в 8-битную матрицу так же, как и раньше:
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
capture_io = cv2.VideoCapture(2)
while True:
_, img = capture_io.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Шаг 3. Остается переписать только конец цикла — чтобы у него было условие выхода, например, по нажатию на «q» (от quit, «выйти»). cv2.waitKey(time) 10 мс ожидает ввода с клавиатуры юникод-символа, который приведет к закрытию стрима и программы.
import cv2.cv2 as cv2
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
capture_io = cv2.VideoCapture(2)
while True:
_, img = capture_io.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow(‘img’, img)
if cv2.waitKey(10) & 0xFF == ord(«q»):
break
capture_io.release()
cv2.destroyAllWindows()
Шаг 4. Код готов, нажимаем Ctrl-Shift-F10 (Ctrl-Shift-R на MacOS) и наблюдаем результат вживую:
Создаём свою модель распознавания лиц на Python
У нас уже есть большой цикл про компьютерное зрение и распознавание лиц. В этом цикле мы научились видеть лицо человека, определять примерный возраст и пол, работать с веб-камерой и с файлами. Если не читали, можно начать сейчас:
- Как работает распознавание лиц;
- Находим лица в картинке с веб-камеры;
- Учим нейросеть определять пол и возраст по картинке с камеры;
- Учим нейросеть распознавать возраст по фотографии.
Пока что наш алгоритм не умеет различать разных людей в кадре. Максимум — сказать, что это «мужчина, столько-то лет», а кто конкретно — нет.
Чтобы нейронка научилась узнавать вас по лицу, нужно создать собственную модель распознавания лиц и скормить её нейросети. Тогда она сможет определять и подписывать имя человека в кадре. Сегодня мы сделаем первую часть — соберём датасет и обучим на нём нашу нейросеть. А во второй части прикрутим новую модель к алгоритмам распознавания.
Коротко про распознавание лиц и компьютерное зрение
- Для распознавания лица компьютер должен получить изображение — через камеру или готовый файл.
- Компьютер использует особый алгоритм, который разбивает изображение на прямоугольники.
- С помощью этих прямоугольников алгоритм пытается найти на картинке знакомые переходы между светлыми и тёмными областями.
- Если в одном месте программа находит много таких совпадений, то, скорее всего, это лицо человека.
- Чтобы программистам каждый раз не писать свой код распознавания с нуля, сделали библиотеку компьютерного зрения — cv2. Если в неё загрузить заранее подготовленные параметры лиц, она сможет распознавать их намного точнее.
- С помощью этой библиотеки можно находить на картинке не только лица, но и другие предметы — для этого нужно использовать дополнительные библиотеки либо обучать систему самому.
- Чтобы нейросеть могла понять, кто именно перед ней, её тоже нужно этому обучить отдельно.
Что нужно для обучения нейросети
Чтобы научить нейросеть узнавать конкретных людей в кадре, нужно:
- Собрать датасет.
- Обучить нейросеть на этом датасете и выгрузить результат обучения в отдельный файл.
Датасет в нашем случае — это набор фотографий. Фото должны быть подобраны так, чтобы лицо было в разных ракурсах или с разным освещением. Чем больше фото, тем точнее обучение. Идеально, если по имени файла сразу будет понятно, какие фото к какому человеку относятся.
Когда датасет будет собран, мы отдадим его нейросети — она распознает все лица и построит их модель, которую можно сохранить в отдельном файле. Если этот файл потом отдать другой нейросети, она сможет понять, кто именно находится перед ней в кадре.
Подготовка
В папке, где будет лежать скрипт, нужно создать две папки:
В первой папке будут лежать фотографии, на которых будет учиться нейросеть, а во второй будут результаты этого обучения.
Ещё нужно скачать файл haarcascade_frontalface_default.xml и положить его туда же, где и скрипт. Это модель распознавания лиц по примитивам Хаара.
Собираем датасет
В коммерческих проектах датасет собирают долго и из разных источников, а потом вручную проверяют каждое фото, подходит оно или нет. Чтобы не тратить на это время, используем такой лайфхак: мы сгенерируем датасет из кадров с камеры. Для этого мы запустим захват видео и каждые 100 миллисекунд будем брать новый кадр и запоминать лицо оттуда.
Точно так же работает разблокировка по лицу с помощью камеры в Андроиде: телефон просит покрутить головой перед камерой, а сам в это время делает много снимков, а потом тренирует модель распознавания.
Сначала подключим все нужные библиотеки:
# подключаем библиотеку машинного зрения
import cv2
# библиотека для вызова системных функций
import os
Сразу подключим модель с примитивами Хаара к нейросети — это тот самый файл, который скачивали отдельно.
Чтобы нейросеть в процессе обучения знала, кому принадлежат эти фотографии, добавим параметр id. Это будет внутренний номер пользователя, который мы потом превратим в настоящее имя:
# получаем путь к этому скрипту path = os.path.dirname(os.path.abspath(__file__)) # указываем, что мы будем искать лица по примитивам Хаара detector = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # счётчик изображений i=0 # расстояния от распознанного лица до рамки offset=50 # запрашиваем номер пользователя name=input('Введите номер пользователя: ') # получаем доступ к камере video=cv2.VideoCapture(0)
Последнее, что осталось, — сделать цикл, который соберёт как минимум 30 фотографий, найдёт на них лица и запишет их файл с нужными именами. Так как примитивы Хаара — это чёрно-белые прямоугольники, для простоты и ускорения работы мы тоже будем переводить кадры в ч/б. Чтобы потом в процессе тренировки нейросети было проще, мы будем сохранять не кадр с камеры целиком, а только лицо:
# запускаем цикл while True: # берём видеопоток ret, im =video.read() # переводим всё в ч/б для простоты gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) # настраиваем параметры распознавания и получаем лицо с камеры faces=detector.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(100, 100)) # обрабатываем лица for(x,y,w,h) in faces: # увеличиваем счётчик кадров i=i+1 # записываем файл на диск cv2.imwrite("dataSet/face-"+name +'.'+ str(i) + ".jpg", gray[y-offset:y+h+offset,x-offset:x+w+offset]) # формируем размеры окна для вывода лица cv2.rectangle(im,(x-50,y-50),(x+w+50,y+h+50),(225,0,0),2) # показываем очередной кадр, который мы запомнили cv2.imshow('im',im[y-offset:y+h+offset,x-offset:x+w+offset]) # делаем паузу cv2.waitKey(100) # если у нас хватает кадров if i>30: # освобождаем камеру video.release() # удалаяем все созданные окна cv2.destroyAllWindows() # останавливаем цикл break
Сохраняем скрипт как face_gen.py — потому что для тренировки нам понадобится отдельный код. После запуска в терминале нужно будет ввести номер пользователя — им может быть любое число. Во время работы скрипт покажет нам 30 кадров, которые он сделал, а в папке dataSet появятся новые файлы — это значит, что мы всё сделали правильно:

Обучаем нейросеть
Создаём новый файл face_train.py — он будет отвечать за обучение на собранном датасете. Так как мы сами придумывали формат имени файла, то это сильно упростит нам задачу: цифра, которая стоит после дефиса и до первой точки, и будет id пользователя:
face-1.29.jpg ← здесь после дефиса и до первой точки стоит число 1, значит эта фотография относится к пользователю с >
Начало скрипта будет похоже на предыдущее, добавятся только две библиотеки — для обучения нейросети и для работы с изображениями:
# подключаем библиотеку компьютерного зрения import cv2 # библиотека для вызова системных функций import os # для обучения нейросетей import numpy as np # встроенная библиотека для работы с изображениями from PIL import Image # получаем путь к этому скрипту path = os.path.dirname(os.path.abspath(__file__)) # создаём новый распознаватель лиц recognizer = cv2.face.LBPHFaceRecognizer_create() # указываем, что мы будем искать лица по примитивам Хаара faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # путь к датасету с фотографиями пользователей dataPath = path+r'/dataSet'
Теперь самое интересное — собираем картинки и id пользователя из датасета. Для простоты id будем называть подписью — если у нас не будет сведений о том, что за человек на фотографиях, будем просто выводить номер пользователя как подпись.
Логика будет такая:
- Открываем папку с картинками.
- По очереди читаем каждую картинку и переводим её в специальный формат, с которым умеет работать библиотека numpy.
- Получаем id пользователя из имени файла — просто убираем всё до дефиса и после первой точки.
- Определяем лицо на картинке — это будет просто, потому что на картинках и так будут только лица.
- Добавляем лица в список лиц.
- Добавляем id пользователя в список пользователей
- Чтобы было видно, что скрипт работает, на долю секунды будем выводить на экран текущую картинку.
- На выходе получим список с лицами и идентификаторами пользователей, к которым они относятся.
Запишем это в виде кода на Python:
# получаем картинки и подписи из датасета def get_images_and_labels(datapath): # получаем путь к картинкам image_paths = [os.path.join(datapath, f) for f in os.listdir(datapath)] # списки картинок и подписей на старте пустые images = [] labels = [] # перебираем все картинки в датасете for image_path in image_paths: # читаем картинку и сразу переводим в ч/б image_pil = Image.open(image_path).convert('L') # переводим картинку в numpy-массив image = np.array(image_pil, 'uint8') # получаем id пользователя из имени файла nbr = int(os.path.split(image_path)[1].split(".")[0].replace("face-", "")) # определяем лицо на картинке faces = faceCascade.detectMultiScale(image) # если лицо найдено for (x, y, w, h) in faces: # добавляем его к списку картинок images.append(image[y: y + h, x: x + w]) # добавляем id пользователя в список подписей labels.append(nbr) # выводим текущую картинку на экран cv2.imshow("Adding faces to traning set. ", image[y: y + h, x: x + w]) # делаем паузу cv2.waitKey(100) # возвращаем список картинок и подписей return images, labels
Наконец, обучаем и сохраняем модель, чтобы её можно было использовать в других проектах. При этом нейросети неважно, сколько пользователей и фотографий будет в датасете — один или тысяча. Она запомнит их все, сопоставит одно с другим и запомнит, как выглядит пользователь под каждым номером. Результат такой обработки сохраним в yml-файле — это один из стандартных форматов для таких моделей:
# получаем список картинок и подписей
images, labels = get_images_and_labels(dataPath)
# обучаем модель распознавания на наших картинках и учим сопоставлять её лица и подписи к ним
recognizer.train(images, np.array(labels))
# сохраняем модель
recognizer.save(path+r’/trainer/trainer.yml’)
# удаляем из памяти все созданные окнаы
cv2.destroyAllWindows()
Если после запуска скрипта в папке trainer появился файл trainer.yml — поздравляем, вы только что обучили нейросеть распознавать лицо человека!
face_gen.py
# подключаем библиотеку машинного зрения import cv2 # библиотека для вызова системных функций import os # получаем путь к этому скрипту path = os.path.dirname(os.path.abspath(__file__)) # указываем, что мы будем искать лица по примитивам Хаара detector = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # счётчик изображений i=0 # расстояния от распознанного лица до рамки offset=50 # запрашиваем номер пользователя name=input('Введите номер пользователя: ') # получаем доступ к камере video=cv2.VideoCapture(0) # запускаем цикл while True: # берём видеопоток ret, im =video.read() # переводим всё в ч/б для простоты gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) # настраиваем параметры распознавания и получаем лицо с камеры faces=detector.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(100, 100)) # обрабатываем лица for(x,y,w,h) in faces: # увеличиваем счётчик кадров i=i+1 # записываем файл на диск cv2.imwrite("dataSet/face-"+name +'.'+ str(i) + ".jpg", gray[y-offset:y+h+offset,x-offset:x+w+offset]) # формируем размеры окна для вывода лица cv2.rectangle(im,(x-50,y-50),(x+w+50,y+h+50),(225,0,0),2) # показываем очередной кадр, который мы запомнили cv2.imshow('im',im[y-offset:y+h+offset,x-offset:x+w+offset]) # делаем паузу cv2.waitKey(100) # если у нас хватает кадров if i>30: # освобождаем камеру video.release() # удаляем все созданные окна cv2.destroyAllWindows() # останавливаем цикл break
face_train.py
# подключаем библиотеку компьютерного зрения import cv2 # библиотека для вызова системных функций import os # для обучения нейросетей import numpy as np # встроенная библиотека для работы с изображениями from PIL import Image # получаем путь к этому скрипту path = os.path.dirname(os.path.abspath(__file__)) # создаём новый распознаватель лиц recognizer = cv2.face.LBPHFaceRecognizer_create() # указываем, что мы будем искать лица по примитивам Хаара faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # путь к датасету с фотографиями пользователей dataPath = path+r'/dataSet' # получаем картинки и подписи из датасета def get_images_and_labels(datapath): # получаем путь к картинкам image_paths = [os.path.join(datapath, f) for f in os.listdir(datapath)] # списки картинок и подписей на старте пустые images = [] labels = [] # перебираем все картинки в датасете for image_path in image_paths: # читаем картинку и сразу переводим в ч/б image_pil = Image.open(image_path).convert('L') # переводим картинку в numpy-массив image = np.array(image_pil, 'uint8') # получаем id пользователя из имени файла nbr = int(os.path.split(image_path)[1].split(".")[0].replace("face-", "")) # определяем лицо на картинке faces = faceCascade.detectMultiScale(image) # если лицо найдено for (x, y, w, h) in faces: # добавляем его к списку картинок images.append(image[y: y + h, x: x + w]) # добавляем id пользователя в список подписей labels.append(nbr) # выводим текущую картинку на экран cv2.imshow("Adding faces to traning set. ", image[y: y + h, x: x + w]) # делаем паузу cv2.waitKey(100) # возвращаем список картинок и подписей return images, labels # получаем список картинок и подписей images, labels = get_images_and_labels(dataPath) # обучаем модель распознавания на наших картинках и учим сопоставлять её лица и подписи к ним recognizer.train(images, np.array(labels)) # сохраняем модель recognizer.save(path+r'/trainer/trainer.yml') # удаляем из памяти все созданные окнаы cv2.destroyAllWindows()
Что дальше
Теперь у нас всё готово для того, чтобы мы добавили новую модель в скрипт распознавания лиц. Сделаем это в следующий раз и посмотрим, как нейросеть справляется с этой задачей.
Любите данные? Посмотрите вот это
Возможно, у вас получится построить карьеру в мире дата-сайенса. Это новое направление, в котором очень нужны люди. Изучите эту сферу и начните карьеру в ИТ: старт — бесплатно, а после обучения — помощь с трудоустройством.

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.