Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cda5b1a
Added results from technical report the repo
oarriaga Jul 14, 2017
a99377e
Update README.md
oarriaga Jul 14, 2017
5b09e94
Update README.md
oarriaga Jul 14, 2017
1521f37
Update README.md
oarriaga Jul 14, 2017
56024ec
Update README.md
oarriaga Jul 14, 2017
a63654b
Update REQUIREMENTS.txt
oarriaga Jul 14, 2017
218155a
Update README.md
oarriaga Jul 14, 2017
ba3d57e
Update README.md
oarriaga Jul 14, 2017
373cd12
Update REQUIREMENTS.txt
oarriaga Jul 22, 2017
e2ec674
Add webservice.
wilderrodrigues Aug 17, 2017
ea8fe96
Dockerize the project to avoid manual installation of dependencies.
wilderrodrigues Aug 17, 2017
4953c2f
Add instructions on how to run with docker.
wilderrodrigues Aug 17, 2017
399867b
Rename endpoint.
wilderrodrigues Sep 19, 2017
bd9a0a0
Rename endpoint and fix opencv version.
wilderrodrigues Sep 19, 2017
6d9e711
Fix parameter name.
wilderrodrigues Sep 19, 2017
4aad9c7
updated report
oarriaga Oct 23, 2017
4ea2758
Update README.md
oarriaga Oct 24, 2017
0f5a08e
Update README.md
oarriaga Nov 7, 2017
f4e8817
Update README.md
oarriaga Nov 7, 2017
5bc94fd
Merge pull request #16 from ekholabs/master
oarriaga Nov 30, 2017
eb5d76f
Update README.md
oarriaga Nov 30, 2017
f96450c
Update REQUIREMENTS.txt
krunal704 Aug 6, 2018
0b904af
Added PEP8 conventions to utils
oarriaga Aug 27, 2018
ac27da0
Added PEP8 conventions to models
oarriaga Aug 27, 2018
6b68515
Merge pull request #82 from krunal704/patch-1
oarriaga Oct 23, 2018
8c6f112
Destroy Window
gokaco Nov 23, 2018
1635d16
Destroy Window
gokaco Nov 23, 2018
4b072a7
Update README.md
oarriaga Jan 25, 2019
71f254a
Merge pull request #98 from gokaco/patch-1
oarriaga May 22, 2019
2f152a2
Merge pull request #99 from gokaco/patch-2
oarriaga May 22, 2019
b861d21
Update README.md
oarriaga Oct 29, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM debian:latest

RUN apt-get -y update && apt-get install -y git python3-pip python3-dev python3-tk vim procps curl

#Face classificarion dependencies & web application
RUN pip3 install numpy scipy scikit-learn pillow tensorflow pandas h5py opencv-python==3.2.0.8 keras statistics pyyaml pyparsing cycler matplotlib Flask

ADD . /ekholabs/face-classifier

WORKDIR ekholabs/face-classifier

ENV PYTHONPATH=$PYTHONPATH:src
ENV FACE_CLASSIFIER_PORT=8084
EXPOSE $FACE_CLASSIFIER_PORT

ENTRYPOINT ["python3"]
CMD ["src/web/faces.py"]
47 changes: 38 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
# Face classification and detection
# This repository is deprecated for at TF-2.0 rewrite visit:
# https://github.com/oarriaga/paz
------------------------------------------------
# Face classification and detection.
Real-time face detection and emotion/gender classification using fer2013/IMDB datasets with a keras CNN model and openCV.
* IMDB gender classification test accuracy: 96%.
* fer2013 emotion classification test accuracy: 66%.

