Make OpenFace work with Python 3 (#231)

* Make OpenFace Python 3 compatible, retaining Python 2 compatibility.
Tests could be parameterised to test for either Python 2 or 3.
Tests currently fail due to different library calculation outcomes?

* Tiny change to remove the dependency on nosetest3.

* Dockerfile updates for OpenFace + Python3 + Dlib19.2 + OpenCV3.2

* Revert "Dockerfile updates for OpenFace + Python3 + Dlib19.2 + OpenCV3.2"

This reverts commit ec08fc9226.

* Change for python2 backwards compatibility

* Change for python2 backwards compatibility

* Change to ensure python2 backwards compatibility

* Change to ensure python2 backwards compatibility
This commit is contained in:
Andrew 2017-04-25 07:50:16 +10:00 committed by Brandon Amos
parent 9c02f78a86
commit 71ee6ee747
11 changed files with 85 additions and 67 deletions

View File

@ -26,6 +26,7 @@ import argparse
import cv2
import os
import pickle
import sys
from operator import itemgetter
@ -171,8 +172,11 @@ def train(args):
def infer(args, multiple=False):
with open(args.classifierModel, 'r') as f:
with open(args.classifierModel, 'rb') as f:
if sys.version_info[0] < 3:
(le, clf) = pickle.load(f)
else:
(le, clf) = pickle.load(f, encoding='latin1')
for img in args.imgs:
print("\n=== {} ===".format(img))
@ -190,10 +194,10 @@ def infer(args, multiple=False):
if args.verbose:
print("Prediction took {} seconds.".format(time.time() - start))
if multiple:
print("Predict {} @ x={} with {:.2f} confidence.".format(person, bbx,
print("Predict {} @ x={} with {:.2f} confidence.".format(person.decode('utf-8'), bbx,
confidence))
else:
print("Predict {} with {:.2f} confidence.".format(person, confidence))
print("Predict {} with {:.2f} confidence.".format(person.decode('utf-8'), confidence))
if isinstance(clf, GMM):
dist = np.linalg.norm(rep - clf.means_[maxI])
print(" + Distance from the mean: {}".format(dist))

View File

@ -33,6 +33,7 @@ import argparse
import cv2
import os
import pickle
import sys
import numpy as np
np.set_printoptions(precision=2)
@ -97,13 +98,16 @@ def getRep(bgrImg):
print("Neural network forward pass took {} seconds.".format(
time.time() - start))
# print reps
# print (reps)
return reps
def infer(img, args):
with open(args.classifierModel, 'r') as f:
if sys.version_info[0] < 3:
(le, clf) = pickle.load(f) # le - label and clf - classifer
else:
(le, clf) = pickle.load(f, encoding='latin1') # le - label and clf - classifer
reps = getRep(img)
persons = []
@ -112,21 +116,21 @@ def infer(img, args):
try:
rep = rep.reshape(1, -1)
except:
print "No Face detected"
print ("No Face detected")
return (None, None)
start = time.time()
predictions = clf.predict_proba(rep).ravel()
# print predictions
# print (predictions)
maxI = np.argmax(predictions)
# max2 = np.argsort(predictions)[-3:][::-1][1]
persons.append(le.inverse_transform(maxI))
# print str(le.inverse_transform(max2)) + ": "+str( predictions [max2])
# print (str(le.inverse_transform(max2)) + ": "+str( predictions [max2]))
# ^ prints the second prediction
confidences.append(predictions[maxI])
if args.verbose:
print("Prediction took {} seconds.".format(time.time() - start))
pass
# print("Predict {} with {:.2f} confidence.".format(person, confidence))
# print("Predict {} with {:.2f} confidence.".format(person.decode('utf-8'), confidence))
if isinstance(clf, GMM):
dist = np.linalg.norm(rep - clf.means_[maxI])
print(" + Distance from the mean: {}".format(dist))
@ -185,7 +189,7 @@ if __name__ == '__main__':
while True:
ret, frame = video_capture.read()
persons, confidences = infer(frame, args)
print "P: " + str(persons) + " C: " + str(confidences)
print ("P: " + str(persons) + " C: " + str(confidences))
try:
# append with two floating point precision
confidenceList.append('%.2f' % confidences[0])

View File

@ -181,10 +181,13 @@ def getRep(imgPath):
def inferFromTest(args):
for clfChoice in clfChoices:
print "==============="
print "Using the classifier: " + clfChoice
print ("===============")
print ("Using the classifier: " + clfChoice)
with open(os.path.join(args.featureFolder[0], clfChoice + ".pkl"), 'r') as f_clf:
if sys.version_info[0] < 3:
(le, clf) = pickle.load(f_clf)
else:
(le, clf) = pickle.load(f_clf, encoding='latin1')
correctPrediction = 0
inCorrectPrediction = 0
@ -204,7 +207,7 @@ def inferFromTest(args):
try:
rep = getRep(img).reshape(1, -1)
except Exception as e:
print e
print (e)
continue
start = time.time()
predictions = clf.predict_proba(rep).ravel()
@ -218,7 +221,7 @@ def inferFromTest(args):
if args.verbose:
print(
"Predict {} with {:.2f} confidence.".format(
person, confidence))
person.decode('utf-8'), confidence))
sumConfidence += confidence
@ -234,11 +237,11 @@ def inferFromTest(args):
dist = np.linalg.norm(rep - clf.means_[maxI])
print(" + Distance from the mean: {}".format(dist))
print "Results for the classifier: " + clfChoice
print "Correct Prediction :" + str(correctPrediction)
print "In-correct Prediction: " + str(inCorrectPrediction)
print "Accuracy :" + str(float(correctPrediction) / (correctPrediction + inCorrectPrediction))
print "Avg Confidence: " + str(float(sumConfidence) / (correctPrediction + inCorrectPrediction))
print ("Results for the classifier: " + clfChoice)
print ("Correct Prediction :" + str(correctPrediction))
print ("In-correct Prediction: " + str(inCorrectPrediction))
print ("Accuracy :" + str(float(correctPrediction) / (correctPrediction + inCorrectPrediction)))
print ("Avg Confidence: " + str(float(sumConfidence) / (correctPrediction + inCorrectPrediction)))
def preprocess(args):
@ -256,8 +259,8 @@ def preprocess(args):
try:
noOfImages.append(len(os.listdir(folder)))
folderName.append(folder.split('/')[-1:][0])
# print folder.split('/')[-1:][0] +": " +
# str(len(os.listdir(folder)))
# print (folder.split('/')[-1:][0] +": " +
# str(len(os.listdir(folder))))
except:
pass
@ -269,7 +272,7 @@ def preprocess(args):
for f, n in zip(folderName_sorted, noOfImages_sorted):
text_file.write("{} : {} \n".format(f, n))
if args.verbose:
print "Sorting lfw dataset took {} seconds.".format(time.time() - start)
print ("Sorting lfw dataset took {} seconds.".format(time.time() - start))
start = time.time()
# Copy known train dataset
@ -289,7 +292,7 @@ def preprocess(args):
print('Directory not copied. Error: %s' % e)
if args.verbose:
print "Copying train dataset from lfw took {} seconds.".format(time.time() - start)
print ("Copying train dataset from lfw took {} seconds.".format(time.time() - start))
start = time.time()
# Take 10% images from train dataset as test dataset for known
@ -309,8 +312,8 @@ def preprocess(args):
destPath, 'test_known_raw', folder.split('/')[-1:][0])):
os.makedirs(os.path.join(destPath, 'test_known_raw',
folder.split('/')[-1:][0]))
# print "Created {}".format(os.path.join(destPath,
# 'test_known_raw', folder.split('/')[-1:][0]))
# print ("Created {}".format(os.path.join(destPath,
# 'test_known_raw', folder.split('/')[-1:][0])))
for i in range(int(0.9 * len(images)), len(images)):
destFile = os.path.join(destPath, 'test_known_raw', folder.split(
'/')[-1:][0], images[i].split('/')[-1:][0])
@ -319,7 +322,7 @@ def preprocess(args):
except:
pass
if args.verbose:
print "Spliting lfw dataset took {} seconds.".format(time.time() - start)
print ("Spliting lfw dataset took {} seconds.".format(time.time() - start))
start = time.time()
# Copy unknown test dataset
@ -339,7 +342,7 @@ def preprocess(args):
print('Directory not copied. Error: %s' % e)
if args.verbose:
print "Copying test dataset from lfw took {} seconds.".format(time.time() - start)
print ("Copying test dataset from lfw took {} seconds.".format(time.time() - start))
start = time.time()
class Args():
@ -380,7 +383,7 @@ def preprocess(args):
p.join()
if args.verbose:
print "Aligning the raw train data took {} seconds.".format(time.time() - start)
print ("Aligning the raw train data took {} seconds.".format(time.time() - start))
start = time.time()
os.system(
@ -394,7 +397,7 @@ def preprocess(args):
'train_known_aligned'))
if args.verbose:
print "Extracting features from aligned train data took {} seconds.".format(time.time() - start)
print ("Extracting features from aligned train data took {} seconds.".format(time.time() - start))
start = time.time()

