Если вы являетесь постоянным пользователем Google Фото, вы, возможно, заметили, как приложение автоматически извлекает и группирует лица людей из фотографий, которые вы копируете в облако.
Приложение для обработки фотографий, такое как Google, достигает этого путем обнаружения на фотографиях лиц людей (и домашних животных тоже!), А затем группирует похожие лица. Обнаружение, а затем классификация лиц на изображениях — обычная задача глубокого обучения с использованием нейронных сетей.
На первом этапе этого урока мы будем использовать предварительно обученную модель MTCNN в Керасе для обнаружения лиц на изображениях. После того как мы извлекли лица из изображения, мы вычислим показатель сходства между этими лицами, чтобы определить, принадлежат ли они одному человеку.
Предпосылки
Прежде чем вы начнете распознавать и распознавать лица, вам необходимо настроить среду разработки. Во-первых, вам нужно «прочитать» изображения через Python, прежде чем выполнять какую-либо обработку. Мы будем использовать библиотеку графиков matplotlib
для чтения и управления изображениями. Установите последнюю версию через pip
:
pip3 install matplotlib
Чтобы использовать любую реализацию алгоритма CNN, вам нужно установить keras
. Загрузите и установите последнюю версию, используя команду ниже:
pip3 install keras
Алгоритм, который мы будем использовать для обнаружения лица, — это MTCNN (многозадачные извилистые нейронные сети), основанный на статье « Совместное обнаружение и выравнивание лиц с использованием многозадачных каскадных сверточных сетей» (Zhang et al., 2016). Реализация алгоритма MTCNN для TensorFlow в Python3.4 доступна в виде пакета . Выполните следующую команду, чтобы установить пакет через pip
:
pip3 install mtcnn
Чтобы сравнить лица после извлечения их из изображений, мы будем использовать алгоритм VGGFace2, разработанный Группой визуальной геометрии в Оксфордском университете. Реализация алгоритма VGG на основе TensorFlow Keras доступна в виде пакета для установки:
pip3 install keras_vggface
Хотя вы можете почувствовать необходимость создания и обучения своей собственной модели, вам понадобится огромный набор данных для обучения и огромные вычислительные мощности. Поскольку данное руководство фокусируется на полезности этих моделей, в нем используются существующие обученные модели, разработанные экспертами в данной области.
Теперь, когда вы успешно установили необходимые компоненты, давайте сразу же перейдем к учебнику!
Шаг 1: Обнаружение лица с моделью MTCNN
Цели на этом этапе следующие:
- извлекать изображения, размещенные на локальном сервере
- читать изображения через
matplotlib
imread()
- обнаруживать и исследовать лица с помощью алгоритма MTCNN
- извлекать лица из изображения.
1.1 Хранить внешние изображения
Вы можете часто делать анализ изображений, размещенных на внешних серверах. Для этого примера мы будем использовать два изображения Ли Якокки, отца Мустанга, размещенного на сайтах BBC и The Detroit News .
Чтобы временно сохранить изображения для нашего анализа, мы извлечем каждое из его URL и запишем его в локальный файл. Для этого определим функцию store_image
:
import urllib.request def store_image(url, local_file_name): with urllib.request.urlopen(url) as resource: with open(local_file_name, 'wb') as f: f.write(resource.read())
Теперь вы можете просто вызвать функцию с URL-адресом и локальным файлом, в котором вы хотите сохранить изображение:
store_image('https://ichef.bbci.co.uk/news/320/cpsprodpb/5944/production/_107725822_55fd57ad-c509-4335-a7d2-bcc86e32be72.jpg', 'iacocca_1.jpg') store_image('https://www.gannett-cdn.com/presto/2019/07/03/PDTN/205798e7-9555-4245-99e1-fd300c50ce85-AP_080910055617.jpg?width=540&height=&fit=bounds&auto=webp', 'iacocca_2.jpg')
После успешного получения изображений, давайте обнаружим лица на них.
1.2 Обнаружение лиц на изображении
Для этого мы сделаем два импорта — matplotlib
для чтения изображений и mtcnn
для обнаружения лиц в изображениях:
from matplotlib import pyplot as plt from mtcnn.mtcnn import MTCNN
Используйте imread()
чтобы прочитать изображение:
image = plt.imread('iacocca_1.jpg')
Затем инициализируйте объект MTCNN()
в переменной detector
и используйте метод .detect_faces()
для обнаружения лиц на изображении. Давайте посмотрим, что он возвращает:
detector = MTCNN() faces = detector.detect_faces(image) for face in faces: print(face)
Для каждого лица возвращается словарь Python, который содержит три ключа. Ключ box
содержит границу лица на изображении. Он имеет четыре значения: x- и y-координаты верхней левой вершины, ширина и высота прямоугольника, содержащего грань. Другие ключи — это confidence
и keypoints
. Ключ keypoints
содержит словарь, содержащий обнаруженные черты лица и их координаты:
{'box': [160, 40, 35, 44], 'confidence': 0.9999798536300659, 'keypoints': {'left_eye': (172, 57), 'right_eye': (188, 57), 'nose': (182, 64), 'mouth_left': (173, 73), 'mouth_right': (187, 73)}}
1.3 Выделите лица на изображении
Теперь, когда мы успешно определили лицо, давайте нарисуем прямоугольник над ним, чтобы выделить лицо на изображении, чтобы убедиться, что обнаружение было правильным.
Чтобы нарисовать прямоугольник, импортируйте объект Rectangle
из matplotlib.patches
:
from matplotlib.patches import Rectangle
Давайте определим функцию highlight_faces
чтобы сначала отобразить изображение, а затем нарисовать прямоугольники поверх обнаруженных лиц. Сначала прочитайте изображение через imread()
и imshow()
его через imshow()
. Для каждого обнаруженного лица нарисуйте прямоугольник с помощью класса Rectangle()
.
Наконец, отобразите изображение и прямоугольники с помощью .show()
. Если вы используете записные книжки Jupyter, вы можете использовать команду %matplotlib inline
magic, чтобы отобразить графики inline:
def highlight_faces(image_path, faces): # display image image = plt.imread(image_path) plt.imshow(image) ax = plt.gca() # for each face, draw a rectangle based on coordinates for face in faces: x, y, width, height = face['box'] face_border = Rectangle((x, y), width, height, fill=False, color='red') ax.add_patch(face_border) plt.show()
Теперь давайте отобразим изображение и обнаруженное лицо с помощью функции highlight_faces()
:
highlight_faces('iacocca_1.jpg', faces)
Давайте покажем второе изображение и лица, обнаруженные в нем:
image = plt.imread('iacocca_2.jpg') faces = detector.detect_faces(image) highlight_faces('iacocca_2.jpg', faces)
На этих двух изображениях видно, что алгоритм MTCNN правильно распознает лица. Давайте теперь извлечем это лицо из изображения, чтобы выполнить дальнейший анализ на нем.
1.4 Извлечь лицо для дальнейшего анализа
На данный момент вы знаете координаты лица от детектора. Извлечение лиц — довольно простая задача с использованием индексов списка. Однако используемый нами алгоритм VGGFace2 требует изменения размеров граней до 224 x 224 пикселей. Мы будем использовать библиотеку PIL для изменения размера изображений.
Функция extract_face_from_image()
извлекает все лица из изображения:
from numpy import asarray from PIL import Image def extract_face_from_image(image_path, required_size=(224, 224)): # load image and detect faces image = plt.imread(image_path) detector = MTCNN() faces = detector.detect_faces(image) face_images = [] for face in faces: # extract the bounding box from the requested face x1, y1, width, height = face['box'] x2, y2 = x1 + width, y1 + height # extract the face face_boundary = image[y1:y2, x1:x2] # resize pixels to the model size face_image = Image.fromarray(face_boundary) face_image = face_image.resize(required_size) face_array = asarray(face_image) face_images.append(face_array) return face_images extracted_face = extract_face_from_image('iacocca_1.jpg') # Display the first face from the extracted faces plt.imshow(extracted_face[0]) plt.show()
Вот как выглядит извлеченное лицо из первого изображения.
Шаг 2: Распознавание лиц с моделью VGGFace2
В этом разделе давайте сначала проверим модель на двух изображениях Ли Якокки, которые мы получили. Затем мы перейдем к сравнению лиц по изображениям стартовых одиннадцати футбольной команды «Челси» в 2018 и 2019 годах. После этого вы сможете оценить, распознает ли алгоритм лица общих игроков между изображениями.
2.1 Сравнить два лица
В этом разделе вам необходимо импортировать три модуля: VGGFace
для подготовки извлеченных граней для использования в моделях распознавания лиц и функцию cosine
из SciPy для вычисления расстояния между двумя гранями:
from keras_vggface.utils import preprocess_input from keras_vggface.vggface import VGGFace from scipy.spatial.distance import cosine
Давайте определим функцию, которая принимает извлеченные грани в качестве входных данных и возвращает вычисленные оценки модели. Модель возвращает вектор, который представляет особенности лица:
def get_model_scores(faces): samples = asarray(faces, 'float32') # prepare the data for the model samples = preprocess_input(samples, version=2) # create a vggface model object model = VGGFace(model='resnet50', include_top=False, input_shape=(224, 224, 3), pooling='avg') # perform prediction return model.predict(samples) faces = [extract_face_from_image(image_path) for image_path in ['iacocca_1.jpg', 'iacocca_2.jpg']] model_scores = get_model_scores(faces)
Поскольку оценки моделей для каждого лица являются векторами, нам необходимо найти сходство между оценками двух лиц. Обычно мы можем использовать евклидову или косинусную функцию для вычисления подобия.
Векторное представление граней соответствует косинусному подобию. Вот подробное сравнение косинусных и евклидовых расстояний с примером .
Функция cosine()
вычисляет косинусное расстояние между двумя векторами. Чем ниже это число, тем лучше совпадают ваши лица. В нашем случае мы установим порог на 0.4
расстояния. Этот порог является спорным и будет варьироваться в зависимости от вашего варианта использования. Вы должны установить этот порог, основываясь на тематических исследованиях в вашем наборе данных:
if cosine(model_scores[0], model_scores[1]) <= 0.4: print("Faces Matched")
В этом случае два лица Ли Якокки совпали.
Faces Matched
2.2 Сравнить несколько лиц в двух изображениях
Давайте хорошо применим модель в этом разделе руководства. Мы сравним лица на двух изображениях стартовых одиннадцати футбольного клуба «Челси» в матче Лиги Европы против «Славии» в сезоне 2018–1919 годов и в матче за Суперкубок УЕФА против «Ливерпуля» в сезоне 2019–20. В то время как многие игроки участвуют в составах обоих игровых дней, давайте посмотрим, сможет ли алгоритм обнаружить всех обычных игроков.
Во-первых, давайте извлечем ресурсы из URL, определим лица на каждом изображении и выделим их:
store_image('https://cdn.vox-cdn.com/thumbor/Ua2BXGAhneJHLQmLvj-ZzILK-Xs=/0x0:4872x3160/1820x1213/filters:focal(1877x860:2655x1638):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/63613936/1143553317.jpg.5.jpg', 'chelsea_1.jpg') image = plt.imread('chelsea_1.jpg') faces_staring_xi = detector.detect_faces(image) highlight_faces('chelsea_1.jpg', faces_staring_xi) store_image('https://cdn.vox-cdn.com/thumbor/mT3JHQtZIyInU8_uGxVH-TCbF50=/0x415:5000x2794/1820x1213/filters:focal(1878x1176:2678x1976):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/65171515/1161847141.jpg.0.jpg', 'chelsea_2.jpg') image = plt.imread('chelsea_2.jpg') faces = detector.detect_faces(image) highlight_faces('chelsea_2.jpg', faces)
Прежде чем мы продолжим, вот стартовые одиннадцать из обоих матчей:
- Пражский матч «Славия». Начало XI : Кепа, Аспиликуэта, Луис, Кристенсен, Эмерсон, Канте, Баркли, Ковачич, Хазард, Педро, Жиру
- Матч «Ливерпуль» Начиная с XI : Кепа, Аспиликуэта, Кристенсен, Зума, Эмерсон, Канте, Жорджинью, Ковачич, Педро, Жиру, Пулишич
У нас есть восемь игроков, которые являются общими для обоих стартовых XI и которые в идеале должны соответствовать алгоритму.
Давайте сначала подсчитаем баллы:
slavia_faces = extract_face_from_image('chelsea_1.jpg') liverpool_faces = extract_face_from_image('chelsea_2.jpg') model_scores_starting_xi_slavia = get_model_scores(slavia_faces) model_scores_starting_xi_liverpool = get_model_scores(liverpool_faces) `` for idx, face_score_1 in enumerate(model_scores_starting_xi_slavia): for idy, face_score_2 in enumerate(model_scores_starting_xi_liverpool): score = cosine(face_score_1, face_score_2) if score <= 0.4: # Printing the IDs of faces and score print(idx, idy, score) # Displaying each matched pair of faces plt.imshow(slavia_faces[idx]) plt.show() plt.imshow(liverpool_faces[idy]) plt.show()
Вот список пар граней, которым соответствует алгоритм. Обратите внимание, что ему удалось сопоставить все восемь пар лиц.
В то время как мы успешно смогли сопоставить каждое лицо на наших изображениях, я хотел бы сделать шаг назад, чтобы обсудить последствия оценки. Как обсуждалось ранее, не существует универсального порога, который бы соответствовал двум изображениям вместе. Возможно, вам придется пересмотреть эти пороговые значения с новыми данными, поступающими в анализ. Например, даже Google Фото принимает ваши данные, когда не может программно определить наилучший порог для пары.
Наилучший способ продвижения вперед — тщательно оценить случаи совпадения лиц разных типов. Эмоции лиц и их углы также играют роль в определении точности. В нашем случае, обратите внимание, как я сознательно использовал фотографии стартовых одиннадцати, когда игроки смотрят прямо в камеру! Вы можете попытаться сопоставить начальные одиннадцать лиц с лицами, отмеченными на трофеях, и я почти уверен, что точность упадет.
Вывод
В этом руководстве мы сначала обнаружили лица на изображениях, используя модель MTCNN, и выделили их на изображениях, чтобы определить, правильно ли работает модель. Затем мы использовали алгоритм VGGFace2 для извлечения объектов из граней в форме вектора и сопоставления различных граней для их группировки.
Используете ли вы другой алгоритм для обнаружения и сопоставления лиц? Дайте мне знать в Твиттере !