Иметь дело с этим это мем, где стекла летают с экрана, а на лицо пользователя. Лучшие экземпляры этого мема делают это уникально.
Сегодня мы напишем автоматический генератор MEME, используя любое статическое изображение с лицами в качестве нашего ввода. Этот код делает отличную отправную точку для MEME API или создание собственной анимированной версии с помощью видеовхода.
Я получил идею для этого поста от Эрик Тари и его в браузере JavaScript версия из этого эффекта.
В конце статьи в качестве бонуса я также включал версию, в которой эффект может быть сделан в режиме реального времени из веб-камеры, используя OpenCV.
Инструменты обнаружения лица и создания GIF
Мы будем использовать DLIB get_frontal_face_detector
вместе с Модель прогнозирования формы 68 точек Мы использовали в Линз Snapchat статья.
Наша программа примет аргумент командной строки, входное изображение. Затем он будет использовать алгоритм обнаружения лица в DLIB, чтобы увидеть, есть ли какие-либо лица. Если есть, он создаст конечное положение для каждого лица, где очки должны в конечном итоге.
Нам нужно будет затем масштабировать и повернуть наши очки, чтобы соответствовать лицу каждого человека. Мы будем использовать набор очков, возвращаемых из модели 68 точек DLIB, чтобы найти центр массы для глаз, и вращение для пространства между ними.
После того, как мы нашли конечную позицию и вращение для очков, мы можем затем оживить GIF, со стеклами, идущими от верхней части экрана. Мы нарисуем это с помощью Movelpy и A make_frame
функция.
Архитектура автоматических GIFS
Архитектура приложения довольно проста. Сначала мы предпринимаем изображение, а затем преобразуйте его в серого на массиве Numpy. После того, как мы получим это, мы можем пройти наши обнаруженные лица в нашу модель прогнозирования ориентации лица.
С возвращенной ориентацией лица мы можем затем выбирать глаза и масштабировать и повернуть наши очки кадров, чтобы соответствовать лицему.
Мы можем накапливать набор граней и их окончательные позиции, добавляя их в список.
Наконец, с этим списком мы можем затем создать рутину рисования, используя MoviePy, который затем генерирует наш анимированный GIF.
Написание кода
С нашей архитектурой кода запланировано, следующее, что нам нужно сделать, это построить наш код шаг за шагом.
Сначала мы импортируем все наши инструменты и принимаем изображение из командной строки:
import dlib from PIL import Image import argparse from imutils import face_utils import numpy as np import moviepy.editor as mpy parser = argparse.ArgumentParser() parser.add_argument("-image", required=True, help="path to input image") args = parser.parse_args()
С этим на месте мы можем затем изменить размер наших изображений, чтобы соответствовать меньшей ширине, поэтому наши GIFS не оказываются массивными и импортируют наше детектор для лица и предикторов формы.
Мы также можем открыть очки и текст, мы будем вставлять на наш образ.
На данный момент мы также должны обнаруживать, обнаружены ли даже какие-либо лица, обнаруженные на изображении. Если нет, мы должны немедленно выйти.
detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor('shape_predictor_68.dat') # resize to a max_width to keep gif size small max_width = 500 # open our image, convert to rgba img = Image.open(args.image).convert('RGBA') # two images we'll need, glasses and deal with it text deal = Image.open("deals.png") text = Image.open('text.png') if img.size[0] > max_width: scaled_height = int(max_width * img.size[1] / img.size[0]) img.thumbnail((max_width, scaled_height)) img_gray = np.array(img.convert('L')) # need grayscale for dlib face detection rects = detector(img_gray, 0) if len(rects) == 0: print("No faces found, exiting.") exit() print("%i faces found in source image. processing into gif now." % len(rects))
Здорово! Теперь мы можем закрутить каждый из обнаруженных граней и создать список масштабированных и повернутых очков вместе с их конечными позициями.
faces = [] for rect in rects: face = {} print(rect.top(), rect.right(), rect.bottom(), rect.left()) shades_width = rect.right() - rect.left() # predictor used to detect orientation in place where current face is shape = predictor(img_gray, rect) shape = face_utils.shape_to_np(shape) # grab the outlines of each eye from the input image leftEye = shape[36:42] rightEye = shape[42:48] # compute the center of mass for each eye leftEyeCenter = leftEye.mean(axis=0).astype("int") rightEyeCenter = rightEye.mean(axis=0).astype("int") # compute the angle between the eye centroids dY = leftEyeCenter[1] - rightEyeCenter[1] dX = leftEyeCenter[0] - rightEyeCenter[0] angle = np.rad2deg(np.arctan2(dY, dX)) # resize glasses to fit face width current_deal = deal.resize((shades_width, int(shades_width * deal.size[1] / deal.size[0])), resample=Image.LANCZOS) # rotate and flip to fit eye centers current_deal = current_deal.rotate(angle, expand=True) current_deal = current_deal.transpose(Image.FLIP_TOP_BOTTOM) # add the scaled image to a list, shift the final position to the # left of the leftmost eye face['glasses_image'] = current_deal left_eye_x = leftEye[0,0] - shades_width // 4 left_eye_y = leftEye[0,1] - shades_width // 6 face['final_pos'] = (left_eye_x, left_eye_y) faces.append(face)
С нашими заключительными позициями на месте вместе с нашими масштабированными и повернутыми стеклами мы можем затем собрать наш фильм. Мы установим продолжительность всего GIF, а также время остановки очков, поэтому мы можем поставить сделку с ним текст на экране.
# how long our gif should be duration = 4 def make_frame(t): draw_img = img.convert('RGBA') # returns copy of original image if t == 0: # no glasses first image return np.asarray(draw_img) for face in faces: if t <= duration - 2: # leave 2 seconds for text current_x = int(face['final_pos'][0]) # start from proper x current_y = int(face['final_pos'][1] * t / (duration - 2)) # move to position w/ 2 secs to spare draw_img.paste(face['glasses_image'], (current_x, current_y) , face['glasses_image']) else: # draw the text for last 2 seconds draw_img.paste(face['glasses_image'], face['final_pos'], face['glasses_image']) draw_img.paste(text, (75, draw_img.height // 2 - 32), text) return np.asarray(draw_img)
Вы заметите, что использовал изображение для наложения текста, а не подушенные функции рисования текста. Я сделал это, потому что подушка не имеет встроенной функции инсульта для текста. Без инсульта текст становится неразборчивым на ярких изображениях.
Наконец, нам нужно создать Видеоклип
Объект в Movelpy и пропустите в нашей анимационной раме вместе с FPS.
animation = mpy.VideoClip(make_frame, duration=duration) animation.write_gif("deal.gif", fps=4)
С этим мы закончили!
Анимация мем в реальном времени
Теперь, когда у нас есть база для генерации наших GIFS, не слишком сложно адаптировать наш код для работы с веб-камерой в режиме реального времени.
Вместо загрузки нашего исходного изображения из командной строки мы можем использовать OpenCV в качестве наших исходных изображений и отслеживать анимацию с счетчиком. Новый код для этого довольно просто, реальное мясо:
# I got lazy, didn't want to bother with transparent pngs in opencv # this is probably slower than it should be if dealing: if current_animation < glasses_on: current_y = int(current_animation / glasses_on * left_eye_y) img.paste(current_deal, (left_eye_x, current_y), current_deal) else: img.paste(current_deal, (left_eye_x, left_eye_y), current_deal) img.paste(text, (75, img.height // 2 - 32), text) if dealing: current_animation += 1 if current_animation > animation_length: dealing = False current_animation = 0 else: frame = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR) cv2.imshow("deal generator", frame) key = cv2.waitKey(1) & 0xFF if key == ord("q"): break if key == ord("d"): dealing = not dealing
Это создает счетчик и шаги через несколько кадров прогрессировали, чтобы отслеживать время. Используя это, мы можем затем оживить наши очки в их окончательную позицию. Мы видим, нажимает ли пользователь D
Ключ, чтобы дело с этим, и когда они делаем, мы начинаем нашу анимацию.
Вы можете прочитать остаток кода для этого на Github Отказ
Куда пойти отсюда
Мы успешно построили самую первую часть в программе, которая может быть использована в качестве API для автоматического генерации MEMES.
Подключая нашу программу к чему-то вроде колбы, мы могли бы отобразить веб-страницу, позволяющую пользователям загружать свои собственные изображения и вернуться полностью завершенные мемы.
Что касается чего-то вроде YouTube-DL, у нас могут быть вставки пользователей в видео URL YouTube, чтобы автоматически генерировать MEMES.
Если вы пропустили его, код доступен в Github Отказ
Если вы заинтересованы в таких как эти проекты, пожалуйста, зарегистрируйтесь учетной записи на Сделать искусство с Python Отказ Вы получите первые три главы моей новой книги, когда вы делаете, и вы поможете мне продолжать делать такие проекты.
Оригинал: “https://dev.to/burningion/deal-with-it-in-python-with-face-detection-chi”