備戰雙十一·誰的表情包在天上飛

閒魚技術發表於2018-11-14

作者:閒魚技術-鎮雷,還休

前言

雙十一剛過,這個全民吃土的時期,閒魚非常貼心的推出了一個土味表情包的活動,可以通過定製表情包來吐槽並分享大家吃土的心聲,這篇文章將為大家介紹如何用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的背景去除來縮小識別區域。

總結

以上就是表情包活動的全部實現流程了,其中效能、效果還有很多可以優化的點,歡迎大家在閒魚或者手淘體驗”拯救吃土族“定製表情包並提出建議和反饋~


相關文章