summaryrefslogtreecommitdiff
path: root/megapixels/app/processors/face_beauty.py
blob: 2e8221b78623bdb802986810bddfc9ec0591c56b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import sys
import os
from os.path import join
from pathlib import Path
import math

import cv2 as cv
import numpy as np
import imutils
import pickle

os.environ['CUDA_VISIBLE_DEVICES'] = ''
import keras
from keras.layers import Conv2D, Input, MaxPool2D,Flatten, Dense, Permute, GlobalAveragePooling2D
from keras.models import Model
from keras.optimizers import adam
import os.path
from keras.models import Sequential
from keras.applications.resnet50 import ResNet50
#from keras.applications.resnet50 import Dense
from keras.layers import Dense
from keras.optimizers import Adam
from keras.layers import Dropout

from app.utils import im_utils, logger_utils
from app.models.bbox import BBox
from app.settings import app_cfg as cfg
from app.settings import types



class FaceBeauty:

  # Estimates beauty using CNN

  def __init__(self, gpu=-1):
    # don't really need GPU, CPU is quick enough
    self.log = logger_utils.Logger.getLogger()
    resnet = ResNet50(include_top=False, pooling='avg')
    self.model = Sequential()
    self.model.add(resnet)
    self.model.add(Dense(5, activation='softmax'))
    self.model.layers[0].trainable = False
    fp_model = join(cfg.DIR_MODELS_KERAS, 'model-ldl-resnet.h5')
    self.model.load_weights(fp_model)


  def beauty(self, im, bbox_dim):
    '''Predicts facial "beauty" score based on SCUT-FBP attractiveness labels
    :param im: (numpy.ndarray) BGR image
    :param bbox_dim: (BBox) dimensioned BBox
    :returns (float) 0.0-1.0 with 1 being most attractive
    '''

    face = bbox_dim.to_xyxy()
    self.log.debug(f'face: {face}')

    cropped_im = im[face[1]:face[3], face[0]:face[2]]

    im_resized = cv.resize(cropped_im, (224, 224))  # force size
    im_norm = np.array([(im_resized - 127.5) / 127.5])  # subtract mean

    # forward pass
    pred = self.model.predict(im_norm)

    # combines score to make final estimate?
    ldList = pred[0]
    score = 1 * ldList[0] + 2 * ldList[1] + 3 * ldList[2] + 4 * ldList[3] + 5 * ldList[4]
    return score/5.0


  def score_mapping(self, score):
    '''(deprecated)
    '''

    # if score <= 1.9:
    #   score_mapped = ((4 - 2.5) / (1.9 - 1.0)) * (score-1.0) + 2.5
    # elif score <= 2.8:
    #   score_mapped = ((5.5 - 4) / (2.8 - 1.9)) * (score-1.9) + 4
    # elif score <= 3.4:
    #   score_mapped = ((6.5 - 5.5) / (3.4 - 2.8)) * (score-2.8) + 5.5
    # elif score <= 4:
    #   score_mapped = ((8 - 6.5) / (4 - 3.4)) * (score-3.4) + 6.5
    # elif score < 5:
    #   score_mapped = ((9 - 8) / (5 - 4)) * (score-4) + 8

    # return score_mapped
    return False