1. 程式人生 > >這屆 Showgirl行不行?AI告訴你誰是ChinaJoy上最漂亮的小姐姐

這屆 Showgirl行不行?AI告訴你誰是ChinaJoy上最漂亮的小姐姐

摘要: CJ開幕,頂著三伏天的酷暑高溫,暴走一整天,就為了拍點漂亮小姐姐給大家看看。

一年一度的遊戲視覺盛宴又來了!

作為一個遊戲動漫控的肥宅,去CJ現場是必須的。除了看看遊戲和動漫,各大遊戲展臺漂亮的Showgirl也是必不可少的,畢竟沒有妹子的CJ就是沒有靈魂的CJ,不拍點妹子照片更是等於白來。

逛完展會下來,腿都快走斷了,當然,收穫是滿滿的,拍了不少妹子的圖,美滋滋地回去了。

回去後和幾個好哥們心生一計,咱們要不來PK一下誰拍的妹子最好看?大家一聲吆喝,紛紛把手機掏出來,開始凶猛地查詢照片。

本肥宅翻了手機裡拍的所有照片,選出幾張準備和大家PK,結果有一兄弟噴我拍的都是些啥玩意,說我審美不行!忍不了啊,是可忍,叔不可忍,嬸嬸更不能忍!竟然懷疑我的審美!!!哥差點跟他當場幹架!

幾個人爭來爭去,都說自己拍的妹子最好看,好吧,這樣爭下去是沒有結果了……

本肥宅的腦子靈光一閃,說啥咱也是個有技術的人,是不是可以用大資料和AI來搞一個顏值評分器?PK一下到底誰拍的妹子最好看?

AI來打分,看看CJ上哪個Showgirl最漂亮?

說幹就幹,馬上上網查詢資料,終於找到一個人臉顏值評分的資料集,總共有2500張男性人臉和2500張女性人臉,由60個人進行人工評分,有資料有標籤,那麼就可以用該資料集訓練一個人臉顏值評分AI模型,技術上來說行得通,行,那就搞起來!

經過2個多小時的“擼力”後,程式碼寫好了,模型ready了,先拿兩張CJ的小姐姐照片試一下,看看效果怎樣呢?

喔嚯嚯~,左邊3.6分,右邊3.1和3.3分。

注:評分標準是滿分5分,最低1分。資料集提供方有說明,5分和1分是驚世駭俗之顏值,所以資料集中的圖片基本上極少能評到5分或1分,絕大多數都是2到4分。

看起來效果還不錯哦,符合本肥宅的預期,最重要的是這是模型預測出來的結果,是基於5000張圖片和60個人的評價訓練得到的模型,完全不帶個人的審美偏見。有如此神器在手,簡直可以橫著走!

我已經開始想象這個神器可以做哪些事情了!/奸笑,比如:

(1)測試一下女盆友(如果你有)化妝前後的顏值變化;

(2)評選出班級裡最好看的女生;

(3)跟好友進行顏值PK,比一下誰更帥,誰更漂亮;

(4)把收藏的資源都拿出來,篩選出最好看的女生;

等等。。。

實在是有太多用處了,必須是神器啊!/流口水

這麼好的東西,不分享一下實在可惜了,畢竟自己也經常從別人那拿東西,本肥宅也決定大度一把,把程式碼和模型共享出來。

10分鐘速成AI顏值評分神器

先講一下我是怎麼開發這個模型的,其實很簡單,就是人臉檢測+人臉顏值評分,人臉檢測模型一大把,這裡就不多說了,至於顏值評分,直接擼一個Resnet50模型,最後加一個Dense(1)層就可以了。

 

我開發這個模型,用的是來自華為雲的ModelArts(它是一個線上、開箱即用的AI平臺,還有免費的GPU算力,每天不限次數使用,不要太爽!),所以程式碼是在ipynb中跑的。

主要有四個步驟實現人臉顏值評分:

(1)前提準備

(2)搭建人臉檢測模型

(3)搭建人臉評分模型

(4)效果測試

下面開始上程式碼,所有程式碼如下,詳情請閱讀程式碼註釋:

(1)前提準備

安裝需要的python模組

!pip install torch==1.1.0 torchvision==0.3.0  # 本案例同時需要 tf 和 pytorch 兩種框架

下載程式碼和模型

import os
import subprocess
import moxing as mox

print('Downloading datasets and code ...')
if not os.path.exists('face_beauty_predict'):
    mox.file.copy('obs://arthur-1/face_beauty_predict/face_beauty_predict.zip', './face_beauty_predict.zip')
    p1 = subprocess.run(['unzip face_beauty_predict.zip;rm face_beauty_predict.zip'], stdout=subprocess.PIPE, shell=True, check=True)
print('Download success')

(2)搭建人臉檢測模型

公開的人臉檢測非常多,例如開源的RetinaFace 效果就不錯,且已經有訓練好的模型可以下載使用,執行下面的程式碼即可完成人臉檢測模型的搭建

import os
import sys
sys.path.insert(0, os.path.join(os.getcwd(), './face_beauty_predict/model'))
import torch
import numpy as np
from PIL import Image
from collections import OrderedDict
import torch.backends.cudnn as cudnn

from data import cfg_re50
from layers.functions.prior_box import PriorBox
from utils.nms.py_cpu_nms import py_cpu_nms
from models.retinaface import RetinaFace
from utils.box_utils import decode, decode_landm
cudnn.benchmark = True


class RetinaFaceModel(object):
    def __init__(self, model_path):
        self.network = 'resnet50'
        self.cpu = True
        self.confidence_threshold = 0.02
        self.top_k = 5000
        self.nms_threshold = 0.4
        self.keep_top_k = 750
        self.save_image = True
        self.vis_thres = 0.9
        self.device = torch.device("cpu" if self.cpu else "cuda")

        print('Loading model from %s' % model_path)
        torch.set_grad_enabled(False)
        self.model = RetinaFace(cfg=cfg_re50, phase='test')
        if self.cpu:
            pretrained_dict = torch.load(model_path, map_location='cpu')
        else:
            pretrained_dict = torch.load(model_path)
        state_dict = OrderedDict()
        for key, value in pretrained_dict.items():
            tmp = key[7:]
            state_dict[tmp] = value
        self.model.load_state_dict(state_dict, strict=False)
        self.model.eval()
        self.model = self.model.to(self.device)
        print('load model success')

    def inference(self, img):
        img = np.float32(img)
        im_height, im_width, _ = img.shape
        scale = torch.Tensor([img.shape[1], img.shape[0], img.shape[1], img.shape[0]])
        img -= (104, 117, 123)
        img = img.transpose(2, 0, 1)
        img = torch.from_numpy(img).unsqueeze(0)
        img = img.to(self.device)
        scale = scale.to(self.device)

        loc, conf, landms = self.model(img)  # forward pass

        priorbox = PriorBox(cfg_re50, image_size=(im_height, im_width))
        priors = priorbox.forward()
        priors = priors.to(self.device)
        prior_data = priors.data
        boxes = decode(loc.data.squeeze(0), prior_data, cfg_re50['variance'])
        boxes = boxes * scale
        boxes = boxes.cpu().numpy()
        scores = conf.squeeze(0).data.cpu().numpy()[:, 1]
        landms = decode_landm(landms.data.squeeze(0), prior_data, cfg_re50['variance'])
        scale1 = torch.Tensor([img.shape[3], img.shape[2], img.shape[3], img.shape[2],
                               img.shape[3], img.shape[2], img.shape[3], img.shape[2],
                               img.shape[3], img.shape[2]])
        scale1 = scale1.to(self.device)
        landms = landms * scale1
        landms = landms.cpu().numpy()

        # ignore low scores
        inds = np.where(scores > self.confidence_threshold)[0]
        boxes = boxes[inds]
        landms = landms[inds]
        scores = scores[inds]

        # keep top-K before NMS
        order = scores.argsort()[::-1][:self.top_k]
        boxes = boxes[order]
        landms = landms[order]
        scores = scores[order]

        # do NMS
        dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
        keep = py_cpu_nms(dets, self.nms_threshold)
        dets = dets[keep, :]
        landms = landms[keep]

        # keep top-K faster NMS
        dets = dets[:self.keep_top_k, :]
        landms = landms[:self.keep_top_k, :]

        dets = np.concatenate((dets, landms), axis=1)  # face detection results

        detection_classes = []
        detection_scores = []
        detection_boxes = []
        for b in dets:
            if b[4] < self.vis_thres:
                continue
            detection_classes.append('face')
            detection_scores.append(round(float(b[4]), 4))
            detection_boxes.append([int(b[1]), int(b[0]), int(b[3]), int(b[2])])

        return detection_classes, detection_scores, detection_boxes

model_path = r'./face_beauty_predict/model/Resnet50_Final.pth'
retina_face_model = RetinaFaceModel(model_path)

(3)搭建人臉評分模型

有個公開的人臉評分資料集是SCUT-FBP5500 ,裡面有人工評分的2500張男性人臉和2500張女性人臉,程式碼庫facial_beauty_prediction 提供了基於SCUT-FBP5500資料集訓練好的模型,執行如下程式碼就可以載入模型使用

import cv2
from PIL import Image
from keras.models import load_model


class FaceBeautyModel(object):
    def __init__(self, model_path):
        print('Loading model from %s' % model_path)
        self.img_width = 350
        self.img_height = 350
        self.channels = 3
        self.beauty_model = load_model(model_path)  # 直接載入訓練好的模型
        print('load model success')

    def inference(self, img):
        img_resize = cv2.resize(img, (self.img_width, self.img_height), cv2.INTER_AREA)
        img_resize = img_resize / 255.
        img_resize = img_resize.reshape((1,) + img_resize.shape)
        pred_result = self.beauty_model.predict(img_resize)
        if pred_result is not None:
            pred_result = pred_result[0][0]

        return pred_result

model_path = r'./face_beauty_predict/model/face_beauty/face_beauty.h5'
face_beauty_model = FaceBeautyModel(model_path)

(4)效果測試

img_path = r'./face_beauty_predict/model/test_imgs/1.jpg'  # 測試圖片路徑
src_img = cv2.imread(img_path)
detection_classes, detection_scores, detection_boxes = retina_face_model.inference(src_img)
img_draw = src_img.copy()
if len(detection_boxes) > 0:
    for box in detection_boxes:
        y1, x1, y2, x2 = int(box[0]), int(box[1]), int(box[2]), int(box[3])
        width = x2 - x1
        height = y2 - y1
        new_x1 = max(int(x1 - 0.5 * width), 0)
        new_y1 = max(int(y1 - 0.5 * height), 0)
        new_x2 = min(int(x2 + 0.5 * width), src_img.shape[1])
        new_y2 = min(int(y2 + 0.2 * height), src_img.shape[0])
        pred_result = face_beauty_model.inference(src_img[new_y1:new_y2, new_x1:new_x2])
        if pred_result is not None:
            cv2.rectangle(img_draw, (x1, y1), (x2, y2), (0, 255, 0), thickness=2)  # 顯示人臉位置
            cv2.putText(img_draw, '%.1f' % pred_result, (x1, y1 - 3), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)  # 顯示顏值評分
else:
    print('未檢測到人臉')

# 顯示圖片預測結果
Image.fromarray(img_draw[:,:,::-1])

 

到這裡,人臉顏值評分的神器就搞定了!想要程式碼和模型動手一試的兄弟請看下文。

顏值評分神器獲取方式:

方式一:獲取程式碼 + 模型

(1)點此連結下載指令碼 face_beauty_predict.ipynb ;      

(2)參考此連結註冊華為雲賬號(官方教程,需點一下報名),參考此連結建立 ModelArts筆記本,單擊筆記本頁面右上角的上傳按鈕,將上一步下載的指令碼上傳到筆記本中,單擊開啟 face_beauty_predict .ipynb ,在新開啟的頁面中,點選頁面頂部的Cell- > Run All ,即可下載全部程式碼和模型。      

方式二:獲取模型

(1)模型已分享到華為雲 ModelArts 的 AI 市場,所有人都可以下載,點此連結進入到模型詳情頁面;    

(2)然後參考下面幾張圖進行滑鼠點選操作,即可完成模型的下載和部署:

同步大概花1分鐘左右,可以重新整理網頁來重新整理狀態,稱為“就緒”狀態後,就可以部署模型了

然後按照提示操作,點下一步、提交、返回線上服務列表,看到的狀態是部署中,狀態變成執行中之後,就可以點選服務名稱進去預測了

ModelArts上有個將模型部署成線上服務的功能,部署成功後有一個RESTAPI介面,再整合該API就可以做成一個h5頁面啦,我已經做好了一個h5頁面,訪問連結:https://jamiexu.easy.echosite.cn/v1/modelarts/ChinaJoy就可以測顏值啦 \(^o^)/~ ,還不快試一下?

(還請溫柔一點,沒錢買伺服器,如果出現卡頓,請平靜對待~)

 

點選關注,第一時間瞭解華為雲新鮮技