备战双十一·谁的表情包在天上飞

简介:

作者:闲鱼技术-镇雷,还休

前言

双十一刚过,这个全民吃土的时期,闲鱼非常贴心的推出了一个土味表情包的活动,可以通过定制表情包来吐槽并分享大家吃土的心声,这篇文章将为大家介绍如何用Python和weex快速搭建这样一个基于人脸识别的活动项目。

关键词:weex、Python、人脸识别

1. 前端搭建

前端页面主要包括:拍照和生成表情两部分。

1.1 拍照

拍照使用的是windvane的拍照模块,目前只能支持weex环境,h5环境暂时只能通过提示和拉端让引导用户到闲鱼or手淘去生成土味表情。在手淘的最新版本8.1.0中,直接用WVCamera.takePhoto进行拍照和上传图片可能出现问题,所以需要把拍照和上传图片分开调用,上传图片使用WVCamera.confirmUploadPhoto接口。

var params = {
    type: '0',
};
window.WindVane.call('WVCamera', 'takePhoto', params, function(e) {
    var uploadParams = {
        // 需要上传的照片的路径
        path: e.localPath,
        // 上传方式
        v: '2.0',
        // 业务代码
        bizCode: 'mtopupload'
    };
    setTimeout(function() {
        window.WindVane.call('WVCamera', 'confirmUploadPhoto', uploadParams, function(e) {
            alert('upload success: ' + JSON.stringify(e));
        }, function(e) {
            alert('upload failure: ' + JSON.stringify(e));
        });
    }, 20);
}, function(e) {
    alert('takePhoto failure: ' + JSON.stringify(e));
});

1.2 生成表情

通过调用后台接口,传人照片地址和表情模板编号,生产表情后,接口会返回表情的地址然后渲染。
效果如下:
IMG_0359.PNG

IMG_0360.PNG

2. 服务端搭建

工程服务端使用纯Python搭建,可以满足快速搭建并部署上线活动的需求,使用的是SocketServer、BaseHTTPServer这两个库构建出的Http服务器:

socketserver是标准库中的一个高级模块,用于网络客户端与服务器的实现。模块中,已经实现了一些可供使用的类,socketserver模块包括许多可以简化TCP,UDP,UNIX域套接字服务器实现的类;

BaseHTTPServer模块构造了HTTP请求处理基类BaseHTTPRequestHandler,它继承自SocketServer模块中的StreamRequestHandler类;

用起来很方便,调用如下:

import BaseHTTPServer as webservice
from SocketServer import ThreadingMixIn
from BaseHTTPServer import HTTPServer,BaseHTTPRequestHandler

if __name__ == '__main__':
    serverAddress = ('', PORT)
    server = ThreadingHttpServer(serverAddress, RequestHandler)
    server.serve_forever()

当有http请求,会触发RequestHandler的do_GET回调,执行里面的业务代码

class RequestHandler(webservice.BaseHTTPRequestHandler):
    def do_GET(self):

基础的调用实现之后,接下来的工作还有用ThreadingHttpServer来实现多线程的webserver,对参数做签名校验,使用Nginx来做分流等…就不一一细说了。

3. 算法选型

人脸融合到表情包的过程可以分四步:

  • 人脸检测
  • 人脸位置对齐
  • 提取脸部五官特征,合成到表情包
  • 调节脸的色调

3.1 在人脸识别部分,我们使用的是dlib库,可以很方便快捷的识别出脸部的68个点,点位置的分布如图:

10_51_41__11_14_2018.jpg

使用起来很简单:

# 初始化dlib
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(PREDICTOR_PATH)
 
# 获取脸部特征点
def get_landmarks(im):
    rects = detector(im, 1)
 
    if len(rects) > 1:
        raise TooManyFaces
    if len(rects) == 0:
        raise NoFaces
 
    return numpy.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()])

3.2 人脸位置对齐,我们取到两张脸的标记矩阵之后,通过使用奇异值分解计算旋转,再利用仿射变换矩阵转化:

def warp_im(im, M, dshape):
    output_im = numpy.zeros(dshape, dtype=im.dtype)
    cv2.warpAffine(im,
                   M[:2],
                   (dshape[1], dshape[0]),
                   dst=output_im,
                   borderMode=cv2.BORDER_TRANSPARENT,
                   flags=cv2.WARP_INVERSE_MAP)
    return output_im

3.3 提取人脸中间特征包括了眼睛、眉毛、鼻子、嘴巴,将这个T字型的关键区域,需要将特征连接成一个凸多边形,然后使用cv.fillConvexPoly填充生成mask遮罩,遮罩的边缘外部羽化扩展,隐藏不连续区域,而表情包的底图需要先将原有的表情擦除,防止原有特征影响照片的图案,再将遮罩与表情包底图的脸部特征矩阵对齐,得到混合图案。

3.4 调节脸的色调是最后一步,经过上一步合成的脸还是原来的色值,需要转换为黑白的图片,首先去色,然后使用gamma曲线调节对比度,让脸部黑色部分更黑,白色部分更白,特征更加明显,调节对比度方法如下:

# 传入参数越大对比度越高
def gamma_trans(img,gamma):
    gamma_table = [numpy.power(x/255.0,gamma)*255.0 for x in range(256)]
    gamma_table = numpy.round(numpy.array(gamma_table)).astype(numpy.uint8)
    return cv2.LUT(img,gamma_table)

4. 算法优化

我们从两个方面对算法做了简单的优化:

一是使用多进程优化,这步使用的是loky库实现:

import loky
from loky import get_reusable_executor

