Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7cbd750
init AgeGenderNet
justadudewhohacks Apr 21, 2019
e908bbd
init age gender example + some fixes
justadudewhohacks Apr 27, 2019
df5ac5d
improved drawing api
justadudewhohacks Apr 29, 2019
9a54b06
fixed examples
justadudewhohacks Apr 29, 2019
1519a74
fixed webcam examples
justadudewhohacks Apr 30, 2019
9ca0e1b
tbd node 12 on travis builds
justadudewhohacks Apr 30, 2019
256ee65
merge drawing-api into branch
justadudewhohacks May 1, 2019
4205fc2
allow face alignment before classification
justadudewhohacks May 3, 2019
7c7cf2a
PredictAgeAndGenderTask
justadudewhohacks May 4, 2019
5285804
use PredictAgeAndGenderTask in ageAndGenderRecognition example + alig…
justadudewhohacks May 4, 2019
58e1e11
fix tests + let typescript automatically figure out return values of …
justadudewhohacks May 5, 2019
d50c2b1
check in age_gender_model + AgeGenderNet loading from weightmap
justadudewhohacks May 5, 2019
5be059a
withAgeAndGender from detect faces tasks
justadudewhohacks May 6, 2019
aecac6c
age and gender webcam example
justadudewhohacks May 6, 2019
5ff0c5c
test cases for AgeGenderNet + fixed memory leaks and batch inputs for…
justadudewhohacks May 7, 2019
37609c2
move task composition test cases from tinyFaceDetector.test to global…
justadudewhohacks May 7, 2019
d2056b0
update readme part1
justadudewhohacks May 7, 2019
907ca4b
Merge branch 'age-gender' of https://github.com/justadudewhohacks/fac…
justadudewhohacks May 7, 2019
5aa3329
fixed some typos
justadudewhohacks May 7, 2019
5a45ad4
added age gender test results + model description
justadudewhohacks May 7, 2019
eb6c7a1
added description of new drawing api to README
justadudewhohacks May 7, 2019
731e34f
fix nodejs tests
justadudewhohacks May 7, 2019
84ec126
age gender recognition nodejs example
justadudewhohacks May 7, 2019
49114d2
fix browser cpu tests
justadudewhohacks May 7, 2019
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
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
sudo: required
language: node_js
node_js:
- "node"
#- "node"
- "11"
- "10"
- "8"
# node 6 is not compatible with tfjs-node
Expand Down
467 changes: 291 additions & 176 deletions README.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions examples/examples-browser/public/js/commons.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ function renderNavBar(navbarId, exampleUri) {
uri: 'face_expression_recognition',
name: 'Face Expression Recognition'
},
{
uri: 'age_and_gender_recognition',
name: 'Age and Gender Recognition'
},
{
uri: 'face_recognition',
name: 'Face Recognition'
Expand All @@ -60,6 +64,10 @@ function renderNavBar(navbarId, exampleUri) {
uri: 'webcam_face_expression_recognition',
name: 'Webcam Face Expression Recognition'
},
{
uri: 'webcam_age_and_gender_recognition',
name: 'Webcam Age and Gender Recognition'
},
{
uri: 'bbt_face_landmark_detection',
name: 'BBT Face Landmark Detection'
Expand Down
42 changes: 0 additions & 42 deletions examples/examples-browser/public/js/drawing.js

This file was deleted.

2 changes: 2 additions & 0 deletions examples/examples-browser/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ app.get('/', (req, res) => res.redirect('/face_detection'))
app.get('/face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceDetection.html')))
app.get('/face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'faceLandmarkDetection.html')))
app.get('/face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceExpressionRecognition.html')))
app.get('/age_and_gender_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'ageAndGenderRecognition.html')))
app.get('/face_extraction', (req, res) => res.sendFile(path.join(viewsDir, 'faceExtraction.html')))
app.get('/face_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'faceRecognition.html')))
app.get('/video_face_tracking', (req, res) => res.sendFile(path.join(viewsDir, 'videoFaceTracking.html')))
app.get('/webcam_face_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceDetection.html')))
app.get('/webcam_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceLandmarkDetection.html')))
app.get('/webcam_face_expression_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'webcamFaceExpressionRecognition.html')))
app.get('/webcam_age_and_gender_recognition', (req, res) => res.sendFile(path.join(viewsDir, 'webcamAgeAndGenderRecognition.html')))
app.get('/bbt_face_landmark_detection', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceLandmarkDetection.html')))
app.get('/bbt_face_similarity', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceSimilarity.html')))
app.get('/bbt_face_matching', (req, res) => res.sendFile(path.join(viewsDir, 'bbtFaceMatching.html')))
Expand Down
191 changes: 191 additions & 0 deletions examples/examples-browser/views/ageAndGenderRecognition.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html>
<head>
<script src="face-api.js"></script>
<script src="js/commons.js"></script>
<script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
<div id="navbar"></div>
<div class="center-content page-container">

<div class="progress" id="loader">
<div class="indeterminate"></div>
</div>
<div style="position: relative" class="margin">
<img id="inputImg" src="" style="max-width: 800px;" />
<canvas id="overlay" />
</div>

<div class="row side-by-side">
<!-- image_selection_control -->
<div id="selectList"></div>
<div class="row">
<label for="imgUrlInput">Get image from URL:</label>
<input id="imgUrlInput" type="text" class="bold">
</div>
<button
class="waves-effect waves-light btn"
onclick="loadImageFromUrl()"
>
Ok
</button>
<!-- image_selection_control -->
</div>

<div class="row side-by-side">

<!-- face_detector_selection_control -->
<div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
<select id="selectFaceDetector">
<option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
<option value="tiny_face_detector">Tiny Face Detector</option>
<option value="mtcnn">MTCNN</option>
</select>
<label>Select Face Detector</label>
</div>
<!-- face_detector_selection_control -->

</div>

<!-- ssd_mobilenetv1_controls -->
<span id="ssd_mobilenetv1_controls">
<div class="row side-by-side">
<div class="row">
<label for="minConfidence">Min Confidence:</label>
<input disabled value="0.5" id="minConfidence" type="text" class="bold">
</div>
<button
class="waves-effect waves-light btn"
onclick="onDecreaseMinConfidence()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseMinConfidence()"
>
<i class="material-icons left">+</i>
</button>
</div>
</span>
<!-- ssd_mobilenetv1_controls -->

<!-- tiny_face_detector_controls -->
<span id="tiny_face_detector_controls">
<div class="row side-by-side">
<div class="row input-field" style="margin-right: 20px;">
<select id="inputSize">
<option value="" disabled selected>Input Size:</option>
<option value="160">160 x 160</option>
<option value="224">224 x 224</option>
<option value="320">320 x 320</option>
<option value="416">416 x 416</option>
<option value="512">512 x 512</option>
<option value="608">608 x 608</option>
</select>
<label>Input Size</label>
</div>
<div class="row">
<label for="scoreThreshold">Score Threshold:</label>
<input disabled value="0.5" id="scoreThreshold" type="text" class="bold">
</div>
<button
class="waves-effect waves-light btn"
onclick="onDecreaseScoreThreshold()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseScoreThreshold()"
>
<i class="material-icons left">+</i>
</button>
</div>
</span>
<!-- tiny_face_detector_controls -->

<!-- mtcnn_controls -->
<span id="mtcnn_controls">
<div class="row side-by-side">
<div class="row">
<label for="minFaceSize">Minimum Face Size:</label>
<input disabled value="20" id="minFaceSize" type="text" class="bold">
</div>
<button
class="waves-effect waves-light btn"
onclick="onDecreaseMinFaceSize()"
>
<i class="material-icons left">-</i>
</button>
<button
class="waves-effect waves-light btn"
onclick="onIncreaseMinFaceSize()"
>
<i class="material-icons left">+</i>
</button>
</div>
</span>
<!-- mtcnn_controls -->

</body>

<script>

async function updateResults() {
if (!isFaceDetectionModelLoaded()) {
return
}

const inputImgEl = $('#inputImg').get(0)
const options = getFaceDetectorOptions()

const results = await faceapi.detectAllFaces(inputImgEl, options)
// compute face landmarks to align faces for better accuracy
.withFaceLandmarks()
.withAgeAndGender()

const canvas = $('#overlay').get(0)
faceapi.matchDimensions(canvas, inputImgEl)

const resizedResults = faceapi.resizeResults(results, inputImgEl)
faceapi.draw.drawDetections(canvas, resizedResults)

resizedResults.forEach(result => {
const { age, gender, genderProbability } = result
new faceapi.draw.DrawTextField(
[
`${faceapi.round(age, 0)} years`,
`${gender} (${faceapi.round(genderProbability)})`
],
result.detection.box.bottomLeft
).draw(canvas)
})
}

async function run() {
// load face detection and age and gender recognition models
// and load face landmark model for face alignment
await changeFaceDetector(SSD_MOBILENETV1)
await faceapi.loadFaceLandmarkModel('/')
await faceapi.nets.ageGenderNet.load('/')

// start processing image
updateResults()
}

$(document).ready(function() {
renderNavBar('#navbar', 'age_and_gender_recognition')
initImageSelectionControls('happy.jpg', true)
initFaceDetectionControls()
run()
})
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion examples/examples-browser/views/batchFaceLandmarks.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
function drawLandmarkCanvas(img, landmarks) {
const canvas = faceapi.createCanvasFromMedia(img)
$('#faceContainer').append(canvas)
faceapi.drawLandmarks(canvas, landmarks, { lineWidth: 2 , drawLines: true })
new faceapi.draw.DrawFaceLandmarks(landmarks).draw(canvas)
}

async function runLandmarkDetection(useBatchInput) {
Expand Down
11 changes: 4 additions & 7 deletions examples/examples-browser/views/batchFaceRecognition.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,10 @@
$('#faceContainer').append(canvas)

const x = 20, y = canvas.height - 20
faceapi.drawText(
canvas.getContext('2d'),
x,
y,
faceMatcher.findBestMatch(descriptor).toString(),
Object.assign(faceapi.getDefaultDrawOptions(), { color: 'red', fontSize: 16 })
)
const ctx = faceapi.getContext2dOrThrow(canvas)
ctx.font = '16px Georgia'
ctx.fillStyle = 'red'
ctx.fillText(faceMatcher.findBestMatch(descriptor).toString(), x, y)
}

async function runComputeFaceDescriptors(useBatchInput) {
Expand Down
4 changes: 2 additions & 2 deletions examples/examples-browser/views/bbtFaceLandmarkDetection.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
const canvas = faceapi.createCanvasFromMedia(currentImg)
$('#faceContainer').empty()
$('#faceContainer').append(canvas)
faceapi.drawLandmarks(canvas, landmarks, { lineWidth: drawLines ? 2 : 4, drawLines })
new faceapi.draw.DrawFaceLandmarks(landmarks, { drawLines }).draw(canvas)
}

async function onSelectionChanged(uri) {
currentImg = await faceapi.fetchImage(uri)
landmarks = await faceapi.detectLandmarks(currentImg)
landmarks = await faceapi.detectFaceLandmarks(currentImg)
redraw()
}

Expand Down
21 changes: 11 additions & 10 deletions examples/examples-browser/views/bbtFaceRecognition.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<head>
<script src="face-api.js"></script>
<script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script>
<script src="js/bbt.js"></script>
Expand Down Expand Up @@ -159,17 +158,19 @@

function drawFaceRecognitionResults(results) {
const canvas = $('#overlay').get(0)
const inputImgEl = $('#inputImg').get(0)

faceapi.matchDimensions(canvas, inputImgEl)
// resize detection and landmarks in case displayed image is smaller than
// original size
resizedResults = resizeCanvasAndResults($('#inputImg').get(0), canvas, results)

const boxesWithText = resizedResults.map(({ detection, descriptor }) =>
new faceapi.BoxWithText(
detection.box,
faceMatcher.findBestMatch(descriptor).toString()
)
)
faceapi.drawDetection(canvas, boxesWithText)
const resizedResults = faceapi.resizeResults(results, inputImgEl)

resizedResults.forEach(({ detection, descriptor }) => {
const label = faceMatcher.findBestMatch(descriptor).toString()
const options = { label }
const drawBox = new faceapi.draw.DrawBox(detection.box, options)
drawBox.draw(canvas)
})
}

async function run() {
Expand Down
5 changes: 3 additions & 2 deletions examples/examples-browser/views/faceDetection.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<head>
<script src="face-api.js"></script>
<script src="js/commons.js"></script>
<script src="js/drawing.js"></script>
<script src="js/faceDetectionControls.js"></script>
<script src="js/imageSelectionControls.js"></script>
<link rel="stylesheet" href="styles.css">
Expand Down Expand Up @@ -148,7 +147,9 @@

const results = await faceapi.detectAllFaces(inputImgEl, options)

drawDetections(inputImgEl, $('#overlay').get(0), results)
const canvas = $('#overlay').get(0)
faceapi.matchDimensions(canvas, inputImgEl)
faceapi.draw.drawDetections(canvas, faceapi.resizeResults(results, inputImgEl))
}

async function run() {
Expand Down
Loading