用OpenCV和Dlib进行人脸颜值预测-解析

参考:
1、http://blog.csdn.net/wc781708249/article/details/78604740
2、http://blog.csdn.net/xingchenbingbuyu/article/details/52804013


数据下载:http://www.hcii-lab.net/data/SCUT-FBP/EN/introduce.html


图片与标签转成pickle文件

# -*- coding: UTF-8 -*-

"""
生成图像数据和标签
数据下载:http://www.hcii-lab.net/data/SCUT-FBP/EN/introduce.html
"""
import csv
import pandas as pd
import numpy as np
import os
import cv2
import glob
from sklearn import preprocessing
from sklearn import decomposition

file_path="./Data_Collection/*.jpg"
img_files=glob.glob(file_path)

img_names=[]
imgs=[]

for img_file in img_files:
    img_name = img_file.split('\\')[-1].split('.')[0].split('-')[-1]  # Linux 为'/'
    img_names.append(img_name) # 记录图片名 后续对应标签
    img=cv2.imread(img_file,0) # 简单点取灰度图
    img=cv2.resize(img,(480,480)) # 尺寸统一
    # # cv2.normalize(img,img,1.0,0.0,cv2.NORM_MINMAX) # 归一到0~1
    img=img.flatten() # 按行展成一行 即每一行代表一张图片
    imgs.append(img)

imgs=np.array(imgs,np.float32)  # 转成 500x230400
# 数据归一化
normalizer = preprocessing.Normalizer(norm='l2').fit(imgs)
imgs=normalizer.transform(imgs)

# pca降维
pca = decomposition.PCA(n_components=20,svd_solver='randomized',whiten=True).fit(imgs)
imgs = pca.transform(imgs)

# 提取图像对应的标签
labels_path="./Rating_Collection/Attractiveness label.xlsx"
labels=pd.read_excel(labels_path)
labels=labels._values[:,:2]
labels=dict(labels)

labels2=[]
# 数据与标签对应
[labels2.append(labels[int(img_name)]) for img_name in img_names]
# 现在 imgs 与 labels2 是对应的
labels2=np.array(labels2,np.float32)[:,np.newaxis]

data=np.hstack((imgs,labels2))

# 保存到文件中
pd.to_pickle(data,'./data.pkl')

加载pkl文件训练模型

# -*- coding: UTF-8 -*-

import pandas as pd
import numpy as np
import argparse
import matplotlib.pyplot as plt

from sklearn import decomposition
from sklearn import linear_model
from sklearn.ensemble import RandomForestRegressor
from sklearn import svm
from sklearn import gaussian_process
from sklearn.externals import joblib
# 加载数据
data=pd.read_pickle('./data.pkl')

# 分成train_datas 与 test_datas
np.random.shuffle(data) # 随机打乱数据
train_datas=data[0:-50]
test_datas=data[-50:]

# regr = linear_model.LinearRegression()
# regr = svm.SVR()
# regr = gaussian_process.GaussianProcess(theta0=1e-2, thetaL=1e-4, thetaU=1e-1)

regr = RandomForestRegressor(n_estimators=50, max_depth=None, min_samples_split=1., random_state=0)
regr = regr.fit(train_datas[:,:-1], train_datas[:,-1])

#一定要把compress设为true或者其他的值,没有设置会输出很多的*.npy
joblib.dump(regr, './my_face_rating.pkl',compress=1)

print("Generate Model Successfully!")

人脸关键点提取

参考:https://github.com/LiuXiaolong19920720/predict-facial-attractiveness/blob/master/source/getLandmarks.py

# -*- coding: UTF-8 -*-

import cv2
import dlib
import numpy
import sys


PREDICTOR_PATH = "./data/shape_predictor_68_face_landmarks.dat"

# 1.使用dlib自带的frontal_face_detector作为我们的人脸提取器
detector = dlib.get_frontal_face_detector()

# 2.使用官方提供的模型构建特征提取器
predictor = dlib.shape_predictor(PREDICTOR_PATH)


class NoFaces(Exception):
    pass


im = cv2.imread("./image/girls.jpg")

# 3.使用detector进行人脸检测 rects为返回的结果
rects = detector(im, 1)

# 4.输出人脸数,rects的元素个数即为脸的个数
if len(rects) >= 1:
    print("{} faces detected".format(len(rects)))

if len(rects) == 0:
    raise NoFaces

f = open('./landmarks.txt', 'w')
for i in range(len(rects)):

    # 5.使用predictor进行人脸关键点识别
    landmarks = numpy.matrix([[p.x, p.y] for p in predictor(im, rects[i]).parts()])
    im = im.copy()

    # 使用enumerate 函数遍历序列中的元素以及它们的下标
    for idx, point in enumerate(landmarks):
        pos = (point[0, 0], point[0, 1])

        f.write(str(point[0, 0]))
        f.write(',')
        f.write(str(point[0, 1]))
        f.write(',')
        # cv2.putText(im,str(idx),pos,
        # fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
        # fontScale=0.4,

        # color=(0,0,255))
        # 6.绘制特征点
        cv2.circle(im, pos, 3, color=(0, 255, 0))
    f.write('\n')
