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 import keras from keras.layers import Conv2D, Input, MaxPool2D,Flatten, Dense, Permute, GlobalAveragePooling2D from keras.models import Model from keras.optimizers import adam 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): # ensure Keras uses CPU (no GPU, it takes up all memory) os.environ['CUDA_VISIBLE_DEVICES'] = '' # 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