Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
Former-commit-id: f32e2c9
  • Loading branch information
ldulcic committed May 28, 2019
0 parents commit 177a76b
Show file tree
Hide file tree
Showing 19 changed files with 1,897 additions and 0 deletions.
216 changes: 216 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Created by .ignore support plugin (hsz.mobi)
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests
### Example user template template
### Example user template

# IntelliJ project files
.idea
*.iml
out
gen### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
### VirtualEnv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json

# Ignore Data
data
Empty file.
39 changes: 39 additions & 0 deletions arsfutura-face-similarity/collect_face_images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os
import cv2
import argparse


def main(directory, name, test):
cap = cv2.VideoCapture(0)

i = 0
while True:
# Capture frame-by-frame
ret, frame = cap.read()
frame = cv2.flip(frame, 1)

# Display the resulting frame
cv2.imshow(name, frame)
if not test and i != 0 and i % 10 == 0:
cv2.imwrite("{}/{}{}.png".format(directory, name, i / 10), frame)
i += 1
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# When everything done, release the captureq
cap.release()
cv2.destroyAllWindows()


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--person', required=True)
parser.add_argument('--test', action='store_true')
args = parser.parse_args()
directory = 'images/{}'.format(args.person)
if not args.test and not os.path.exists(directory):
os.mkdir(directory)
try:
main(directory, args.person, args.test)
except KeyboardInterrupt:
print "Photo session done for {} :)".format(args.person)
2 changes: 2 additions & 0 deletions arsfutura-face-similarity/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DATA_PATH = 'data/features/'
MODEL_PATH = 'models/model.pkl'
15 changes: 15 additions & 0 deletions arsfutura-face-similarity/dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pandas as pd
from constants import DATA_PATH

EMBEDDINGS_PATH = DATA_PATH + 'reps.csv'
LABELS_PATH = DATA_PATH + 'labels.csv'


def load_data():
embeddings = pd.read_csv(EMBEDDINGS_PATH, header=None).values
labels = map(lambda label: label.split('/')[-2].upper(), pd.read_csv(LABELS_PATH, header=None).values[:, 1].tolist())
return embeddings, labels


if __name__ == '__main__':
print load_data()
45 changes: 45 additions & 0 deletions arsfutura-face-similarity/predict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import openface
import cv2
import pickle
import numpy as np
from collections import namedtuple
from constants import MODEL_PATH

Face = namedtuple('Face', 'bb identity probability')

align = openface.AlignDlib('models/shape_predictor_68_face_landmarks.dat')
net = openface.TorchNeuralNet('models/nn4.small2.v1.t7', imgDim=96, cuda=False)
le, model = pickle.load(open(MODEL_PATH, 'rb'))


def faces_embeddings_and_bbs(img):
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
bb = align.getAllFaceBoundingBoxes(rgb_img)

aligned_faces = []
for box in bb:
aligned_faces.append(
align.align(
96,
rgb_img,
box,
landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE))

embeddings = np.array([net.forward(alignedFace) for alignedFace in aligned_faces])

return embeddings, bb


def predict(img):
embeddings, bb = faces_embeddings_and_bbs(img)
if embeddings.size == 0 or not bb:
return None
probs = model.predict_proba(embeddings)
predicted = probs.argmax(axis=1)
identities = le.inverse_transform(predicted)
probs = probs[np.arange(len(predicted)), predicted]
return [Face(box, identity, prob * 100) for identity, box, prob in zip(identities, bb, probs)]


if __name__ == '__main__':
predict('')
33 changes: 33 additions & 0 deletions arsfutura-face-similarity/real_time_face_detection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from __future__ import print_function, division

import cv2
from predict import predict


def main():
cap = cv2.VideoCapture(0)

while True:
# Capture frame-by-frame
ret, frame = cap.read()
frame = cv2.flip(frame, 1)

faces = predict(frame)
if faces is not None:
for face in faces:
cv2.rectangle(frame, (face.bb.left(), face.bb.top()), (face.bb.right(), face.bb.bottom()), (0, 255, 0), 2)
cv2.putText(frame, "%s %.2f%%" % (face.identity, face.probability),
(face.bb.left(), face.bb.bottom() + 20), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255, 255, 255), 1)

# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break

# When everything done, release the captureq
cap.release()
cv2.destroyAllWindows()


if __name__ == '__main__':
main()
42 changes: 42 additions & 0 deletions arsfutura-face-similarity/train.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import pickle
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
from dataset import load_data
from constants import MODEL_PATH
from sklearn.ensemble import RandomForestClassifier

CLASSIFIERS = {
'svm': (
SVC(decision_function_shape='ovr'),
[
{'C': [0.001, 0.1, 1, 10, 100, 1000], 'kernel': ['linear']},
{'C': [0.001, 0.1, 1, 10, 100, 1000], 'gamma': [100, 50, 10, 1, 0.01, 0.001, 0.0001], 'kernel': ['rbf']}
]
),
'logreg': (
LogisticRegression(max_iter=100000),
{'C': [0.001, 0.1, 1, 10, 100, 1000]}
)
}


def main():
X, y = load_data()
le = LabelEncoder()
le.fit(y)

classifier = CLASSIFIERS['logreg']

clf = GridSearchCV(classifier[0], classifier[1], cv=5, verbose=1)
clf.fit(X, le.transform(y))

print clf.best_params_
print classification_report(le.transform(y), clf.predict(X), target_names=le.classes_)
pickle.dump((le, clf), open(MODEL_PATH, 'wb'))


if __name__ == '__main__':
main()
Empty file.
Loading

0 comments on commit 177a76b

Please sign in to comment.