print("landmarks,get!")
cv2.namedWindow("im", 2)
cv2.imshow("im", im)
cv2.waitKey(1000)

特征生成

参考:https://github.com/LiuXiaolong19920720/predict-facial-attractiveness/blob/master/source/generateFeatures.py

import math
import numpy
import itertools

def facialRatio(points):
    x1 = points[0];
    y1 = points[1];
    x2 = points[2];
    y2 = points[3];
    x3 = points[4];
    y3 = points[5];
    x4 = points[6];
    y4 = points[7];

    dist1 = math.sqrt((x1-x2)**2 + (y1-y2)**2)
    dist2 = math.sqrt((x3-x4)**2 + (y3-y4)**2)

    ratio = dist1/dist2

    return ratio


def generateFeatures(pointIndices1, pointIndices2, pointIndices3, pointIndices4, allLandmarkCoordinates):
    size = allLandmarkCoordinates.shape
    allFeatures = numpy.zeros((size[0], len(pointIndices1)))
    for x in range(0, size[0]):
        landmarkCoordinates = allLandmarkCoordinates[x, :]
        ratios = [];
        for i in range(0, len(pointIndices1)):
            x1 = landmarkCoordinates[2*(pointIndices1[i]-1)]
            y1 = landmarkCoordinates[2*pointIndices1[i] - 1]
            x2 = landmarkCoordinates[2*(pointIndices2[i]-1)]
            y2 = landmarkCoordinates[2*pointIndices2[i] - 1]

            x3 = landmarkCoordinates[2*(pointIndices3[i]-1)]
            y3 = landmarkCoordinates[2*pointIndices3[i] - 1]
            x4 = landmarkCoordinates[2*(pointIndices4[i]-1)]
            y4 = landmarkCoordinates[2*pointIndices4[i] - 1]

            points = [x1, y1, x2, y2, x3, y3, x4, y4]
            ratios.append(facialRatio(points))
        allFeatures[x, :] = numpy.asarray(ratios)
    return allFeatures


def generateAllFeatures(allLandmarkCoordinates):
    a = [18, 22, 23, 27, 37, 40, 43, 46, 28, 32, 34, 36, 5, 9, 13, 49, 55, 52, 58]
    combinations = itertools.combinations(a, 4)
    i = 0
    pointIndices1 = [];
    pointIndices2 = [];
    pointIndices3 = [];
    pointIndices4 = [];

    for combination in combinations:
        pointIndices1.append(combination[0])
        pointIndices2.append(combination[1])
        pointIndices3.append(combination[2])
        pointIndices4.append(combination[3])
        i = i+1
        pointIndices1.append(combination[0])
        pointIndices2.append(combination[2])
        pointIndices3.append(combination[1])
        pointIndices4.append(combination[3])
        i = i+1
        pointIndices1.append(combination[0])
        pointIndices2.append(combination[3])
        pointIndices3.append(combination[1])
        pointIndices4.append(combination[2])
        i = i+1

    return generateFeatures(pointIndices1, pointIndices2, pointIndices3, pointIndices4, allLandmarkCoordinates)


landmarks = numpy.loadtxt('./landmarks.txt', delimiter=',', usecols=range(136))

featuresALL = generateAllFeatures(landmarks)
numpy.savetxt('./my_features.txt', featuresALL, delimiter=',', fmt = '%.04f')
print("Generate Feature Successfully!")
#pointIndices1 = [20, 20, 45, 45]
#pointIndices2 = [58, 9, 58, 58]
#pointIndices3 = [5, 7, 5, 32]
#pointIndices4 = [13, 13, 11, 36]
#features = generateFeatures(pointIndices1, pointIndices2, pointIndices3, pointIndices4, landmarks)

颜值预测

参考:https://github.com/LiuXiaolong19920720/predict-facial-attractiveness/blob/master/source/myPredict.py

from sklearn.externals import joblib
import numpy as np
from sklearn import decomposition

#use your own path
clf = joblib.load('./my_face_rating.pkl')
features = np.loadtxt(root + './features_ALL.txt', delimiter=',')
my_features = np.loadtxt(root + './my_features.txt', delimiter=',')
pca = decomposition.PCA(n_components=20)
pca.fit(features)

predictions = np.zeros([6,1])

for i in range(0, 6):
    features_test = features[i, :]
    features_test = pca.transform(features_test)
    #regr = linear_model.LinearRegression()
    #regr.fit(features_train, ratings_train)
    predictions[i] = clf.predict(features_test)
#predictions = clf.predict(features)
print (predictions)

猜你喜欢

转载自blog.csdn.net/wc781708249/article/details/78615331