Skip to content

Commit

Permalink
add ML train and test code for FBP
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasxlu committed Dec 7, 2018
1 parent bd7a237 commit a16970e
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 4 deletions.
29 changes: 29 additions & 0 deletions cv/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import time
from random import randint

import cv2
from django.http import HttpResponse
from mtcnn.mtcnn import MTCNN

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Expand Down Expand Up @@ -60,3 +62,30 @@ def upload_and_rec(request):
json_result = json.dumps(result, ensure_ascii=False)

return HttpResponse(json_result)


def detect_face(img_path):
"""
detect face with MTCNN
:param img_path:
:return:
"""
img = cv2.imread(img_path)
detector = MTCNN()
mtcnn_result = detector.detect_faces(img)

return mtcnn_result


class BeautyRecognizer:
def __init__(self, pretrained_model):
self.model = None

def infer(self, img_path):
img = cv2.imread(img_path)
mtcnn_result = detect_face(img_path)
bbox = mtcnn_result['box']
face_region = img[bbox[0] - int(bbox[2] / 2): bbox[0] + int(bbox[2] / 2),
bbox[1] - int(bbox[3] / 2): bbox[1] + int(bbox[3] / 2)]

return self.model.infer(face_region)
116 changes: 116 additions & 0 deletions cv/features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
feature extractor
"""
import cv2
import dlib
import numpy as np
import skimage.color
from skimage import io
from skimage.feature import hog, local_binary_pattern, corner_harris

DLIB_MODEL = "E:\ModelZoo\shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(DLIB_MODEL)
detector = dlib.get_frontal_face_detector()


def HOG(img_path):
"""
extract HOG feature
:param img_path:
:return:
:version: 1.0
"""
img = io.imread(img_path)
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)
feature = hog(img, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(1, 1), block_norm='L2-Hys')

return feature


def LBP(img_path):
"""
extract LBP features
:param img_path:
:return:
"""
img = io.imread(img_path)
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)
feature = local_binary_pattern(img, P=8, R=0.2)
# im = Image.fromarray(np.uint8(feature))
# im.show()

return feature.reshape(feature.shape[0] * feature.shape[1])


def LBP_from_cv(img):
"""
extract LBP features from opencv region
:param img:
:return:
"""
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)
feature = local_binary_pattern(img, P=8, R=0.2)
# im = Image.fromarray(np.uint8(feature))
# im.show()

return feature.reshape(feature.shape[0] * feature.shape[1])


def HARRIS(img_path):
"""
extract HARR features
:param img_path:
:return:
:Version:1.0
"""
img = io.imread(img_path)
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)
feature = corner_harris(img, method='k', k=0.05, eps=1e-06, sigma=1)

return feature.reshape(feature.shape[0] * feature.shape[1])


def RAW(img_path):
img = io.imread(img_path)
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)

return img.reshape(img.shape[0] * img.shape[1])


def HOG_from_cv(img):
"""
extract HOG feature from opencv image object
:param img:
:return:
:Version:1.0
"""
img = skimage.color.rgb2gray(img)
img = (img - np.mean(img)) / np.std(img)

return hog(img, orientations=8, pixels_per_cell=(16, 16), cells_per_block=(1, 1), block_norm='L2-Hys')


def Geo_from_cv(img):
"""
68 facial landmarks as geometry feature
:param img:
:return:
"""
faces = detector(img, 1)

result = {}
if len(faces) > 0:
for k, d in enumerate(faces):
shape = predictor(img, d)
result[k] = {"bbox": [d.left(), d.top(), d.right(), d.bottom()],
"landmarks": [[shape.part(i).x, shape.part(i).y] for i in range(68)]}

xs = np.array([_[0] for _ in result['landmarks']])
ys = np.array([_[1] for _ in result['landmarks']])

return list(xs - np.mean(xs)) + list(ys - np.mean(ys))
84 changes: 84 additions & 0 deletions cv/train_and_test_fbp_with_ml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
train and test FBP with traditional ML, instead of DL
"""
import os
import sys

import pandas as pd
from mtcnn.mtcnn import MTCNN
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error

sys.path.append('../')
from cv.features import *

SCUT5500_DIR = "E:\DataSet\CV\SCUT-FBP5500\Images"
LABEL_CSV = "E:\DataSet\CV\SCUT-FBP5500/train_test_files\SCUT-FBP5500-With-Head.csv"


def prepare_data():
features = []
lbs = []

df = pd.read_csv(LABEL_CSV)
files = df['file']
scores = df['score']
detector = MTCNN()

for i in range(len(files)):
img = cv2.imread(os.path.join(SCUT5500_DIR, files[i]))
mtcnn_result = detector.detect_faces(img)
bbox = mtcnn_result['box']

if bbox is not None:
face_region = img[bbox[0] - int(bbox[2] / 2): bbox[0] + int(bbox[2] / 2),
bbox[1] - int(bbox[3] / 2): bbox[1] + int(bbox[3] / 2)]
ratio = max(face_region[0], face_region[1]) / min(face_region[0], face_region[1])
if face_region[0] > face_region[1]:
face_region = cv2.resize(face_region, (int((face_region[0] / ratio) * 64 / face_region[1]), 64))
else:
face_region = cv2.resize(face_region, (64, int((face_region[1] / ratio) * 64 / face_region[0])))
else:
face_region = cv2.resize(img, (64, 64))

lbp = LBP_from_cv(face_region)
hog = HOG_from_cv(face_region)
ldmk = Geo_from_cv(img)

feature = lbp + hog + ldmk
features.append(feature)
lbs.append(scores[i])

return features, lbs


def train_fbp(X, y):
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42)

rfreg = RandomForestRegressor()
print('start training Random Forest Regressor...')
rfreg.fit(X_train, y_train)

if not os.path.exists('./model'):
os.makedirs('./model')

joblib.dump(rfreg, './model/RandomForestRegressor.pkl')
print('The regression model has been persisted...')

y_pred = rfreg.predict(X_test)

mae_lr = round(mean_absolute_error(y_test, np.array(y_pred).ravel()), 4)
rmse_lr = round(np.math.sqrt(mean_squared_error(np.array(y_test), np.array(y_pred).ravel())), 4)
pc = round(np.corrcoef(np.array(y_test), np.array(y_pred).ravel())[0, 1], 4)

print('===============The Mean Absolute Error of ANet is {0}===================='.format(mae_lr))
print('===============The Root Mean Square Error of ANet is {0}===================='.format(rmse_lr))
print('===============The Pearson Correlation of ANet is {0}===================='.format(pc))


if __name__ == '__main__':
X, y = prepare_data()
train_fbp(X, y)
4 changes: 2 additions & 2 deletions cv/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
urlpatterns = [
path('welcome', views.welcome, name='welcome'),
path('index', views.index, name='index'),
path('facerank', views.facerank, name='facerank'),
url('fbp', views.fbp, name='fbp'),
path('fbp', views.fbp, name='fbp'),
url('fbpview', views.fbp_view, name='fbpview'),
url('detectface', views.detect_face, name='detectface'),
]
4 changes: 2 additions & 2 deletions cv/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def index(request):
return render(request, 'index.html')


def facerank(request):
def fbp(request):
from cv import controllers
return controllers.upload_and_rec(request)


def fbp(request):
def fbp_view(request):
return render(request, 'fbp.html')


Expand Down

0 comments on commit a16970e

Please sign in to comment.