特此声明:本模型仅供娱乐,大家慎重使用(尤其是不要轻易给女朋友用),本编辑部对后果概不负责
记得2019年的时候,我无意间看到了华南理工大学的颜值评估的数据集。顿时就手痒了,于是做了一个基于深度学习的颜值打分器。不过一直没什么机会用,慢慢地就把这件事忘记了。
直到后来和一个女同学聊天。
我:你长得真好看!
女:阿谀奉承,一看就是说假话。
(低情商)我:对,说的是假话,你长得真丑。
女:......
我当然没这么说,当时情况是这样的。
我:说你好看你还不信!
女:空口无凭啊,怎么证明我好看,难道你有啥量化指标!
我:噫,量化指标,我还真有......你等着
(半小时后)
女:怎么还没找到?
我:......留着青山在,不怕没柴烧,只要数据还在就可以重新写一个。
(两天后)
代码真的写出来了,而且也有训练过的模型,现在只需要输入照片(最好是证件照),就可以输出这个人的颜值。
获取代码方式:
关注“python趣味爱好者”微信公众号,回复“颜值评估”可以得到模型和代码。
项目原理:
首先大家看一看华南理工大学的数据集,正名叫做《华南理工SCUT-FBP5500人脸美学数据集》。一共又5500张人脸照片,还有志愿者根据这些照片的美丽度(颜值)给出的分数,0分最低,5分最高。
如果是研究深度学习的同学,现在已经明白了,我们要做的就是构建一个卷积升神经网络,最后用一个全连接层将特征压缩到一个神经元中。依次输入图片以后反馈调节模型。最终就可以训练一个可以评估人脸美丽度的模型。
我也确实就是这么做的,模型的框架如下图所示:
代码一共有3部分,第一是载入数据,load_img.py,然后是model.py。最后是test_score.py。
大家如果想直接使用这个模型来测试颜值,可以将test_score.py中的image_path里面的文件名换成你想要测试的照片。
另外,由于训练的图片全部都是证件照,所以如果想准确评估自己的颜值,也要输入证件照(不许化妆哦)。
部分代码(模型):
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
#kernel_size表示的是卷积核大小
#nn.Sequential是容器的意思,按顺序执行下列操作
#nn.BatchNorm2d(64)是归一化的意思。
self.encode1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(True),
nn.MaxPool2d(2, 2)
)
self.encode2 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(True),
nn.MaxPool2d(2, 2)
)
self.encode3 = nn.Sequential(
nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(True),
nn.Conv2d(256, 256, 3, 1, 1),
nn.BatchNorm2d(256),
nn.ReLU(True),
nn.MaxPool2d(2, 2)
)
self.encode4 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(True),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(True),
nn.MaxPool2d(2, 2)
)
self.encode5 = nn.Sequential(
nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(512),
nn.ReLU(True),
nn.MaxPool2d(2,2),
nn.Conv2d(512, 512, 3, 1, 1),
nn.BatchNorm2d(512),
nn.ReLU(True),
nn.MaxPool2d(2,2)
)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(4608, 50)
self.fc2 = nn.Linear(50, 1)
def forward(self, x): # b: batch_size
out = self.encode1(x) # [b, 3, 224, 224] => [b, 64, 112, 112]
out = self.encode2(out) # [b, 64, 112, 112] => [b, 128, 56, 56]
out = self.encode3(out) # [b, 128, 56, 56] => [b, 256, 28, 28]
out = self.encode4(out) # [b, 256, 28, 28] => [b, 512, 14, 14]
out = self.encode5(out) # [b, 512, 14, 14] => [b, 512, 7, 7]
out=out.view(-1,4608)
out = F.relu(self.fc1(out))
out = F.dropout(out, training=self.training)
out=self.fc2(out)
return out
测试代码
import os
import model
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from load_img import MyDataset
from torchvision import transforms
from torch.utils.data import DataLoader
import cv2
from torchvision import transforms
image_path='2.png'
image = cv2.imread(image_path)
img = cv2.resize(image, (224, 224))
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])
#device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device="cpu"
img = transform(img)
img=img.unsqueeze(0)
pthfile = r'model_epoch_800.pth'
net = torch.load(pthfile,map_location=torch.device('cpu'))
num=30
score1=0
for i in range(num):
output=torch.sigmoid(net(img))
score=5*(output.detach().numpy())
score1=score+score1
score2=score1/30
print("满分为5分")
print("颜值分数是:",score2)
图片来源:百度图片
数据集来源:华南理工