基于神经网络搭建自己的颜值检测网页

寒假在家,闲来无事,萌生了用神经网络搭建一个颜值检测算法的想法,起初,只是想要把这个算法实现一下就好,但是,最后本着精(想)益(要)求(装)精(逼)的想法,就尝试着把它做成了一个网页版本的小游戏,后来为了让朋友们可以直接访问,于是就利用旧电脑搭建了一个服务器,把网站做成了可以公共访问的形式。最后做出的颜值检测的网站是这样的
在这里插入图片描述github地址:https://github.com/lwpyh/face_mark/
下面就如何搭建这一个颜值检测网站做一些说明。下面的说明分成以下几个模块,首先是算法模块,因为我是做模式识别这一方向的,所以这一部分也是我研究的重点。首先要考量的是数据集的问题,由于大部分现有的颜值检测是一些公司的项目组的作品,而处于隐私的原因,大多数数据集是不公开的,换言之,这些数据集是比较难找到的。我在网上找了半天,最后也没有发现满意的数据集,出于这些原因,我最后选择自己爬虫,然后发动朋友圈的朋友们帮我标注,换言之就是征集志愿者为我标注数据,但是最后把数据收集以后发现打的分数具有一定的bias并且数据集大小还是不够大,所以我又开始在网络上寻找数据集,最后功夫不负有心人,找到了华南理工大学制作的男性女性颜值检测数据集,这个数据集的链接是颜值检测数据集,这个数据集里面包含了男性与女性两个数据集,年龄分布合理,而且颜值分布满足正态分布,与实际情况相符,因此,选定这一个数据集为我所使用的数据集。
有了数据集,下一步考虑的就是如何对数据进行处理了,由于该数据集较大,所以首先考量的是利用alexnet这样的比较成熟的神经网络解决这些问题,于是,我利用现有的alexnet网络架构对这一个数据集进行训练,做出的微小的改变就是最后一层为一个输出,输出再乘以5(因为数据集满分为5)得到最后的结果,然而,由于在神经网络中最后一层前往往有sigmoid这样的激活单元,导致最后的输出结果总是趋向于两端,即0和5,使得最后结果不佳,同时考虑到部署到旧电脑上的话,性能也不一定达到要求,所以我决定使用一种相对轻量简洁的网络来做颜值检测。
首先介绍一个神器,是基于python的一个库,叫做face_recognition,这个库的主要目的就是识别出面孔,并且还具有比较面孔相似度等功能接口,这里我们使用这个模块的主要目的是通过face_recognition这一模块实现将每幅高维度的图像转化为相对简单的一组向量,这一操作类似于bottleneck layer的操作,将高维图像转化为一组相对简单的向量,从而便于后续操作。这里需要注意的一点是face_recognition的安装是有一些难度的,我在pycharm里面直接安装这个库是装不上的,还需要百度的帮忙。姑且,我们把这一部分当作是数据预处理阶段吧,这一部分的代码我把它集成到了一个子程序里,命名为prepaer.py

# coding: utf8
import os
import pickle
import face_recognition as fr

images_root = "/home/tuo/jhu/SCUT-FBP5500_v2/SCUT-FBP5500_v2/Images"
labels_file = "/home/tuo/jhu/SCUT-FBP5500_v2/SCUT-FBP5500_v2/train_test_files/All_labels.txt"

face_list = []
with open(labels_file, encoding = "utf8") as fi:
    for line in fi:
        line = line.strip()
        filename, score = line.split(" ")
        full_path = os.path.join(images_root, filename)
        if not os.path.exists(full_path):
            print("Error: image file not found: ", full_path)
            continue
        image = fr.load_image_file(full_path)
        assert image is not None
        encs = fr.face_encodings(image)
        if len(encs) != 1:
            print("%s has %d faces." % (filename, len(encs)))
            continue

        item = {
            'enc': encs[0],
            'score': float(score)
        }
        face_list.append(item)

print("Total faces: %d." % len(face_list))
with open("training.pkl", "wb") as fo:
    pickle.dump(face_list, fo)

解释一下这部分代码的思路,首先加载数据集,然后按照顺序,依次使用face_recognition库依次加载每幅图片,并对图片进行处理,获得一个向量,这个向量表征的就是这幅图片里面的人脸特征,并将其对应的标签一一整理好,最后存放在training.pkl这一文件里。
下一部分代码是将预处理的图像信息进行加载与训练,这一部分代码放在了train.py里面了,

# coding: utf8
import pickle
import random
import numpy as np
from keras import Sequential, Model
from keras.layers import Dense,Flatten,Dropout
from keras.layers.convolutional import Conv2D,MaxPooling2D
from keras.layers import Dense

def load_data():
    with open("training.pkl", "rb") as fi:
        return pickle.load(fi)

def split_data(faces_with_label, train_percent = 0.8):
    pos = int(len(faces_with_label) * train_percent)
    print("Split pos: ", pos)
    x = [item['enc'] for item in faces_with_label]
    print("enc size: ", x[0].shape)
    y = [item['score'] for item in faces_with_label]
    x = np.array(x)
    y = np.array(y)
    # img_rows,img_cols=28,28
    print("shape of x: ", x.shape)
    print("shape of y: ", y.shape)
    train_x, train_y = x[:pos], y[:pos]
    # train_x=train_x.reshape(pos,1,img_rows,img_cols)
    val_x, val_y = x[:pos], y[:pos]
    # print(val_x)
    # val_x =val_x.reshape((len(faces_with_label)-pos), -1, img_rows, img_cols)
    return (train_x, train_y), (val_x, val_y)

