用AI人脸识别技术实现抖音特效

640?wx_fmt=gif


李远君 ,Web和云计算开发人员。Java,Python,Golang爱好者。

个人网址:https://tomoncle.com

本文作者已加入Python中文社区专栏作者计划

导言

  • 为什么会写这个人脸例子?


浏览博客的过程,无意发现了一篇名为deal-with-it-generator-face-recognition的文章,通过这篇文章,使我有了写这个例子的想法,尤其是现在很多短视频APP中经常出现这样的效果,感觉还是有点好玩的。


  • 感谢!

写这个例子初衷与资料来自burningion的分享。


  • 变化?

deal-with-it-generator-face-recognition 这篇文章是一个戴眼镜的简单例子及构思,我在其原基础上,添加了烟卷的部分,并且把代码结构重构了一下,使其更易拓展和维护,也易于阅读。

实现流程

程序从命令行参数获取图片信息,然后,它将使用Dlib中的人脸检测算法来查看是否有人脸存在。如果有,它将为每个人脸创建一个结束位置,眼镜和烟卷会移动到那里结束。


然后我们需要缩放和旋转我们的眼镜以适合每个人的脸。我们将使用从Dlib的68点模型返回的点集来找到眼睛的中心,并为它们之间的空间旋转。


在我们找到眼镜的最终位置和旋转后,我们可以为gif制作动画,眼镜从屏幕顶部进入。我们将使用MoviePy和一个make_frame函数绘制它。


同理烟卷也是这样。


应用程序的体系结构非常简单。我们首先接收图片,然后将其转换为灰度NumPy数组。假如没有人脸,程序会自己退出,如果存在,我们就可以将检测到的人脸信息传递到人脸方向预测模型中。


通过返回的脸部方向,我们可以选择眼睛,缩放和旋转我们的眼镜框架以适合人的面部大小。


当然这个程序不仅仅只针对于一张人脸,可以检测多个人脸信息。


最后,通过获取的人脸列表,我们可以使用MoviePy创建一个绘图,然后生成我们的动画gif。


  • 导入对应的工具包


import moviepy.editor as mpy
import numpy as np
from PIL import Image
from imutils import face_utils

try:
    from dlib import get_frontal_face_detector, shape_predictor
except ImportError:
    raise


  • 创建人脸识别的工具类FaceDetect及其对应的方法


class FaceDetect(object):
    pass


  • 创建detectorpredictor两个属性,用来加载dlib库函数


@property
def detector(self):
    """
    检测是否有人脸
    :return:
    """

    return get_frontal_face_detector()

@property
def predictor(self):
    """
    预测人脸方向
    :return:
    """

    return shape_predictor('shape_predictor_68_face_landmarks.dat')


  • 创建init_mask函数,用来加载面具信息(墨镜,烟卷等信息)


@classmethod
def load(cls, img_src):
    """
    加载图片转为Image对象
    :param img_src:
    :return:
    """

    return Image.open(img_src)


def init_mask(self):
    """
    加载面具
    :return:
    """

    self.deal, self.text, self.cigarette = (
    self.load(x) for x in ["../images/deals.png""../images/text.png""../images/cigarette.png"]
    )


  • 创建收集人脸信息的对应方法

首先get_glasses_info方法会根据当前人脸的特征值及图片基础设置,对图片中人脸进行面部定位,计算眼角倾斜度,来改变眼镜最终位置及角度,并将此信息返回给面部定位函数
get_cigarette_info 方法会根据当前人脸的特征值及图片基础设置,来计算人脸嘴巴的位置,并将其返回给面部定位函数。


orientation 方法会将基础的人脸信息通过"get_cigarette_info"和"get_glasses_info"方法处理后,再一并返回给画图函数,供其画图。

def get_glasses_info(self, face_shape, face_width):
    """
    获取当前面部的眼镜信息
    :param face_shape:
    :param face_width:
    :return:
    """

    left_eye = face_shape[36:42]
    right_eye = face_shape[42:48]

    left_eye_center = left_eye.mean(axis=0).astype("int")
    right_eye_center = right_eye.mean(axis=0).astype("int")

    y = left_eye_center[1] - right_eye_center[1]
    x = left_eye_center[0] - right_eye_center[0]
    eye_angle = np.rad2deg(np.arctan2(y, x))

    deal = self.deal.resize(
    (face_width, int(face_width * self.deal.size[1] / self.deal.size[0])),
    resample=Image.LANCZOS)

    deal = deal.rotate(eye_angle, expand=True)
    deal = deal.transpose(Image.FLIP_TOP_BOTTOM)

    left_eye_x = left_eye[00] - face_width // 4
    left_eye_y = left_eye[01] - face_width // 6

    return {"image": deal, "pos": (left_eye_x, left_eye_y)}

