Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
face
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Кубота
face
Commits
3f1826ab
Commit
3f1826ab
authored
Jul 14, 2018
by
vincent
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added examples for mtcnn face detection + added getters to FaceDetection
parent
2b794bc3
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
196 additions
and
44 deletions
+196
-44
commons.js
examples/public/commons.js
+9
-2
server.js
examples/server.js
+1
-0
mtcnnFaceDetection.html
examples/views/mtcnnFaceDetection.html
+12
-11
mtcnnFaceDetectionVideo.html
examples/views/mtcnnFaceDetectionVideo.html
+24
-26
mtcnnFaceDetectionWebcam.html
examples/views/mtcnnFaceDetectionWebcam.html
+125
-0
FaceDetection.ts
src/FaceDetection.ts
+25
-5
No files found.
examples/public/commons.js
View file @
3f1826ab
...
@@ -123,6 +123,10 @@ function renderNavBar(navbarId, exampleUri) {
...
@@ -123,6 +123,10 @@ function renderNavBar(navbarId, exampleUri) {
name
:
'MTCNN Face Detection Video'
name
:
'MTCNN Face Detection Video'
},
},
{
{
uri
:
'mtcnn_face_detection_webcam'
,
name
:
'MTCNN Face Detection Webcam'
},
{
uri
:
'batch_face_landmarks'
,
uri
:
'batch_face_landmarks'
,
name
:
'Batch Face Landmarks'
name
:
'Batch Face Landmarks'
},
},
...
@@ -159,7 +163,7 @@ function renderNavBar(navbarId, exampleUri) {
...
@@ -159,7 +163,7 @@ function renderNavBar(navbarId, exampleUri) {
githubLink
.
id
=
'github-link'
githubLink
.
id
=
'github-link'
githubLink
.
href
=
'https://github.com/justadudewhohacks/face-api.js'
githubLink
.
href
=
'https://github.com/justadudewhohacks/face-api.js'
const
h5
=
document
.
createElement
(
'h5'
)
const
h5
=
document
.
createElement
(
'h5'
)
h5
.
innerHTML
=
'face-api.js'
//'If you like this project, feel free to leave a star on github :)'
h5
.
innerHTML
=
'face-api.js'
githubLink
.
appendChild
(
h5
)
githubLink
.
appendChild
(
h5
)
const
githubLinkIcon
=
document
.
createElement
(
'img'
)
const
githubLinkIcon
=
document
.
createElement
(
'img'
)
githubLinkIcon
.
src
=
'github_link_icon.png'
githubLinkIcon
.
src
=
'github_link_icon.png'
...
@@ -176,7 +180,10 @@ function renderNavBar(navbarId, exampleUri) {
...
@@ -176,7 +180,10 @@ function renderNavBar(navbarId, exampleUri) {
const
a
=
document
.
createElement
(
'a'
)
const
a
=
document
.
createElement
(
'a'
)
a
.
classList
.
add
(
'waves-effect'
,
'waves-light'
)
a
.
classList
.
add
(
'waves-effect'
,
'waves-light'
)
a
.
href
=
ex
.
uri
a
.
href
=
ex
.
uri
a
.
innerHTML
=
ex
.
name
const
span
=
document
.
createElement
(
'span'
)
span
.
innerHTML
=
ex
.
name
span
.
style
.
whiteSpace
=
'nowrap'
a
.
appendChild
(
span
)
li
.
appendChild
(
a
)
li
.
appendChild
(
a
)
menuContent
.
appendChild
(
li
)
menuContent
.
appendChild
(
li
)
})
})
...
...
examples/server.js
View file @
3f1826ab
...
@@ -26,6 +26,7 @@ app.get('/face_alignment', (req, res) => res.sendFile(path.join(viewsDir, 'faceA
...
@@ -26,6 +26,7 @@ app.get('/face_alignment', (req, res) => res.sendFile(path.join(viewsDir, 'faceA
app
.
get
(
'/detect_and_recognize_faces'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'detectAndRecognizeFaces.html'
)))
app
.
get
(
'/detect_and_recognize_faces'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'detectAndRecognizeFaces.html'
)))
app
.
get
(
'/mtcnn_face_detection'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'mtcnnFaceDetection.html'
)))
app
.
get
(
'/mtcnn_face_detection'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'mtcnnFaceDetection.html'
)))
app
.
get
(
'/mtcnn_face_detection_video'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'mtcnnFaceDetectionVideo.html'
)))
app
.
get
(
'/mtcnn_face_detection_video'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'mtcnnFaceDetectionVideo.html'
)))
app
.
get
(
'/mtcnn_face_detection_webcam'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'mtcnnFaceDetectionWebcam.html'
)))
app
.
get
(
'/batch_face_landmarks'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'batchFaceLandmarks.html'
)))
app
.
get
(
'/batch_face_landmarks'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'batchFaceLandmarks.html'
)))
app
.
get
(
'/batch_face_recognition'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'batchFaceRecognition.html'
)))
app
.
get
(
'/batch_face_recognition'
,
(
req
,
res
)
=>
res
.
sendFile
(
path
.
join
(
viewsDir
,
'batchFaceRecognition.html'
)))
...
...
examples/views/mtcnnFaceDetection.html
View file @
3f1826ab
...
@@ -52,10 +52,10 @@
...
@@ -52,10 +52,10 @@
</div>
</div>
<script>
<script>
let
minFaceSize
=
50
//20 //
let
minFaceSize
=
50
let
scaleFactor
=
0.709
// 0.2
let
scaleFactor
=
0.709
let
maxNumScales
=
10
// 0.2
let
maxNumScales
=
10
let
stage1Threshold
=
0.
6
let
stage1Threshold
=
0.
7
let
stage2Threshold
=
0.7
let
stage2Threshold
=
0.7
let
stage3Threshold
=
0.7
let
stage3Threshold
=
0.7
let
mtcnn
let
mtcnn
...
@@ -85,13 +85,15 @@
...
@@ -85,13 +85,15 @@
canvas
.
width
=
width
canvas
.
width
=
width
canvas
.
height
=
height
canvas
.
height
=
height
const
scoreThresholds
=
[
stage1Threshold
,
stage2Threshold
,
stage3Threshold
]
const
mtcnnParams
=
{
const
{
results
,
stats
}
=
await
mtcnn
.
forwardWithStats
(
inputImgEl
,
minFaceSize
,
scaleFactor
,
maxNumScales
,
scoreThresholds
)
minFaceSize
,
scaleFactor
,
console
.
log
(
stats
)
maxNumScales
,
scoreThresholds
:
[
stage1Threshold
,
stage2Threshold
,
stage3Threshold
]
}
const
results
=
await
faceapi
.
mtcnn
(
inputImgEl
,
mtcnnParams
)
if
(
results
)
{
if
(
results
)
{
const
{
faceDetection
,
faceLandmarks
}
=
results
results
.
forEach
(({
faceDetection
,
faceLandmarks
})
=>
{
results
.
forEach
(({
faceDetection
,
faceLandmarks
})
=>
{
faceapi
.
drawDetection
(
'overlay'
,
faceDetection
.
forSize
(
width
,
height
))
faceapi
.
drawDetection
(
'overlay'
,
faceDetection
.
forSize
(
width
,
height
))
faceapi
.
drawLandmarks
(
'overlay'
,
faceLandmarks
.
forSize
(
width
,
height
),
{
lineWidth
:
4
,
color
:
'red'
})
faceapi
.
drawLandmarks
(
'overlay'
,
faceLandmarks
.
forSize
(
width
,
height
),
{
lineWidth
:
4
,
color
:
'red'
})
...
@@ -106,8 +108,7 @@
...
@@ -106,8 +108,7 @@
}
}
async
function
run
()
{
async
function
run
()
{
const
weightsBuffer
=
await
(
await
fetch
(
'/uncompressed/mtcnn_model.weights'
)).
arrayBuffer
()
await
faceapi
.
loadMtcnnModel
(
'/'
)
mtcnn
=
faceapi
.
mtcnn
(
new
Float32Array
(
weightsBuffer
))
$
(
'#loader'
).
hide
()
$
(
'#loader'
).
hide
()
onSelectionChanged
(
$
(
'#selectList select'
).
val
())
onSelectionChanged
(
$
(
'#selectList select'
).
val
())
}
}
...
...
examples/views/mtcnnFaceDetectionVideo.html
View file @
3f1826ab
...
@@ -20,18 +20,18 @@
...
@@ -20,18 +20,18 @@
</div>
</div>
<div
class=
"row side-by-side"
>
<div
class=
"row side-by-side"
>
<div
class=
"row"
>
<div
class=
"row"
>
<label
for=
"min
Confidence"
>
Min Confidenc
e:
</label>
<label
for=
"min
FaceSize"
>
Minimum Face Siz
e:
</label>
<input
disabled
value=
"
0.7"
id=
"minConfidenc
e"
type=
"text"
class=
"bold"
>
<input
disabled
value=
"
80"
id=
"minFaceSiz
e"
type=
"text"
class=
"bold"
>
</div>
</div>
<button
<button
class=
"waves-effect waves-light btn"
class=
"waves-effect waves-light btn"
onclick=
"onDecrease
Threshold
()"
onclick=
"onDecrease
MinFaceSize
()"
>
>
<i
class=
"material-icons left"
>
-
</i>
<i
class=
"material-icons left"
>
-
</i>
</button>
</button>
<button
<button
class=
"waves-effect waves-light btn"
class=
"waves-effect waves-light btn"
onclick=
"onIncrease
Threshold
()"
onclick=
"onIncrease
MinFaceSize
()"
>
>
<i
class=
"material-icons left"
>
+
</i>
<i
class=
"material-icons left"
>
+
</i>
</button>
</button>
...
@@ -49,29 +49,26 @@
...
@@ -49,29 +49,26 @@
</div>
</div>
<script>
<script>
let
modelLoaded
=
false
let
minFaceSize
=
80
let
minFaceSize
=
80
let
scaleFactor
=
0.709
let
maxNumScales
=
10
let
minConfidence
=
0.9
let
minConfidence
=
0.9
let
stage1Threshold
=
0.7
let
forwardTimes
=
[]
let
stage2Threshold
=
0.7
let
stage3Threshold
=
0.7
let
modelLoaded
=
false
let
result
function
onIncrease
Threshold
()
{
function
onIncrease
MinFaceSize
()
{
min
Confidence
=
Math
.
min
(
faceapi
.
round
(
minConfidence
+
0.1
),
1.
0
)
min
FaceSize
=
Math
.
min
(
faceapi
.
round
(
minFaceSize
+
20
),
20
0
)
$
(
'#min
Confidence'
).
val
(
minConfidenc
e
)
$
(
'#min
FaceSize'
).
val
(
minFaceSiz
e
)
}
}
function
onDecrease
Threshold
()
{
function
onDecrease
MinFaceSize
()
{
min
Confidence
=
Math
.
max
(
faceapi
.
round
(
minConfidence
-
0.1
),
0.1
)
min
FaceSize
=
Math
.
max
(
faceapi
.
round
(
minFaceSize
-
20
),
20
)
$
(
'#min
Confidence'
).
val
(
minConfidenc
e
)
$
(
'#min
FaceSize'
).
val
(
minFaceSiz
e
)
}
}
function
displayTimeStats
(
timeInMs
)
{
function
updateTimeStats
(
timeInMs
)
{
$
(
'#time'
).
val
(
`
${
timeInMs
}
ms`
)
forwardTimes
=
[
timeInMs
].
concat
(
forwardTimes
).
slice
(
0
,
30
)
$
(
'#fps'
).
val
(
`
${
faceapi
.
round
(
1000
/
timeInMs
)}
`
)
const
avgTimeInMs
=
forwardTimes
.
reduce
((
total
,
t
)
=>
total
+
t
)
/
forwardTimes
.
length
$
(
'#time'
).
val
(
`
${
Math
.
round
(
avgTimeInMs
)}
ms`
)
$
(
'#fps'
).
val
(
`
${
faceapi
.
round
(
1000
/
avgTimeInMs
)}
`
)
}
}
async
function
onPlay
(
videoEl
)
{
async
function
onPlay
(
videoEl
)
{
...
@@ -83,13 +80,15 @@
...
@@ -83,13 +80,15 @@
canvas
.
width
=
width
canvas
.
width
=
width
canvas
.
height
=
height
canvas
.
height
=
height
const
scoreThresholds
=
[
stage1Threshold
,
stage2Threshold
,
stage3Threshold
]
const
mtcnnParams
=
{
minFaceSize
}
const
ts
=
Date
.
now
()
const
ts
=
Date
.
now
()
const
{
results
,
stats
}
=
await
mtcnn
.
forwardWithStats
(
videoEl
,
minFaceSize
,
scaleFactor
,
maxNumScales
,
scoreThreshold
s
)
const
results
=
await
faceapi
.
mtcnn
(
videoEl
,
mtcnnParam
s
)
display
TimeStats
(
Date
.
now
()
-
ts
)
update
TimeStats
(
Date
.
now
()
-
ts
)
if
(
results
)
{
if
(
results
)
{
const
{
faceDetection
,
faceLandmarks
}
=
results
results
.
forEach
(({
faceDetection
,
faceLandmarks
})
=>
{
results
.
forEach
(({
faceDetection
,
faceLandmarks
})
=>
{
if
(
faceDetection
.
score
<
minConfidence
)
{
if
(
faceDetection
.
score
<
minConfidence
)
{
return
return
...
@@ -102,8 +101,7 @@
...
@@ -102,8 +101,7 @@
}
}
async
function
run
()
{
async
function
run
()
{
const
weightsBuffer
=
await
(
await
fetch
(
'/uncompressed/mtcnn_model.weights'
)).
arrayBuffer
()
await
faceapi
.
loadMtcnnModel
(
'/'
)
mtcnn
=
faceapi
.
mtcnn
(
new
Float32Array
(
weightsBuffer
))
modelLoaded
=
true
modelLoaded
=
true
onPlay
(
$
(
'#inputVideo'
).
get
(
0
))
onPlay
(
$
(
'#inputVideo'
).
get
(
0
))
$
(
'#loader'
).
hide
()
$
(
'#loader'
).
hide
()
...
...
examples/views/mtcnnFaceDetectionWebcam.html
0 → 100644
View file @
3f1826ab
<!DOCTYPE html>
<html>
<head>
<script
src=
"face-api.js"
></script>
<script
src=
"commons.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"
>
<video
onplay=
"onPlay(this)"
id=
"inputVideo"
autoplay
muted
></video>
<canvas
id=
"overlay"
/>
</div>
<div
class=
"row side-by-side"
>
<div
class=
"row"
>
<label
for=
"minFaceSize"
>
Minimum Face Size:
</label>
<input
disabled
value=
"200"
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>
<div
class=
"row side-by-side"
>
<div
class=
"row"
>
<label
for=
"time"
>
Time:
</label>
<input
disabled
value=
"-"
id=
"time"
type=
"text"
class=
"bold"
>
</div>
<div
class=
"row"
>
<label
for=
"fps"
>
Estimated Fps:
</label>
<input
disabled
value=
"-"
id=
"fps"
type=
"text"
class=
"bold"
>
</div>
</div>
</div>
<script>
let
modelLoaded
=
false
let
minFaceSize
=
200
let
minConfidence
=
0.9
let
forwardTimes
=
[]
function
onIncreaseMinFaceSize
()
{
minFaceSize
=
Math
.
min
(
faceapi
.
round
(
minFaceSize
+
50
),
300
)
$
(
'#minFaceSize'
).
val
(
minFaceSize
)
}
function
onDecreaseMinFaceSize
()
{
minFaceSize
=
Math
.
max
(
faceapi
.
round
(
minFaceSize
-
50
),
50
)
$
(
'#minFaceSize'
).
val
(
minFaceSize
)
}
function
updateTimeStats
(
timeInMs
)
{
forwardTimes
=
[
timeInMs
].
concat
(
forwardTimes
).
slice
(
0
,
30
)
const
avgTimeInMs
=
forwardTimes
.
reduce
((
total
,
t
)
=>
total
+
t
)
/
forwardTimes
.
length
$
(
'#time'
).
val
(
`
${
Math
.
round
(
avgTimeInMs
)}
ms`
)
$
(
'#fps'
).
val
(
`
${
faceapi
.
round
(
1000
/
avgTimeInMs
)}
`
)
}
async
function
onPlay
(
videoEl
)
{
if
(
videoEl
.
paused
||
videoEl
.
ended
||
!
modelLoaded
)
return
false
const
{
width
,
height
}
=
faceapi
.
getMediaDimensions
(
videoEl
)
const
canvas
=
$
(
'#overlay'
).
get
(
0
)
canvas
.
width
=
width
canvas
.
height
=
height
const
mtcnnParams
=
{
minFaceSize
}
const
c
=
faceapi
.
createCanvas
({
width
:
width
,
height
:
height
})
c
.
getContext
(
'2d'
).
drawImage
(
videoEl
,
0
,
0
)
const
{
results
,
stats
}
=
await
faceapi
.
nets
.
mtcnn
.
forwardWithStats
(
c
,
mtcnnParams
)
updateTimeStats
(
stats
.
total
)
if
(
results
)
{
results
.
forEach
(({
faceDetection
,
faceLandmarks
})
=>
{
if
(
faceDetection
.
score
<
minConfidence
)
{
return
}
faceapi
.
drawDetection
(
'overlay'
,
faceDetection
.
forSize
(
width
,
height
))
faceapi
.
drawLandmarks
(
'overlay'
,
faceLandmarks
.
forSize
(
width
,
height
),
{
lineWidth
:
4
,
color
:
'red'
})
})
}
setTimeout
(()
=>
onPlay
(
videoEl
))
}
async
function
run
()
{
await
faceapi
.
loadMtcnnModel
(
'/'
)
modelLoaded
=
true
const
videoEl
=
$
(
'#inputVideo'
).
get
(
0
)
navigator
.
getUserMedia
(
{
video
:
{}
},
stream
=>
videoEl
.
srcObject
=
stream
,
err
=>
console
.
error
(
err
)
)
$
(
'#loader'
).
hide
()
}
$
(
document
).
ready
(
function
()
{
renderNavBar
(
'#navbar'
,
'mtcnn_face_detection_webcam'
)
run
()
})
</script>
</body>
</html>
\ No newline at end of file
src/FaceDetection.ts
View file @
3f1826ab
...
@@ -24,23 +24,23 @@ export class FaceDetection {
...
@@ -24,23 +24,23 @@ export class FaceDetection {
)
)
}
}
public
get
Score
()
{
public
get
score
():
number
{
return
this
.
_score
return
this
.
_score
}
}
public
get
Box
()
{
public
get
box
():
Rect
{
return
this
.
_box
return
this
.
_box
}
}
public
get
ImageWidth
()
{
public
get
imageWidth
():
number
{
return
this
.
_imageWidth
return
this
.
_imageWidth
}
}
public
get
ImageHeight
()
{
public
get
imageHeight
():
number
{
return
this
.
_imageHeight
return
this
.
_imageHeight
}
}
public
get
RelativeBox
()
{
public
get
relativeBox
():
Rect
{
return
new
Rect
(
return
new
Rect
(
this
.
_box
.
x
/
this
.
_imageWidth
,
this
.
_box
.
x
/
this
.
_imageWidth
,
this
.
_box
.
y
/
this
.
_imageHeight
,
this
.
_box
.
y
/
this
.
_imageHeight
,
...
@@ -49,6 +49,26 @@ export class FaceDetection {
...
@@ -49,6 +49,26 @@ export class FaceDetection {
)
)
}
}
public
getScore
()
{
return
this
.
score
}
public
getBox
()
{
return
this
.
box
}
public
getImageWidth
()
{
return
this
.
imageWidth
}
public
getImageHeight
()
{
return
this
.
imageHeight
}
public
getRelativeBox
()
{
return
this
.
relativeBox
}
public
forSize
(
width
:
number
,
height
:
number
):
FaceDetection
{
public
forSize
(
width
:
number
,
height
:
number
):
FaceDetection
{
return
new
FaceDetection
(
return
new
FaceDetection
(
this
.
_score
,
this
.
_score
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment