谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你

一年一度的游戏视觉盛宴又来了!

作为一个游戏动漫控的肥宅,去CJ现场是必须的。除了看看游戏和动漫,各大游戏展台漂亮的Showgirl也是必不可少的,毕竟没有妹子的CJ就是没有灵魂的CJ,不拍点妹子照片更是等于白来。

逛完展会下来,腿都快走断了,当然,收获是满满的,拍了不少妹子的图,美滋滋地回去了。

回去后和几个好哥们心生一计,咱们要不来PK一下谁拍的妹子最好看?大家一声吆喝,纷纷把手机掏出来,开始凶猛地查找照片。

本肥宅翻了手机里拍的所有照片,选出几张准备和大家PK,结果有一兄弟喷我拍的都是些啥玩意,说我审美不行!忍不了啊,是可忍,叔不可忍,婶婶更不能忍!竟然怀疑我的审美!!!哥差点跟他当场干架!

几个人争来争去,都说自己拍的妹子最好看,好吧,这样争下去是没有结果了……

本肥宅的脑子灵光一闪,说啥咱也是个有技术的人,是不是可以用大数据和AI来搞一个颜值评分器?PK一下到底谁拍的妹子最好看?

AI来打分,看看CJ上哪个Showgirl最漂亮?

说干就干,马上上网查找资料,终于找到一个人脸颜值评分的数据集,总共有2500张男性人脸和2500张女性人脸,由60个人进行人工评分,有数据有标签,那么就可以用该数据集训练一个人脸颜值评分AI模型,技术上来说行得通,行,那就搞起来!

经过2个多小时的“撸力”后,代码写好了,模型ready了,先拿两张CJ的小姐姐照片试一下,看看效果怎样呢?

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第1张图片谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第2张图片

 

喔嚯嚯~,左边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模块

1	!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])

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第3张图片

##################################### 来自程序猿视角的分割线 ######################################

到这里,人脸颜值评分的神器就搞定了!想要代码和模型动手一试的兄弟请看下文。

颜值评分神器获取方式:

方式一:获取代码 + 模型

(1)       点此链接下载脚本face_beauty_predict.ipynb;

(2)       参考此链接注册华为云账号(官方教程,需点一下报名),参考此链接创建ModelArts Notebook,点击Notebook页面右上角的Upload按钮,将上一步下载的脚本上传到Notebook中,点击打开face_beauty_predict.ipynb,在新打开的页面中,点击页面顶部的Cell->Run All,即可下载全部代码和模型。

方式二:获取模型

(1)       模型已分享到华为云ModelArts的AI市场,所有人都可以下载,点此链接进入到模型详情页面;

(2)       然后参考下面几张图进行鼠标点击操作,即可完成模型的下载和部署:

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第4张图片

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第5张图片

3.png

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第6张图片

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第7张图片

同步大概花1分钟左右,可以刷新网页来刷新状态,称为“就绪”状态后,就可以部署模型了

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第8张图片

然后按照提示操作,点下一步、提交、返回在线服务列表,看到的状态是部署中,状态变成运行中之后,就可以点击服务名称进去预测了

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第9张图片

ModelArts上有个将模型部署成在线服务的功能,部署成功后有一个RESTAPI接口,再集成该API就可以做成一个h5页面啦,我已经做好了一个h5页面,点击下方链接就可以测颜值啦 \(^o^)/~ ,还不快试一下?

(还请温柔一点,没钱买服务器,如果出现卡顿,请平静对待~)

http://cj.modelarts.club/v1/modelarts/ChinaJoy

谁是ChinaJoy上最漂亮的小姐姐?AI颜值评分神器来帮你_第10张图片

点击这里→了解更多精彩内容

你可能感兴趣的:(技术交流,ChinaJoy,AI,ModelArts,人工智能)