def build_model(input_dim,hidden_size):
    model = Sequential()
    model.add(Dense(hidden_size, input_dim=input_dim, kernel_initializer="normal", activation="relu"))
    model.add(Dense(hidden_size, input_dim=hidden_size, kernel_initializer="normal", activation="relu"))
    model.add(Dense(1, kernel_initializer="normal"))
    model.compile(loss="mean_squared_error", optimizer="adam")
    return model

def main():
    train_batch_size = 64
    epochs = 1000
    faces_with_score = load_data()
    #random.shuffle(faces_with_score)
    print("Total faces: %d" % len(faces_with_score))
    (train_x, train_y), (val_x, val_y) = split_data(faces_with_score)
    # print(train_y,val_y)
    model=build_model(input_dim=128,hidden_size=512)
    history = model.fit(train_x, train_y, batch_size=train_batch_size, epochs=epochs, shuffle=False, validation_data=(val_x, val_y))
    model.evaluate(val_x, val_y)
    model.save("face_rank_model.h5")


if __name__ == '__main__':
    main()

这一部分所做的事情也非常简单了,首先就是加载与处理数据,然后通过一个简单的CNN神经网络实现训练。
最后通过predict.py对得到的算法进行测试,这里测试的图片是自己找的,你可以根据自己需要进行修改,测试结果基本符合审美。
predict.py的程序是

# coding: utf8
import glob
import numpy as np
from keras.models import load_model
import face_recognition as fr

def main():
    model = load_model("face_rank_model.h5")
    files = glob.glob(r"samples/a*")
    files.extend(glob.glob(r"samples/b*"))
    files.extend(glob.glob(r"samples/c*"))
    files.extend(glob.glob(r"samples/d*"))
    files.extend(glob.glob(r"samples/e*"))
    files.extend(glob.glob(r"samples/f*"))
    for f in files:
        image = fr.load_image_file(f)
        encs = fr.face_encodings(image)
        if len(encs) != 1:
            print("Find %d faces in %s" % (len(encs), f))
            continue
        predicted = model.predict(np.array(encs))
        predicted = np.squeeze(predicted)
        print(type(predicted))
        print("%s: %.4f" % (f, predicted))

if __name__ == '__main__':
    main()

那么现在完成了这一部分的代码之后关键的问题就是如何构建一个网页版的交互界面了,这个时候github再一次站了出来,我在GitHub上找到了一个用网页显示自己的AIdemo的程序,具体链接是AI demo网页实现,具体使用方法就是将刚刚训练得到的.h5文件放入到对应的model文件夹里,然后对app.py进行修改,使其可以正确处理我们加载的图像数据,本质而言,通过网页进行交互就是一个测试的过程,然后在local:5000这一网址上运行,即可得到网页版的颜值检测界面,对应修改过的app.py如下

import re
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Flatten, Activation
from keras.layers.convolutional import Conv2D, MaxPooling2D
import keras
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
from keras.models import load_model
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array
# Flask utils
from flask import Flask, redirect, url_for, request, render_template
from werkzeug.utils import secure_filename
from gevent.pywsgi import WSGIServer
import pickle
import face_recognition as fr

# Define a flask app
app = Flask(__name__)

# Model saved with Keras model.save()
MODEL_PATH = 'models/face_rank_model.h5'

# Load your trained model
# model=make_network()
# model.load_weights (MODEL_PATH)
model=load_model(MODEL_PATH)
model.summary()
model._make_predict_function()          # Necessary
print('Model loaded. Start serving...')

# You can also use pretrained model from Keras
# Check https://keras.io/applications/
# from keras.applications.resnet50 import ResNet50
# model = ResNet50(weights='imagenet') #zhushidiaole
# print('Model loaded. Check http://127.0.0.1:5000/') #zhushidiaole


def model_predict(img_path, model):

    # Preprocessing the image
    image = fr.load_image_file(img_path)
    encs = fr.face_encodings(image)
    # if len(encs) != 1:
    #     print("Find %d faces in %s" % (len(encs), img_path))
    #     continue

    # Be careful how your trained model deals with the input
    # otherwise, it won't make correct prediction!
    # x = preprocess_input(x, mode='caffe')  wozhushidiaole

    preds = model.predict(np.array(encs))
    print(type(preds))
    return preds


@app.route('/', methods=['GET'])
def index():
    # Main page
    return render_template('index.html')


@app.route('/predict', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        # Get the file from post request
        f = request.files['file']

        # Save the file to ./uploads
        basepath = os.path.dirname(__file__)
        file_path = os.path.join(
            basepath, 'uploads', secure_filename(f.filename))
        f.save(file_path)

        # Make prediction
        preds = model_predict(file_path, model)
        # preds=model_predict("C://l/c1.jpg",model)
        print(preds[0])
        t=round(preds[0][0]*2,3)
        print('t',t)
        print(type(t))
        result=str(t)
        print(result)
        result1 = str(result)
        return result1
    return None


if __name__ == '__main__':
    # Serve the app with gevent
    http_server = WSGIServer(('', 5000), app)
    http_server.serve_forever()

但是到这一步,网页是只能 自己把玩的,如何使身边的朋友们也能一起调戏AI呢?这里需要两个工具,花生壳和nginx,一个是用来做内网穿透,一个用来做反向代理,花生壳的教程我觉得百度的就可以了,这里就不放连接了,首先使用花生壳做内网穿透后,可以通过访问花生壳给你的域名直接访问到你的服务器的80端口,但是,我们的实际程序是运行在服务器的5000端口的,所以还需要用nginx做一下反向代理,这样就可以实现当访问服务器时,会直接跳转到指定的5000端口,这一部分也有教程,这里就不赘述了。
最后,一个网页版的颜值检测小游戏就做完了!放一张木村拓哉的测试结果来完结这篇总结。
最后再把代码地址重复一遍:https://github.com/lwpyh/face_mark/
在这里插入图片描述

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值