def get_cigarette_info(self, face_shape, face_width):
    """
    获取当前面部的眼镜信息
    :param face_shape:
    :param face_width:
    :return:
    """

    mouth = face_shape[49:68]
    mouth_center = mouth.mean(axis=0).astype("int")

    cigarette = self.cigarette.resize(
    (face_width, int(face_width * self.cigarette.size[1] / self.cigarette.size[0])),
    resample=Image.LANCZOS)

    x = mouth[00] - face_width + int(16 * face_width / self.cigarette.size[0])
    y = mouth_center[1]
    return {"image": cigarette, "pos": (x, y)}

def orientation(self):
    """
    人脸定位
    :return:
    """

    faces = []
    for rect in self.rects:
    face = {}
    face_shades_width = rect.right() - rect.left()
    predictor_shape = self.predictor(self.img_gray, rect)
    face_shape = face_utils.shape_to_np(predictor_shape)

    face['cigarette'] = self.get_cigarette_info(face_shape, face_shades_width)
    face['glasses'] = self.get_glasses_info(face_shape, face_shades_width)

    faces.append(face)

    return faces


  • 那我们开始来实现画图函数drawing

根据传入的参数t来计算生成GIF的进度,这里设置画图周期前2秒,来移动面具(即眼镜和烟卷),在两秒前结束移动,然后再画出字体,基本就是这个流程。


面具移动的实现就是来动态更新面具的纵坐标。

