Автор оригинала: Guest Contributor.
Вступление
Распознавание лиц-это мощный и распространенный метод машинного обучения. Он может быть использован для автоматизации ручных задач, таких как посещение школы и правоохранительные органы. С другой стороны, его можно использовать для биометрической авторизации.
В этой статье мы будем выполнять распознавание лиц в Python с помощью OpenCV.
OpenCV
OpenCV-одна из самых популярных библиотек компьютерного зрения. Он был написан на C и C++, а также обеспечивает поддержку Python, помимо Java и MATLAB. Хотя это не самая быстрая библиотека, с ней легко работать и она обеспечивает высокоуровневый интерфейс, позволяющий разработчикам писать стабильный код.
Давайте установим OpenCV, чтобы мы могли использовать его в нашем коде Python:
$ pip install opencv-contrib-python
Кроме того, вы можете установить opencv-python
только для основных модулей OpenCV. opencv-contrib-python
содержит основные модули, а также модули contrib , которые обеспечивают расширенную функциональность.
Обнаружение лиц на изображении с помощью OpenCV
С установленным OpenCV мы можем импортировать его как cv2
в наш код.
Чтобы прочитать изображение, мы будем использовать функцию imread()
вместе с путем к изображению, которое мы хотим обработать. Функция imread()
просто загружает изображение из указанного файла в ndarray
. Если изображение не удалось прочитать, например, в случае отсутствия файла или неподдерживаемого формата, функция вернет None
.
Мы будем использовать изображение из набора данных Kaggle :
import cv2 path_to_image = 'Parade_12.jpg' original_image = cv2.imread(path_to_image)
Полная информация RGB не нужна для распознавания лиц. Цвет содержит много несущественной информации на изображении, поэтому более эффективно просто удалить его и работать с изображением в оттенках серого. Кроме того, алгоритм Виолы-Джонса, который работает под капотом с OpenCV, проверяет разницу в интенсивности области изображения. Изображения в оттенках серого указывают на эту разницу более резко.
Примечание: В случае цветных изображений декодированные изображения будут иметь каналы, сохраненные в порядке BGR, поэтому при изменении их на оттенки серого нам нужно использовать флаг cv2.COLOR_BGR2GRAY
:
image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
Это можно было бы сделать непосредственно при использовании imread()
, установив флаг cv2.IMREAD_GRAYSCALE
:
original_image = cv2.imread(path_to_image, cv2.IMREAD_GRAYSCALE)
Библиотека OpenCV поставляется с несколькими предварительно обученными классификаторами, которые обучены находить различные вещи, такие как лица, глаза, улыбки, верхняя часть тела и т. Д.
Функции Haar для обнаружения этих объектов хранятся в формате XML и, в зависимости от того, как вы установили OpenCV, чаще всего можно найти в файле Lib\site-packages\cv2\data
. Их также можно найти в репозитории OpenCV GitHub .
Чтобы получить доступ к ним из кода, вы можете использовать файл cv2.data.haarcascades
и добавить имя XML-файла, который вы хотите использовать.
Мы можем выбрать, какие функции Haar мы хотим использовать для обнаружения объектов, добавив путь к файлу в конструктор CascadeClassifier ()
, который использует предварительно обученные модели для обнаружения объектов:
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
Теперь мы можем использовать этот объект face_cascade
для обнаружения лиц на изображении:
detected_faces = face_cascade.detectMultiScale(image=image, scaleFactor=1.3, minNeighbors=4)
Когда модели обнаружения объектов обучаются, они обучаются обнаруживать лица определенного размера и могут пропустить лица, которые больше или меньше, чем они ожидают. Имея это в виду, изображение изменяется несколько раз в надежде, что лицо в конечном итоге будет “обнаруживаемым” размером. Масштабный коэффициент позволяет OpenCV знать, насколько масштабировать изображения. В нашем случае
1.3 это означает, что он может масштабироваться
на 30% вниз, чтобы попытаться лучше соответствовать граням.
Что касается параметра minNeighbors
, то он используется для управления количеством ложных срабатываний и ложных негативов. Он определяет минимальное количество положительных прямоугольников (обнаруживает черты лица), которые должны быть смежны с положительным прямоугольником, чтобы он считался действительно положительным. Если minNeighbors
имеет значение 0
, малейший намек на лицо будет считаться окончательным лицом, даже если рядом с ним не будет обнаружено никаких других черт лица.
Оба параметра масштабный коэффициент
и minNeighbors
несколько произвольны и установлены экспериментально. Мы выбрали ценности, которые хорошо работали для нас и не давали ложных срабатываний, с компромиссом большего количества ложных негативов (незамеченных лиц).
Метод detectMultiScale()
возвращает список прямоугольников всех обнаруженных объектов (граней в нашем первом случае). Каждый элемент в списке представляет собой уникальное лицо. Этот список содержит кортежи (x, y, w, h)
, где значения x, y
представляют верхние левые координаты прямоугольника, а значения w, h
представляют ширину и высоту прямоугольника соответственно.
Мы можем использовать возвращенный список прямоугольников и использовать функцию cv2.rectangle ()
, чтобы легко нарисовать прямоугольники, в которых была обнаружена грань. Имейте в виду, что предоставленный цвет должен быть кортежем в порядке RGB:
for (x, y, width, height) in detected_faces: cv2.rectangle( image, (x, y), (x + width, y + height), color, thickness=2 )
А теперь давайте сложим все это вместе:
import cv2 def draw_found_faces(detected, image, color: tuple): for (x, y, width, height) in detected: cv2.rectangle( image, (x, y), (x + width, y + height), color, thickness=2 ) path_to_image = 'Parade_12.jpg' original_image = cv2.imread(path_to_image) if original_image is not None: # Convert image to grayscale image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) # Create Cascade Classifiers face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") profile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_profileface.xml") # Detect faces using the classifiers detected_faces = face_cascade.detectMultiScale(image=image, scaleFactor=1.3, minNeighbors=4) detected_profiles = profile_cascade.detectMultiScale(image=image, scaleFactor=1.3, minNeighbors=4) # Filter out profiles profiles_not_faces = [x for x in detected_profiles if x not in detected_faces] # Draw rectangles around faces on the original, colored image draw_found_faces(detected_faces, original_image, (0, 255, 0)) # RGB - green draw_found_faces(detected_profiles, original_image, (0, 0, 255)) # RGB - red # Open a window to display the results cv2.imshow(f'Detected Faces in {path_to_image}', original_image) # The window will close as soon as any key is pressed (not a mouse click) cv2.waitKey(0) cv2.destroyAllWindows() else: print(f'En error occurred while trying to load {path_to_image}')
На этом снимке мы использовали две разные модели. Модель по умолчанию для обнаружения лиц, обращенных вперед, и модель, построенная для лучшего обнаружения лиц, смотрящих в сторону.
Лица, обнаруженные с помощью модели frontal face
, обведены зеленым цветом, а лица, обнаруженные с помощью модели profile face
, обведены красным. Большинство лиц, найденных первой моделью, также были бы найдены второй, поэтому мы рисовали только красные прямоугольники, где модель profileface
обнаружила лицо, но frontalface
этого не сделала:
profiles_not_faces = [x for x in detected_profiles if x not in detected_faces]
Метод imshow()
просто показывает переданное изображение в окне с предоставленным заголовком. С изображением, которое мы выбрали, это дало бы следующий результат:
Использование различных значений для масштабного коэффициента
и minNeighbors
даст нам разные результаты. Например, используя масштабный коэффициент.1
и minNeighbors
дает нам больше ложных срабатываний и истинных срабатываний с обеими моделями:
Мы видим, что алгоритм не идеален, но он очень эффективен. Это особенно заметно при работе с данными реального времени, такими как видеопоток с веб-камеры.
Распознавание лиц в реальном времени С помощью веб-камеры
Видеопотоки-это просто потоки изображений. С эффективностью алгоритма Виола-Джонс мы можем делать распознавание лиц в режиме реального времени.
Шаги, которые нам нужно предпринять, очень похожи на предыдущий пример только с одним изображением – мы будем выполнять это на каждом изображении в потоке.
Чтобы получить видеопоток, мы будем использовать класс cv2.VideoCapture
. Конструктор для этого класса принимает целочисленный параметр, представляющий видеопоток. На большинстве машин доступ к веб-камере можно получить, пройдя мимо 0
, но на машинах с несколькими видеопотоками вам может потребоваться попробовать разные значения.
Далее нам нужно прочитать отдельные изображения из входного потока. Это делается с помощью функции read ()
, которая возвращает retval
и image
. изображение
– это просто извлеченный кадр. Возвращаемое значение retval
используется для определения того, был ли получен кадр или нет, и будет False
, если это не так.
Однако он имеет тенденцию быть несовместимым с потоками видеовхода (например, не обнаруживает, что веб-камера была отключена), поэтому мы будем игнорировать это значение.
Давайте продолжим и изменим предыдущий код для обработки видеопотока:
import cv2 def draw_found_faces(detected, image, color: tuple): for (x, y, width, height) in detected: cv2.rectangle( image, (x, y), (x + width, y + height), color, thickness=2 ) # Capturing the Video Stream video_capture = cv2.VideoCapture(0) # Creating the cascade objects face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye_tree_eyeglasses.xml") while True: # Get individual frame _, frame = video_capture.read() # Covert the frame to grayscale grayscale_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Detect all the faces in that frame detected_faces = face_cascade.detectMultiScale(image=grayscale_image, scaleFactor=1.3, minNeighbors=4) detected_eyes = eye_cascade.detectMultiScale(image=grayscale_image, scaleFactor=1.3, minNeighbors=4) draw_found_faces(detected_faces, frame, (0, 0, 255)) draw_found_faces(detected_eyes, frame, (0, 255, 0)) # Display the updated frame as a video stream cv2.imshow('Webcam Face Detection', frame) # Press the ESC key to exit the loop # 27 is the code for the ESC key if cv2.waitKey(1) == 27: break # Releasing the webcam resource video_capture.release() # Destroy the window that was showing the video stream cv2.destroyAllWindows()
Вывод
В этой статье мы создали приложение для распознавания лиц с использованием Python и OpenCV.
Использование библиотеки OpenCV очень просто для базовых программ обнаружения объектов. Экспериментальная настройка масштабного коэффициента
и minNeighbors
параметров для типов изображений, которые вы хотите обработать, может дать довольно точные результаты очень эффективно.