For more information please consult the [publication](https://github.com/oarriaga/face_classification/blob/master/report.pdf)

# Emotion/gender examples:

![alt tag](images/demo_results.png)

Guided back-prop
![alt tag](images/gradcam_results.png)

Real-time demo:
<div align='center'>
<img src='images/color_demo.gif' width='400px'>
</div>

Emotion/gender classification of the [B-IT-BOTS](https://mas-group.inf.h-brs.de/?page_id=622) robotics team :)
![alt tag](images/predicted_test_image.png)

Emotion examples
![alt tag](images/emotion_classification.jpg)
[B-IT-BOTS](https://mas-group.inf.h-brs.de/?page_id=622) robotics team :)
![alt tag](images/robocup_team.png)

## Instructions

### Run real-time emotion demo:
> python3 video_emotion_color_demo.py

### Run real-time guided back-prop demo:
> python3 image_gradcam_demo.py

### Make inference on single images:
> python3 image_emotion_gender_demo.py <image_path>

e.g.

> python3 image_emotion_gender_demo.py ../images/test_image.jpg

### Running with Docker

With a few steps one can get its own face classification and detection running. Follow the commands below:

* ```docker pull ekholabs/face-classifier```
* ```docker run -d -p 8084:8084 --name=face-classifier ekholabs/face-classifier```
* ```curl -v -F image=@[path_to_image] http://localhost:8084/classifyImage > image.png```

### To train previous/new models for emotion classification:


Expand All @@ -38,7 +68,6 @@ Emotion examples
* Untar the file:
> tar -xfv imdb_crop.tar

* Run the train_emotion_classification.py file
> python3 train_emotion_classifier.py

* Run the train_gender_classification.py file
> python3 train_gender_classifier.py

6 changes: 2 additions & 4 deletions REQUIREMENTS.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
keras==2.0.3
keras==2.0.5
tensorflow==1.1.0
pandas==0.19.1
numpy==1.12.1
h5py==2.7.0
statistics

#optional for video_test.py
opencv2-python==3.2.0
opencv-python==3.2.0
Binary file added images/demo_results.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/gradcam_results.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file renamed technical_report.pdf → report.pdf
Binary file not shown.
51 changes: 28 additions & 23 deletions src/models/cnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from keras import layers
from keras.regularizers import l2


def simple_CNN(input_shape, num_classes):

model = Sequential()
Expand Down Expand Up @@ -48,11 +49,13 @@ def simple_CNN(input_shape, num_classes):

model.add(Convolution2D(filters=256, kernel_size=(3, 3), padding='same'))
model.add(BatchNormalization())
model.add(Convolution2D(filters=num_classes, kernel_size=(3, 3), padding='same'))
model.add(Convolution2D(
filters=num_classes, kernel_size=(3, 3), padding='same'))
model.add(GlobalAveragePooling2D())
model.add(Activation('softmax',name='predictions'))
model.add(Activation('softmax', name='predictions'))
return model


def simpler_CNN(input_shape, num_classes):

model = Sequential()
Expand Down Expand Up @@ -100,21 +103,22 @@ def simpler_CNN(input_shape, num_classes):
strides=(2, 2), padding='same'))

model.add(Flatten())
#model.add(GlobalAveragePooling2D())
model.add(Activation('softmax',name='predictions'))
# model.add(GlobalAveragePooling2D())
model.add(Activation('softmax', name='predictions'))
return model


def tiny_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
regularization = l2(l2_regularization)

# base
img_input = Input(input_shape)
x = Conv2D(5, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
use_bias=False)(img_input)
use_bias=False)(img_input)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(5, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
use_bias=False)(x)
use_bias=False)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)

Expand Down Expand Up @@ -191,10 +195,10 @@ def tiny_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
x = layers.add([x, residual])

x = Conv2D(num_classes, (3, 3),
#kernel_regularizer=regularization,
padding='same')(x)
# kernel_regularizer=regularization,
padding='same')(x)
x = GlobalAveragePooling2D()(x)
output = Activation('softmax',name='predictions')(x)
output = Activation('softmax', name='predictions')(x)

model = Model(img_input, output)
return model
Expand All @@ -206,11 +210,11 @@ def mini_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
# base
img_input = Input(input_shape)
x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
use_bias=False)(img_input)
use_bias=False)(img_input)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Conv2D(8, (3, 3), strides=(1, 1), kernel_regularizer=regularization,
use_bias=False)(x)
use_bias=False)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)

Expand Down Expand Up @@ -287,14 +291,15 @@ def mini_XCEPTION(input_shape, num_classes, l2_regularization=0.01):
x = layers.add([x, residual])

x = Conv2D(num_classes, (3, 3),
#kernel_regularizer=regularization,
padding='same')(x)
# kernel_regularizer=regularization,
padding='same')(x)
x = GlobalAveragePooling2D()(x)
output = Activation('softmax',name='predictions')(x)
output = Activation('softmax', name='predictions')(x)

model = Model(img_input, output)
return model


def big_XCEPTION(input_shape, num_classes):
img_input = Input(input_shape)
x = Conv2D(32, (3, 3), strides=(2, 2), use_bias=False)(img_input)
Expand Down Expand Up @@ -331,10 +336,10 @@ def big_XCEPTION(input_shape, num_classes):
x = MaxPooling2D((3, 3), strides=(2, 2), padding='same')(x)
x = layers.add([x, residual])
x = Conv2D(num_classes, (3, 3),
#kernel_regularizer=regularization,
padding='same')(x)
# kernel_regularizer=regularization,
padding='same')(x)
x = GlobalAveragePooling2D()(x)
output = Activation('softmax',name='predictions')(x)
output = Activation('softmax', name='predictions')(x)

model = Model(img_input, output)
return model
Expand All @@ -343,11 +348,11 @@ def big_XCEPTION(input_shape, num_classes):
if __name__ == "__main__":
input_shape = (64, 64, 1)
num_classes = 7
#model = tiny_XCEPTION(input_shape, num_classes)
#model.summary()
#model = mini_XCEPTION(input_shape, num_classes)
#model.summary()
#model = big_XCEPTION(input_shape, num_classes)
#model.summary()
# model = tiny_XCEPTION(input_shape, num_classes)
# model.summary()
# model = mini_XCEPTION(input_shape, num_classes)
# model.summary()
# model = big_XCEPTION(input_shape, num_classes)
# model.summary()
model = simple_CNN((48, 48, 1), num_classes)
model.summary()
Loading