def drawing(self, t):
    """
    动态画图
    :param t:
    :return:
    """

    draw_img = self.image.convert('RGBA')
    if t == 0:
    return np.asarray(draw_img)

    for face in self.orientation():
    if t <= self.duration - 2:
        current_x = int(face["glasses"]["pos"][0])
        current_y = int(face["glasses"]["pos"][1] * t / (self.duration - 2))
        draw_img.paste(face["glasses"]["image"], (current_x, current_y), face["glasses"]["image"])

        cigarette_x = int(face["cigarette"]["pos"][0])
        cigarette_y = int(face["cigarette"]["pos"][1] * t / (self.duration - 2))
        draw_img.paste(face["cigarette"]["image"], (cigarette_x, cigarette_y), face["cigarette"]["image"])
    else:
        draw_img.paste(face["glasses"]["image"], face["glasses"]["pos"], face["glasses"]["image"])
        draw_img.paste(face["cigarette"]["image"], face["cigarette"]["pos"], face["cigarette"]["image"])
            draw_img.paste(self.text, (75, draw_img.height // 2 + 128), self.text)

    return np.asarray(draw_img)


  • 以上基本的函数及实现已经完成,让我们来设置一下初始化参数


class FaceDetect(object):
    def __init__(self, img_src, gif_path=None):
        self.gif_max_width = 500
        self.duration = 4
        self.image = self.load(img_src).convert('RGBA')
        self.img_gray = None
        self.rects = None
        self.deal = None
        self.text = None
        self.cigarette = None
        if not self.validate:
            print("没有检测到人脸,程序退出.")
            exit(1)
        self.init_mask()
        self.make_gif(gif_path=gif_path)

    @property
    def validate(self):
        """
        验证是否存在人脸,如果不存在返回False
        :return:
        """

        if self.image.size[0] > self.gif_max_width:
            scaled_height = int(self.gif_max_width * self.image.size[1] / self.image.size[0])
            self.image.thumbnail((self.gif_max_width, scaled_height))
        self.img_gray = np.array(self.image.convert('L'))
        self.rects = self.detector(self.img_gray, 0)
        return len(self.rects) > 0

    def make_gif(self, gif_path=None):
        """
        :param gif_path: 保存路径
        :return:
        """

        gif_path = gif_path or "deal.gif"
        animation = mpy.VideoClip(self.drawing, duration=self.duration)
        animation.write_gif(gif_path, fps=self.duration)


  • 最后我们实现一下main函数

if __name__ == '__main__':
    # 运行 python input_static_pic_to_gif2_for_class.py -image ../images/1.jpg
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("-image", required=True, help="path to input image")
    parser.add_argument("-save", required=False, default="deal.gif", help="path to output image")
    args = parser.parse_args()
    FaceDetect(args.image, args.save)


  • 写到这里,这个小功能就已经实现了,大家不妨来使用一下

写在最后

  • 关注face-detection-induction-course这个仓库,不定时更新更多的人脸识别小示例。


  • 临时测试地址:https://liyuanjun.cn/gifmask https://tomoncle.com/gifmask 

zhi

 支

chi

 持

zuo

 作

zhe

 者


640?wx_fmt=jpeg

长按扫码鼓励作者

点 击 投 稿


长按扫描下方二维码关注后回复“特效

获取本文完整源代码和模型下载地址


640?wx_fmt=jpeg


热 门 推 荐
为你的Python程序加密
用Python开发计时器程序
硬核 | 用Python给女朋友送一颗彩蛋

用Pandas库实现MySQL数据库的读写
推荐Python中文社区旗下的几个服务类公众号

640?wx_fmt=jpeg

▼ 长按扫码上方二维码或点击下方阅读原文

免费成为社区注册会员,会员可以享受更多权益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41830.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 热度飙升,一键生成最近抖音超火的 AI 人物绘图

点击关注公众号&#xff0c;利用碎片时间学习 Paper2GUI 是一款面向普通人的 AI 桌面 APP 工具箱&#xff0c;免安装即开即用&#xff0c;已支持20AI 模型&#xff0c;内容涵盖语音合成、视频补帧、视频超分、目标检测、图片风格化、OCR 识别等领域。支持 Windows、Mac、Linux …

抖音一键生成的AI绘画火了,网友惊呼:有点东西

在各大AI绘画软件争奇斗艳的时候&#xff0c;近期最火的AI绘画莫过于抖音一键生成的AI绘画特效&#xff0c;网友惊呼&#xff1a;有点东西。 就连最近话题度超高的“汪小菲”&#xff0c;也用AI绘画来“秀”恩爱了。 AI绘画识别度还挺高&#xff0c;特别是关于大白志愿者的生成…

讯飞语音的中的bug用户校验失败

用户校验失败&#xff1a;原因是目录没有复制粘贴正确. 下面是刚刚下载的SDK目录: 下面的是自己Android工程中的目录&#xff1a;注意复制粘贴的文件路径要正确 转载于:https://www.cnblogs.com/Oldz/p/9620359.html

Android端科大讯飞语音应用开发

创建语音应用及sdk集成 讯飞开放平台网址 网址&#xff1a;http://www.xfyun.cn/ 1.注册讯飞账号,我以前注册过就直接登录了,创建应用(注:创建过的应用不能被删除)2.创建应用名称规范: 名称_平台类型3.这里显示你的APPID,应用的唯一标示4.创建完成之后现在并没什么卵用,还需要…

python3讯飞语音识别

#!/usr/bin/python # -*- coding: UTF-8 -*- import urllib.parse, urllib.request #这是python3&#xff0c;原先py2里的urllib2或者其他都包含在了py3的urllib里了&#xff0c; # py3里的urllib里的parse和request一定要这么导入&#xff0c;直接import urllib # 是不行的imp…

移动开发-语音识别-调用讯飞平台提供的API

1 登录讯飞平台&#xff0c;申请账号&#xff0c;创建一个应用 具体步骤可以百度查找 2 进入“我的应用”&#xff0c;下载相应的SDK文件 选择语音听写&#xff08;流式版&#xff09;-> Android MSC 3 打开安卓&#xff0c;新建项目 创建一个EditText和一个Button &…

UNIAPP调用讯飞语音评测API

1、历经千辛万苦&#xff0c;UNIAPP调用评测API终于完成&#xff0c;在此做下总结下&#xff1a;首先看效果&#xff01; 2、实现第1步&#xff0c;首先是鉴权&#xff0c;用到的CryptoJS等工具都可以从讯飞和uniapp官方获取 import * as base64 from "base-64" impo…

Android科大讯飞语音集成,非常详细的使用讲解

讯飞语音开发集成地址http://www.xfyun.cn/ 解压后的doc文件夹下的msc develop 文件中有详细集成步骤 AppId: 1.先要注册开发者账户, 添加我的应用 , 下载sdk 2.下载后将sdk解压, 把案例导入工程中运行看看效果 3.将libs下的两个jar包添加到libs目录下, 将同路径下的其它 …

Android 讯飞语音识别功能开发

以下代码主要参考博客&#xff1a; Android 科大讯飞语音识别 Android蓝牙串口开发部分请参照博客&#xff1a; Android蓝牙串口开发 讯飞语音官方开发文档&#xff1a; 语音听写 Android SDK 文档 文章目录 前言一、SDK的下载和导入1.SDK的下载2.新建工程3.配置项目a.导包b.权…

uniapp - 接入科大讯飞语音评测

欢迎关注微信公众号&#xff1a;FSA全栈行动 &#x1f44b; 一、简介 科大讯飞语音评测可以对字、词、句、篇章等题型进行多维度评分&#xff08;准确度、流畅度、完整度、声韵调型等&#xff09;&#xff0c;支持中文和英文。最新的流式版使用 webSocket 调用接口&#xff0c…

目标检测算法——YOLOv5/YOLOv7改进之结合​PP-LCNet(轻量级CPU网络)

>>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 ​PP-LCNet——轻量级且超强悍的CPU级骨干网络&#xff01;&#xff01; &#xff08;一&#xff09;前沿介绍 1.PP-LCNet主要模块 2.相关实验结果 &#xff08;二&#xff09;YOLOv5/YOLOv7改进之结…

从Blip2到Segment Anything视觉语义金字塔+ChatGPT= 把图片变文本段落, 8G显存即可Run...

关注公众号&#xff0c;发现CV技术之美 8G GPU显存即可以运行 Twitter链接&#xff1a;https://twitter.com/awinyimgprocess/status/1646225454599372800?s46&tHvOe9T2n35iFuCHP5aIHpQ 代码链接&#xff1a;https://github.com/showlab/Image2Paragraph https:// 01 …

目标检测算法——YOLOv5/YOLOv7改进之结合​ASPP(空洞空间卷积池化金字塔)

&#x1f496;&#x1f496;>>>加勒比海带&#xff0c;QQ2479200884<<<&#x1f496;&#x1f496; &#x1f340;&#x1f340;>>>【YOLO魔法搭配&论文投稿咨询】<<<&#x1f340;&#x1f340; ✨✨>>>学习交流 | 温澜潮…

从BLIP-2到SAM视觉语义金字塔+ChatGPT= 把图片变文本段落, 8G显存即可Run

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【图像分割】微信技术交流群 作者&#xff1a;老大 |&#xff08;已授权转载&#xff09;编辑&#xff1a;CVer https://zhuanlan.zhihu.com/p/621503837 8G GPU显存即可以运…

问一下ChatGPT:DIKW金字塔模型

经常看到这张DIKW金字塔模型图&#xff0c;还看到感觉有点过份解读的图&#xff0c;后面又加上了insight&#xff0c;impact等内容。 Data&#xff1a;是数据&#xff0c;零散的、无规则的呈现到人们眼前&#xff0c;如果你只看到这些数字&#xff0c;如果没有强大的知识背景&a…

QCon: 工程师成长的金字塔思维

QCon 线下会议终于来了&#xff0c;但这次的分享有一些意外&#xff0c;不是性能、架构、内核、缓存&#xff0c;而不是AI实践相关的内容&#xff0c;论坛的主题是“工程师成长实践”&#xff0c;而我的topic 是“工程师成长的金字塔思维”。本以为这是一个非热门话题&#xff…

拉普拉斯金字塔

原文 高斯金字塔G0层下采样后为G1&#xff0c;用G0减去G1的上采样&#xff0c;就得到了拉普拉斯层L0. 高斯金字塔G1层上采样后与拉普拉斯金字塔L0层相加后就得到了G0层。 import numpy as np import cv2 as cv from matplotlib import pyplot as pltimg cv.imread(left_01.png…

微信称不会推出「已读」功能;马斯克宣布成立 AI 公司 xAI;GPT-4 架构曝光,有 1.8 万亿参数|极客头条

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&…

百度版本gactgpt即将来临,gpt人工智能机器横空出世

百度版本gactgpt即将来临&#xff0c;gpt人工智能机器横空出世&#xff0c;“一言”为定&#xff01;百度版ChatGPT确认&#xff01;李彦宏OKR曝光&#xff0c;率先应用于收索业务 gactCBT 大获&#xff0c;当下极有可能成为人工智能的 iPhone 时刻。为了在这场人工智能竞赛中…

解锁实盘交易,打通量化系统交易环节!股票量化分析工具QTYX-V2.3.9

前言 本期我们把股票量化分析工具QTYX的“交易”子页面给解锁了&#xff0c;这样一来&#xff0c;就打通了量化交易系统从分析到交易的完整过程&#xff0c;注意当前的QTYX版本升级到了2.3.9。 QTYX完整架构如下所示&#xff0c;其中包括了QTYX股票量化分析系统和实盘机器人两部…