这届 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. torchvision==0.3. # 本案例同时需要 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(, 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 =
self.nms_threshold = 0.4
self.keep_top_k =
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[:]
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[], img.shape[], img.shape[], img.shape[]])
img -= (, , )
img = img.transpose(, , )
img = torch.from_numpy(img).unsqueeze()
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(), prior_data, cfg_re50['variance'])
boxes = boxes * scale
boxes = boxes.cpu().numpy()
scores = conf.squeeze().data.cpu().numpy()[:, ]
landms = decode_landm(landms.data.squeeze(), prior_data, cfg_re50['variance'])
scale1 = torch.Tensor([img.shape[], img.shape[], img.shape[], img.shape[],
img.shape[], img.shape[], img.shape[], img.shape[],
img.shape[], img.shape[]])
scale1 = scale1.to(self.device)
landms = landms * scale1
landms = landms.cpu().numpy() # ignore low scores
inds = np.where(scores > self.confidence_threshold)[]
boxes = boxes[inds]
landms = landms[inds]
scores = scores[inds] # keep top-K before NMS
order = scores.argsort()[::-][: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=) # face detection results detection_classes = []
detection_scores = []
detection_boxes = []
for b in dets:
if b[] < self.vis_thres:
continue
detection_classes.append('face')
detection_scores.append(round(float(b[]), ))
detection_boxes.append([int(b[]), int(b[]), int(b[]), int(b[])]) 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 =
self.img_height =
self.channels =
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 / .
img_resize = img_resize.reshape((,) + img_resize.shape)
pred_result = self.beauty_model.predict(img_resize)
if pred_result is not None:
pred_result = pred_result[][] 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) > :
for box in detection_boxes:
y1, x1, y2, x2 = int(box[]), int(box[]), int(box[]), int(box[])
width = x2 - x1
height = y2 - y1
new_x1 = max(int(x1 - 0.5 * width), )
new_y1 = max(int(y1 - 0.5 * height), )
new_x2 = min(int(x2 + 0.5 * width), src_img.shape[])
new_y2 = min(int(y2 + 0.2 * height), src_img.shape[])
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), (, , ), thickness=) # 显示人脸位置
cv2.putText(img_draw, '%.1f' % pred_result, (x1, y1 - ), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (, , ), ) # 显示颜值评分
else:
print('未检测到人脸') # 显示图片预测结果
Image.fromarray(img_draw[:,:,::-])
##################################### 来自程序猿视角的分割线 ######################################
到这里,人脸颜值评分的神器就搞定了!想要代码和模型动手一试的兄弟请看下文。
颜值评分神器获取方式:
方式一:获取代码 + 模型
(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^)/~ ,还不快试一下?
(还请温柔一点,没钱买服务器,如果出现卡顿,请平静对待~)
这届 Showgirl行不行?AI告诉你谁是ChinaJoy上最漂亮的小姐姐的更多相关文章
- 开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码
开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码. 开源地址: https://github.com/jkpang/PPRows
- 看看你的正则行不行——正则优化一般的json字符串
json字符串很有用,有时候一些后台接口返回的信息是字符串格式的,可读性很差,这个时候要是有个可以格式化并高亮显示json串的方法那就好多了,下面看看一个正则表达式完成的json字符串的格式化与高亮显 ...
- php高级工程师面试题,行不行对照看下自己的实力
在网上看到一些高级php 的面试题目.. 最近接连面试了几家公司,有些重要问题记录一下,督促自己学习提高,同时希望给朋友们一些帮助.内容很多,一点点完善,一步步学习..有些是面试被问,有些是招聘要求, ...
- 世界杯足彩怎么买划算?机器学习AI告诉你答案(含预测)
本文首发于InfoQ公众号头条. 四年一度的世界杯又来了,作为没什么时间看球的码农,跟大家一样,靠买买足彩给自己点看球动力和乐趣, 然而总是买错球队,面对各种赔率也不知道怎么买才划算,足彩是不是碰大运 ...
- 网站源IP暴露使用高防之后还行不行如何解决?
如题:使用高防后源站IP暴露的解决办法 在购买高防IP后,如果还存在攻击绕过高防直接打到源站IP的情况,就需要更换下源站IP了.但在这之前,请务必排查确认没有其他可能暴露源站IP的因素后,再去更换源站 ...
- 昨天刚看了Handler和HandlerThread这个东西,不明白为什么要用这么复杂的东西,而且Handler直接post的话好像还不是子线程运行。那我再开发的时候直接用Thread行不行?两个有什么区别?
Handler就是android中一个机制,主要是考虑到线程安全的! Handler是可以实现线程间通信的,LZ知道Android的UI线程不安全的吧,也就是说不可以在UI线程以外的其他线程对UI进行 ...
- 用Python爬虫轻松挣个上万块行不行?
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者: 小猿猿er 文章首发于我的技术博客:你可以在上面看到更多的Pytho ...
- Chrome 浏览器跨域和安全访问问题 使用 chrome的命令行标记:disable-web-security 参数联调线上数据
做前端的,用Ajax获取数据,是常有的事情,同域下自然没问题了,如果是不同域获取数据,浏览器就有个同源策略的限制. 如图: Origin * is not allowed by Access-Cont ...
- 翻扣告诉你外出旅游时实用的一些小tips
很多人出行都会带着大包小包,东西胡乱塞成一团,导致每次要用的时候都翻个遍.所以今天游游君为大家推荐几个出门旅行的小技巧. 收拾行李时,把鞋子放进浴帽里.浴帽很容易洗干净,还可以防止鞋子把干净的衣服弄脏 ...
随机推荐
- Least Cost Bracket Sequence,题解
题目链接 题意: 给你一个含有(,),?的序列,每个?变成(或)有一定的花费,问变成课匹配的括号的最小花费. 分析: 首先如果能变成匹配的,那么就有右括号的个数始终不多于左括号且左右括号数量相等,那就 ...
- 传递 HDU - 5961 题解
题目传送门 分析 题目大意:给一个竞赛图,将图分成两部分,判断两部分的图是否符合传递闭包,a->b,b->c,则a->c 这道题用Floyd硬跑的显然n\({^3}\)会T 如果用b ...
- Flask路由中使用正则表达式匹配
1.说明 由于flask并不支持直接使用正则表达式来匹配路由,我们可以使用werkzeug.routing的BaseConverter来实现 2.代码 from flask import Flask ...
- Github和Azure DevOps的代码同步
[前言]Github和Azure DevOps都提供了Git代码库功能,那么有没有办法将两边的代码库进行同步呢,答案是肯定的.这里的操作我都是用Azure DevOps的Pipelines功能来完成的 ...
- 常用js代码片段(一)
1.如果数组所有元素都满足函数条件,则返回true.调用时,如果省略第二个参数,则默认传递布尔值. const all= (arr, fn=Boolean) => arr.every(fn); ...
- web 基础(二) HTML5
web 基础(二) HTML5 一.HTML5 HTML5 是最新的 HTML 标准.是专门为承载丰富的 web 内容而设计的,并且无需额外插件.它拥有新的语义.图形以及多媒体元素.并提供的新元素和新 ...
- LintCode笔记 - 82.落单的数
这一题相对简单,但是代码质量可能不是很好,我分享一下我的做题笔记以及做题过程给各位欣赏,有什么不足望各位大佬指出来 原题目,各位小伙伴也可以试着做一下 . 落单的数 中文English 给出 * n ...
- nginx中的root和alias辨析
root介绍 Syntax: root path; Default: root html; Context: http, server, location, if in location Sets t ...
- java 面向对象(二十):类的结构:代码块
类的成员之四:代码块(初始化块)(重要性较属性.方法.构造器差一些)1.代码块的作用:用来初始化类.对象的信息2.分类:代码块要是使用修饰符,只能使用static分类:静态代码块 vs 非静态代码块3 ...
- SQLAlchemy(三):外键、连表关系
SQLAlchemy03 /外键.连表关系 目录 SQLAlchemy03 /外键.连表关系 1.外键 2.ORM关系以及一对多 3.一对一的关系 4.多对多的关系 5.ORM层面的删除数据 6.OR ...