View File

@ -125,7 +125,10 @@ def cacheToFile(file_name):
def decorator(original_func):
global cache
try:
if sys.version_info[0] < 3:
cache = pickle.load(open(file_name, 'rb'))
else:
cache = pickle.load(open(file_name, 'rb'), encoding='latin1')
except:
cache = None

View File

@ -1,7 +1,9 @@
# flake8: noqa
from __future__ import absolute_import
from .align_dlib import AlignDlib
from .torch_neural_net import TorchNeuralNet
import data
import helper
from . import data
from . import helper

View File

@ -81,7 +81,7 @@ class TorchNeuralNet:
'-model', model, '-imgDim', str(imgDim)]
if cuda:
self.cmd.append('-cuda')
self.p = Popen(self.cmd, stdin=PIPE, stdout=PIPE, bufsize=0)
self.p = Popen(self.cmd, stdin=PIPE, stdout=PIPE, bufsize=0, universal_newlines=True)
def exitHandler():
if self.p.poll() is None:
@ -160,7 +160,7 @@ cmd: {}
stdout: {}
""".format(self.cmd, self.p.stdout.read()))
self.p.stdin.write(imgPath + "\n")
self.p.stdin.write(imgPath + '\n')
output = self.p.stdout.readline()
try:
rep = [float(x) for x in output.strip().split(',')]

View File

@ -4,4 +4,4 @@ set -e
cd $(dirname $0)
nosetests-2.7 -v
nosetests -v

View File

@ -52,6 +52,8 @@ def test_pipeline():
# assert np.isclose(norm(rgbImg), 11.1355)
bb = align.getLargestFaceBoundingBox(rgbImg)
print ("Bounding box found was: ")
print (bb)
assert bb.left() == 341
assert bb.right() == 1006
assert bb.top() == 193

View File

@ -40,19 +40,19 @@ def test_batch_represent():
workDir = tempfile.mkdtemp(prefix='OpenFaceBatchRep-')
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(workDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert p.returncode == 0
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(workDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
@ -61,7 +61,7 @@ def test_batch_represent():
cmd = ['th', './batch-represent/main.lua',
'-data', os.path.join(workDir, 'aligned'),
'-outDir', os.path.join(workDir, 'reps')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)

View File

@ -28,61 +28,61 @@ lfwSubset = os.path.join(openfaceDir, 'data', 'lfw-subset')
def test_compare_demo():
cmd = ['python2', os.path.join(openfaceDir, 'demos', 'compare.py'),
cmd = ['python3', os.path.join(openfaceDir, 'demos', 'compare.py'),
os.path.join(exampleImages, 'lennon-1.jpg'),
os.path.join(exampleImages, 'lennon-2.jpg')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert "0.763" in out
assert '0.763' in out
def test_classification_demo_pretrained():
cmd = ['python2', os.path.join(openfaceDir, 'demos', 'classifier.py'),
cmd = ['python3', os.path.join(openfaceDir, 'demos', 'classifier.py'),
'infer',
os.path.join(openfaceDir, 'models', 'openface',
'celeb-classifier.nn4.small2.v1.pkl'),
os.path.join(exampleImages, 'carell.jpg')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert "Predict SteveCarell with 0.97 confidence." in out
assert 'Predict SteveCarell with 0.97 confidence.' in out
def test_classification_demo_pretrained_multi():
cmd = ['python2', os.path.join(openfaceDir, 'demos', 'classifier.py'),
cmd = ['python3', os.path.join(openfaceDir, 'demos', 'classifier.py'),
'infer', '--multi',
os.path.join(openfaceDir, 'models', 'openface',
'celeb-classifier.nn4.small2.v1.pkl'),
os.path.join(exampleImages, 'longoria-cooper.jpg')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert "Predict EvaLongoria @ x=91 with 0.99 confidence." in out
assert "Predict BradleyCooper @ x=191 with 0.99 confidence." in out
assert 'Predict EvaLongoria @ x=91 with 0.99 confidence.' in out
assert 'Predict BradleyCooper @ x=191 with 0.99 confidence.' in out
def test_classification_demo_training():
assert os.path.isdir(lfwSubset), "Get lfw-subset by running ./data/download-lfw-subset.sh"
assert os.path.isdir(lfwSubset), 'Get lfw-subset by running ./data/download-lfw-subset.sh'
workDir = tempfile.mkdtemp(prefix='OpenFaceCls-')
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(workDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert p.returncode == 0
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(workDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
@ -91,26 +91,26 @@ def test_classification_demo_training():
cmd = ['th', './batch-represent/main.lua',
'-data', os.path.join(workDir, 'aligned'),
'-outDir', os.path.join(workDir, 'reps')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert p.returncode == 0
cmd = ['python2', os.path.join(openfaceDir, 'demos', 'classifier.py'),
cmd = ['python3', os.path.join(openfaceDir, 'demos', 'classifier.py'),
'train',
os.path.join(workDir, 'reps')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert p.returncode == 0
cmd = ['python2', os.path.join(openfaceDir, 'demos', 'classifier.py'),
cmd = ['python3', os.path.join(openfaceDir, 'demos', 'classifier.py'),
'infer',
os.path.join(workDir, 'reps', 'classifier.pkl'),
os.path.join(lfwSubset, 'raw', 'Adrien_Brody', 'Adrien_Brody_0001.jpg')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)

View File

@ -37,19 +37,19 @@ def test_dnn_training():
lfwSubset), "Get lfw-subset by running ./data/download-lfw-subset.sh"
imgWorkDir = tempfile.mkdtemp(prefix='OpenFaceTrainingTest-Img-')
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(imgWorkDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
assert p.returncode == 0
cmd = ['python2', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
cmd = ['python3', os.path.join(openfaceDir, 'util', 'align-dlib.py'),
os.path.join(lfwSubset, 'raw'), 'align', 'outerEyesAndNose',
os.path.join(imgWorkDir, 'aligned')]
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)
@ -69,7 +69,7 @@ def test_dnn_training():
'-cuda', '-cudnn', '-testing',
'-nDonkeys', '-1']
p = Popen(cmd, stdout=PIPE, stderr=PIPE,
cwd=os.path.join(openfaceDir, 'training'))
cwd=os.path.join(openfaceDir, 'training'), universal_newlines=True)
(out, err) = p.communicate()
print(out)
print(err)