执行部分:

    # work_thread为机器能使用的最大进程数
    executor = get_reusable_executor(max_workers=work_thread, timeout=60)
    params = []
    # 传入需要多进程执行的方法名和参数,多个参数需要合成一个传入
    result = executor.map(do_func, params)
    try:
        while 1:
            re = result.next()

需要注意的是dlib的初始化部分,需要放入多进程优化的函数中,如果作为单例,dlib库会报no safe错误,而当dlib初始化放到了多进程的函数中,每次初始化都会调用一遍,这也是一个耗时的点,使用时需要去权衡优化。

另外还有一点需要注意是,如果你的功能是用Python2实现,另一个更加主流方便的多进程库Process则不能使用,与dlib会有冲突。

二是压缩检测区域,可以对原图先复制一个副本然后将副本压缩至1/4,然后传入dlib中进行识别,再对识别出的landmarks特征数组乘以4,得到原来的特征位置,再来处理原图和复原后的特征点集。除了压缩还可以通过裁剪来减小dlib的计算量,截取ROI区域,识别时将表情包人脸的区域截取出来传入dlib,聚焦图片中部位置识别,或者可以配合OpenCV的背景去除来缩小识别区域。

总结

以上就是表情包活动的全部实现流程了,其中性能、效果还有很多可以优化的点,欢迎大家在闲鱼或者手淘体验”拯救吃土族“定制表情包并提出建议和反馈~

相关文章
|
Cloud Native Dubbo 应用服务中间件
阿里巴巴捐献的14个顶级开源项目,国内开源贡献第一!
代表性的项目包括龙蜥操作系统、Apache RocketMQ、Apache Dubbo、Spring Cloud Alibaba 等
|
6月前
|
监控 数据挖掘 API
🔥 新手也能懂!Shopee商品详情API接口全攻略
本文介绍了一个用于采集Shopee商品数据的API及其使用方法。通过该API,电商运营者可快速监控竞品价格、销量与评价;数据分析人员能批量获取商品信息进行市场调研;开发者则可构建自动化工具如比价系统或生成报告。内容涵盖注册准备、关键参数说明、Python代码示例以及实战案例(如监控竞品差评)。此外,还提供了防封技巧、常见问题解答及适合人群分析,帮助用户高效上手并解决实际需求。
|
5月前
|
存储 前端开发 数据可视化
Postman vs. Apifox 用于 API 测试全面对比
寻找一款可靠的 API 测试工具?这份对比分析将深入探讨 Postman 和 Apifox 的功能和特性。了解哪款工具最适合您的 API 测试需求。
|
11月前
|
网络协议 Java Linux
PyAV学习笔记(一):PyAV简介、安装、基础操作、python获取RTSP(海康)的各种时间戳(rtp、dts、pts)
本文介绍了PyAV库,它是FFmpeg的Python绑定,提供了底层库的全部功能和控制。文章详细讲解了PyAV的安装过程,包括在Windows、Linux和ARM平台上的安装步骤,以及安装中可能遇到的错误和解决方法。此外,还解释了时间戳的概念,包括RTP、NTP、PTS和DTS,并提供了Python代码示例,展示如何获取RTSP流中的各种时间戳。最后,文章还提供了一些附录,包括Python通过NTP同步获取时间的方法和使用PyAV访问网络视频流的技巧。
2415 4
PyAV学习笔记(一):PyAV简介、安装、基础操作、python获取RTSP(海康)的各种时间戳(rtp、dts、pts)
|
数据采集 机器学习/深度学习 自然语言处理
本地训练,开箱可用,Bert-VITS2 V2.0.2版本本地基于现有数据集训练(原神刻晴)
按照固有思维方式,深度学习的训练环节应该在云端,毕竟本地硬件条件有限。但事实上,在语音识别和自然语言处理层面,即使相对较少的数据量也可以训练出高性能的模型,对于预算有限的同学们来说,也没必要花冤枉钱上“云端”了,本次我们来演示如何在本地训练Bert-VITS2 V2.0.2模型。
本地训练,开箱可用,Bert-VITS2 V2.0.2版本本地基于现有数据集训练(原神刻晴)
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
5680 4
|
机器学习/深度学习 设计模式 人工智能
AIGC对设计行业的影响与启发:AIGC设计能替代真正的设计师吗?
AIGC技术正深刻影响设计行业,提升效率、拓宽创意边界,但无法替代设计师的创造力、审美和情感理解。Adobe国际认证成为设计师掌握AIGC技术的起点,推动行业标准化和设计师职业发展。AIGC与设计师的结合将共创设计行业的未来。
|
机器学习/深度学习 存储 人工智能
AI人像动漫
学术界自2000年左右开始对图像生成进行研究。日常采集到的图像数量非常有限,而且采集成本相对较高。因此,我们希望计算机能够自动化生成新的图像。但是,如果图像内容随机生成,无法控制生成结果,则图像依然不可用。
|
移动开发 API
阿里云优惠口令(2024更新)
阿里云优惠口令(2024更新)com域名续费优惠口令“com批量注册更享优惠”,cn域名续费优惠口令“cn注册多个价格更优”,cn域名注册优惠口令“互联网上的中国标识”,阿里云优惠口令是域名专属的优惠码,可用于域名注册、续费和转入使用,域名优惠口令区分域名后缀,阿里云百科分享2024年阿里云域名优惠口令更新(注册、转入、续费均可使用)
25992 0
|
自然语言处理 前端开发
html+css+js+jq简单实现原神官网动态效果
html+css+js+jq简单实现原神官网动态效果
737 0