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
7c7cf2a8
Commit
7c7cf2a8
authored
May 04, 2019
by
vincent
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PredictAgeAndGenderTask
parent
4205fc29
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
325 additions
and
54 deletions
+325
-54
AgeGenderNet.ts
src/ageGenderNet/AgeGenderNet.ts
+24
-9
types.ts
src/ageGenderNet/types.ts
+11
-0
WithAge.ts
src/factories/WithAge.ts
+19
-0
WithGender.ts
src/factories/WithGender.ts
+26
-0
ComputeFaceDescriptorsTasks.ts
src/globalApi/ComputeFaceDescriptorsTasks.ts
+40
-19
DetectFaceLandmarksTasks.ts
src/globalApi/DetectFaceLandmarksTasks.ts
+12
-0
PredictAgeAndGenderTask.ts
src/globalApi/PredictAgeAndGenderTask.ts
+99
-0
PredictFaceExpressionsTask.ts
src/globalApi/PredictFaceExpressionsTask.ts
+29
-22
extractFacesAndComputeResults.ts
src/globalApi/extractFacesAndComputeResults.ts
+49
-0
nets.ts
src/globalApi/nets.ts
+16
-4
No files found.
src/ageGenderNet/AgeGenderNet.ts
View file @
7c7cf2a8
...
...
@@ -6,7 +6,7 @@ import { seperateWeightMaps } from '../faceProcessor/util';
import
{
TinyXception
}
from
'../xception/TinyXception'
;
import
{
extractParams
}
from
'./extractParams'
;
import
{
extractParamsFromWeigthMap
}
from
'./extractParamsFromWeigthMap'
;
import
{
NetOutput
,
NetParams
}
from
'./types'
;
import
{
AgeAndGenderPrediction
,
Gender
,
NetOutput
,
NetParams
}
from
'./types'
;
export
class
AgeGenderNet
extends
NeuralNetwork
<
NetParams
>
{
...
...
@@ -50,17 +50,32 @@ export class AgeGenderNet extends NeuralNetwork<NetParams> {
return
this
.
forwardInput
(
await
toNetInput
(
input
))
}
public
async
predictAgeAndGender
(
input
:
TNetInput
):
Promise
<
{
age
:
number
,
gender
:
string
,
genderProbability
:
number
}
>
{
public
async
predictAgeAndGender
(
input
:
TNetInput
):
Promise
<
AgeAndGenderPrediction
|
AgeAndGenderPrediction
[]
>
{
const
netInput
=
await
toNetInput
(
input
)
const
out
=
await
this
.
forwardInput
(
netInput
)
const
age
=
(
await
out
.
age
.
data
())[
0
]
const
probMale
=
(
await
out
.
gender
.
data
())[
0
]
const
isMale
=
probMale
>
0.5
const
gender
=
isMale
?
'male'
:
'female'
const
genderProbability
=
isMale
?
probMale
:
(
1
-
probMale
)
return
{
age
,
gender
,
genderProbability
}
const
ages
=
tf
.
unstack
(
out
.
age
)
const
genders
=
tf
.
unstack
(
out
.
gender
)
const
ageAndGenderTensors
=
ages
.
map
((
ageTensor
,
i
)
=>
({
ageTensor
,
genderTensor
:
genders
[
i
]
}))
const
predictionsByBatch
=
await
Promise
.
all
(
ageAndGenderTensors
.
map
(
async
({
ageTensor
,
genderTensor
})
=>
{
const
age
=
(
await
ageTensor
.
data
())[
0
]
const
probMale
=
(
await
out
.
gender
.
data
())[
0
]
const
isMale
=
probMale
>
0.5
const
gender
=
isMale
?
Gender
.
MALE
:
Gender
.
FEMALE
const
genderProbability
=
isMale
?
probMale
:
(
1
-
probMale
)
return
{
age
,
gender
,
genderProbability
}
})
)
return
netInput
.
isBatchInput
?
predictionsByBatch
:
predictionsByBatch
[
0
]
}
protected
getDefaultModelName
():
string
{
...
...
src/ageGenderNet/types.ts
View file @
7c7cf2a8
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
TfjsImageRecognitionBase
}
from
'tfjs-image-recognition-base'
;
export
type
AgeAndGenderPrediction
=
{
age
:
number
gender
:
Gender
genderProbability
:
number
}
export
enum
Gender
{
FEMALE
=
'female'
,
MALE
=
'male'
}
export
type
NetOutput
=
{
age
:
tf
.
Tensor1D
,
gender
:
tf
.
Tensor2D
}
export
type
NetParams
=
{
...
...
src/factories/WithAge.ts
0 → 100644
View file @
7c7cf2a8
export
type
WithAge
<
TSource
>
=
TSource
&
{
age
:
number
}
export
function
isWithAge
(
obj
:
any
):
obj
is
WithAge
<
{}
>
{
return
typeof
obj
[
'age'
]
===
'number'
}
export
function
extendWithAge
<
TSource
>
(
sourceObj
:
TSource
,
age
:
number
):
WithAge
<
TSource
>
{
const
extension
=
{
age
}
return
Object
.
assign
({},
sourceObj
,
extension
)
}
\ No newline at end of file
src/factories/WithGender.ts
0 → 100644
View file @
7c7cf2a8
import
{
isValidProbablitiy
}
from
'tfjs-image-recognition-base'
;
import
{
Gender
}
from
'../ageGenderNet/types'
;
export
type
WithGender
<
TSource
>
=
TSource
&
{
gender
:
Gender
genderProbability
:
number
}
export
function
isWithGender
(
obj
:
any
):
obj
is
WithGender
<
{}
>
{
return
(
obj
[
'gender'
]
===
Gender
.
MALE
||
obj
[
'gender'
]
===
Gender
.
FEMALE
)
&&
isValidProbablitiy
(
obj
[
'genderProbability'
])
}
export
function
extendWithGender
<
TSource
>
(
sourceObj
:
TSource
,
gender
:
Gender
,
genderProbability
:
number
):
WithGender
<
TSource
>
{
const
extension
=
{
gender
,
genderProbability
}
return
Object
.
assign
({},
sourceObj
,
extension
)
}
\ No newline at end of file
src/globalApi/ComputeFaceDescriptorsTasks.ts
View file @
7c7cf2a8
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
TNetInput
}
from
'tfjs-image-recognition-base'
;
import
{
extractFaces
,
extractFaceTensors
}
from
'../dom'
;
import
{
extendWithFaceDescriptor
,
WithFaceDescriptor
}
from
'../factories/WithFaceDescriptor'
;
import
{
WithFaceDetection
}
from
'../factories/WithFaceDetection'
;
import
{
WithFaceLandmarks
}
from
'../factories/WithFaceLandmarks'
;
import
{
ComposableTask
}
from
'./ComposableTask'
;
import
{
extractAllFacesAndComputeResults
,
extractSingleFaceAndComputeResult
}
from
'./extractFacesAndComputeResults'
;
import
{
nets
}
from
'./nets'
;
import
{
PredictAllAgeAndGenderWithFaceAlignmentTask
,
PredictSingleAgeAndGenderWithFaceAlignmentTask
,
}
from
'./PredictAgeAndGenderTask'
;
import
{
PredictAllFaceExpressionsWithFaceAlignmentTask
,
PredictSingleFaceExpressionsWithFaceAlignmentTask
,
}
from
'./PredictFaceExpressionsTask'
;
export
class
ComputeFaceDescriptorsTaskBase
<
TReturn
,
TParentReturn
>
extends
ComposableTask
<
TReturn
>
{
constructor
(
...
...
@@ -25,19 +32,25 @@ export class ComputeAllFaceDescriptorsTask<
const
parentResults
=
await
this
.
parentTask
const
dlibAlignedRects
=
parentResults
.
map
(({
landmarks
})
=>
landmarks
.
align
(
null
,
{
useDlibAlignment
:
true
}))
const
dlibAlignedFaces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
=
this
.
input
instanceof
tf
.
Tensor
?
await
extractFaceTensors
(
this
.
input
,
dlibAlignedRects
)
:
await
extractFaces
(
this
.
input
,
dlibAlignedRects
)
const
descriptors
=
await
extractAllFacesAndComputeResults
<
TSource
,
Float32Array
[]
>
(
parentResults
,
this
.
input
,
faces
=>
Promise
.
all
(
faces
.
map
(
face
=>
nets
.
faceRecognitionNet
.
computeFaceDescriptor
(
face
)
as
Promise
<
Float32Array
>
)),
null
,
parentResult
=>
parentResult
.
landmarks
.
align
(
null
,
{
useDlibAlignment
:
true
})
)
const
results
=
await
Promise
.
all
(
parentResults
.
map
(
async
(
parentResult
,
i
)
=>
{
const
descriptor
=
await
nets
.
faceRecognitionNet
.
computeFaceDescriptor
(
dlibAlignedFaces
[
i
])
as
Float32Array
return
extendWithFaceDescriptor
<
TSource
>
(
parentResult
,
descriptor
)
}))
return
descriptors
.
map
((
descriptor
,
i
)
=>
extendWithFaceDescriptor
<
TSource
>
(
parentResults
[
i
],
descriptor
))
}
dlibAlignedFaces
.
forEach
(
f
=>
f
instanceof
tf
.
Tensor
&&
f
.
dispose
())
withFaceExpressions
():
PredictAllFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictAllFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
return
results
withAgeAndGender
():
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
}
...
...
@@ -51,15 +64,22 @@ export class ComputeSingleFaceDescriptorTask<
if
(
!
parentResult
)
{
return
}
const
descriptor
=
await
extractSingleFaceAndComputeResult
<
TSource
,
Float32Array
>
(
parentResult
,
this
.
input
,
face
=>
nets
.
faceRecognitionNet
.
computeFaceDescriptor
(
face
)
as
Promise
<
Float32Array
>
,
null
,
parentResult
=>
parentResult
.
landmarks
.
align
(
null
,
{
useDlibAlignment
:
true
})
)
const
dlibAlignedRect
=
parentResult
.
landmarks
.
align
(
null
,
{
useDlibAlignment
:
true
})
const
alignedFaces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
=
this
.
input
instanceof
tf
.
Tensor
?
await
extractFaceTensors
(
this
.
input
,
[
dlibAlignedRect
])
:
await
extractFaces
(
this
.
input
,
[
dlibAlignedRect
])
const
descriptor
=
await
nets
.
faceRecognitionNet
.
computeFaceDescriptor
(
alignedFaces
[
0
])
as
Float32Array
return
extendWithFaceDescriptor
(
parentResult
,
descriptor
)
}
alignedFaces
.
forEach
(
f
=>
f
instanceof
tf
.
Tensor
&&
f
.
dispose
())
withFaceExpressions
():
PredictSingleFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictSingleFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
return
extendWithFaceDescriptor
(
parentResult
,
descriptor
)
withAgeAndGender
():
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
}
\ No newline at end of file
src/globalApi/DetectFaceLandmarksTasks.ts
View file @
7c7cf2a8
...
...
@@ -11,6 +11,10 @@ import { ComposableTask } from './ComposableTask';
import
{
ComputeAllFaceDescriptorsTask
,
ComputeSingleFaceDescriptorTask
}
from
'./ComputeFaceDescriptorsTasks'
;
import
{
nets
}
from
'./nets'
;
import
{
PredictAllAgeAndGenderWithFaceAlignmentTask
,
PredictSingleAgeAndGenderWithFaceAlignmentTask
,
}
from
'./PredictAgeAndGenderTask'
;
import
{
PredictAllFaceExpressionsWithFaceAlignmentTask
,
PredictSingleFaceExpressionsWithFaceAlignmentTask
,
}
from
'./PredictFaceExpressionsTask'
;
...
...
@@ -59,6 +63,10 @@ export class DetectAllFaceLandmarksTask<
return
new
PredictAllFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withAgeAndGender
():
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptors
():
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
...
...
@@ -91,6 +99,10 @@ export class DetectSingleFaceLandmarksTask<
return
new
PredictSingleFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withAgeAndGender
():
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptor
():
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
...
...
src/globalApi/PredictAgeAndGenderTask.ts
0 → 100644
View file @
7c7cf2a8
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
TNetInput
}
from
'tfjs-image-recognition-base'
;
import
{
AgeAndGenderPrediction
}
from
'../ageGenderNet/types'
;
import
{
extendWithAge
,
WithAge
}
from
'../factories/WithAge'
;
import
{
WithFaceDetection
}
from
'../factories/WithFaceDetection'
;
import
{
WithFaceLandmarks
}
from
'../factories/WithFaceLandmarks'
;
import
{
extendWithGender
,
WithGender
}
from
'../factories/WithGender'
;
import
{
ComposableTask
}
from
'./ComposableTask'
;
import
{
ComputeAllFaceDescriptorsTask
,
ComputeSingleFaceDescriptorTask
}
from
'./ComputeFaceDescriptorsTasks'
;
import
{
extractAllFacesAndComputeResults
,
extractSingleFaceAndComputeResult
}
from
'./extractFacesAndComputeResults'
;
import
{
nets
}
from
'./nets'
;
import
{
PredictAllFaceExpressionsWithFaceAlignmentTask
,
PredictSingleFaceExpressionsWithFaceAlignmentTask
,
}
from
'./PredictFaceExpressionsTask'
;
export
class
PredictAgeAndGenderTaskBase
<
TReturn
,
TParentReturn
>
extends
ComposableTask
<
TReturn
>
{
constructor
(
protected
parentTask
:
ComposableTask
<
TParentReturn
>
|
Promise
<
TParentReturn
>
,
protected
input
:
TNetInput
,
protected
extractedFaces
?:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
)
{
super
()
}
}
export
class
PredictAllAgeAndGenderTask
<
TSource
extends
WithFaceDetection
<
{}
>
>
extends
PredictAgeAndGenderTaskBase
<
WithAge
<
WithGender
<
TSource
>>
[],
TSource
[]
>
{
public
async
run
():
Promise
<
WithAge
<
WithGender
<
TSource
>>
[]
>
{
const
parentResults
=
await
this
.
parentTask
const
ageAndGenderByFace
=
await
extractAllFacesAndComputeResults
<
TSource
,
AgeAndGenderPrediction
[]
>
(
parentResults
,
this
.
input
,
async
faces
=>
await
Promise
.
all
(
faces
.
map
(
face
=>
nets
.
ageGenderNet
.
predictAgeAndGender
(
face
)
as
Promise
<
AgeAndGenderPrediction
>
)),
this
.
extractedFaces
)
return
parentResults
.
map
((
parentResult
,
i
)
=>
{
const
{
age
,
gender
,
genderProbability
}
=
ageAndGenderByFace
[
i
]
return
extendWithAge
(
extendWithGender
(
parentResult
,
gender
,
genderProbability
),
age
)
})
}
}
export
class
PredictSingleAgeAndGenderTask
<
TSource
extends
WithFaceDetection
<
{}
>
>
extends
PredictAgeAndGenderTaskBase
<
WithAge
<
WithGender
<
TSource
>>
|
undefined
,
TSource
|
undefined
>
{
public
async
run
():
Promise
<
WithAge
<
WithGender
<
TSource
>>
|
undefined
>
{
const
parentResult
=
await
this
.
parentTask
if
(
!
parentResult
)
{
return
}
const
{
age
,
gender
,
genderProbability
}
=
await
extractSingleFaceAndComputeResult
<
TSource
,
AgeAndGenderPrediction
>
(
parentResult
,
this
.
input
,
face
=>
nets
.
ageGenderNet
.
predictAgeAndGender
(
face
)
as
Promise
<
AgeAndGenderPrediction
>
,
this
.
extractedFaces
)
return
extendWithAge
(
extendWithGender
(
parentResult
,
gender
,
genderProbability
),
age
)
}
}
export
class
PredictAllAgeAndGenderWithFaceAlignmentTask
<
TSource
extends
WithFaceLandmarks
<
WithFaceDetection
<
{}
>>
>
extends
PredictAllAgeAndGenderTask
<
TSource
>
{
withFaceExpressions
():
PredictAllFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictAllFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptors
():
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
}
export
class
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
TSource
extends
WithFaceLandmarks
<
WithFaceDetection
<
{}
>>
>
extends
PredictSingleAgeAndGenderTask
<
TSource
>
{
withFaceExpressions
():
PredictSingleFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictSingleFaceExpressionsWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptor
():
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
}
\ No newline at end of file
src/globalApi/PredictFaceExpressionsTask.ts
View file @
7c7cf2a8
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
TNetInput
}
from
'tfjs-image-recognition-base'
;
import
{
extractFaces
,
extractFaceTensors
}
from
'../dom'
;
import
{
FaceExpressions
}
from
'../faceExpressionNet/FaceExpressions'
;
import
{
WithFaceDetection
}
from
'../factories/WithFaceDetection'
;
import
{
extendWithFaceExpressions
,
WithFaceExpressions
}
from
'../factories/WithFaceExpressions'
;
import
{
isWithFaceLandmarks
,
WithFaceLandmarks
}
from
'../factories/WithFaceLandmarks'
;
import
{
WithFaceLandmarks
}
from
'../factories/WithFaceLandmarks'
;
import
{
ComposableTask
}
from
'./ComposableTask'
;
import
{
ComputeAllFaceDescriptorsTask
,
ComputeSingleFaceDescriptorTask
}
from
'./ComputeFaceDescriptorsTasks'
;
import
{
extractAllFacesAndComputeResults
,
extractSingleFaceAndComputeResult
}
from
'./extractFacesAndComputeResults'
;
import
{
nets
}
from
'./nets'
;
import
{
PredictAllAgeAndGenderWithFaceAlignmentTask
,
PredictSingleAgeAndGenderWithFaceAlignmentTask
,
}
from
'./PredictAgeAndGenderTask'
;
export
class
PredictFaceExpressionsTaskBase
<
TReturn
,
TParentReturn
>
extends
ComposableTask
<
TReturn
>
{
constructor
(
protected
parentTask
:
ComposableTask
<
TParentReturn
>
|
Promise
<
TParentReturn
>
,
protected
input
:
TNetInput
protected
input
:
TNetInput
,
protected
extractedFaces
?:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
)
{
super
()
}
...
...
@@ -27,18 +32,14 @@ export class PredictAllFaceExpressionsTask<
const
parentResults
=
await
this
.
parentTask
const
faceBoxes
=
parentResults
.
map
(
parentResult
=>
isWithFaceLandmarks
(
parentResult
)
?
parentResult
.
alignedRect
:
parentResult
.
detection
const
faceExpressionsByFace
=
await
extractAllFacesAndComputeResults
<
TSource
,
FaceExpressions
[]
>
(
parentResults
,
this
.
input
,
async
faces
=>
await
Promise
.
all
(
faces
.
map
(
face
=>
nets
.
faceExpressionNet
.
predictExpressions
(
face
)
as
Promise
<
FaceExpressions
>
)),
this
.
extractedFaces
)
const
faces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
=
this
.
input
instanceof
tf
.
Tensor
?
await
extractFaceTensors
(
this
.
input
,
faceBoxes
)
:
await
extractFaces
(
this
.
input
,
faceBoxes
)
const
faceExpressionsByFace
=
await
Promise
.
all
(
faces
.
map
(
face
=>
nets
.
faceExpressionNet
.
predictExpressions
(
face
)
))
as
FaceExpressions
[]
faces
.
forEach
(
f
=>
f
instanceof
tf
.
Tensor
&&
f
.
dispose
())
return
parentResults
.
map
(
(
parentResult
,
i
)
=>
extendWithFaceExpressions
<
TSource
>
(
parentResult
,
faceExpressionsByFace
[
i
])
...
...
@@ -57,14 +58,12 @@ export class PredictSingleFaceExpressionsTask<
return
}
const
faceBox
=
isWithFaceLandmarks
(
parentResult
)
?
parentResult
.
alignedRect
:
parentResult
.
detection
const
faces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
=
this
.
input
instanceof
tf
.
Tensor
?
await
extractFaceTensors
(
this
.
input
,
[
faceBox
])
:
await
extractFaces
(
this
.
input
,
[
faceBox
])
const
faceExpressions
=
await
nets
.
faceExpressionNet
.
predictExpressions
(
faces
[
0
])
as
FaceExpressions
faces
.
forEach
(
f
=>
f
instanceof
tf
.
Tensor
&&
f
.
dispose
())
const
faceExpressions
=
await
extractSingleFaceAndComputeResult
<
TSource
,
FaceExpressions
>
(
parentResult
,
this
.
input
,
face
=>
nets
.
faceExpressionNet
.
predictExpressions
(
face
)
as
Promise
<
FaceExpressions
>
,
this
.
extractedFaces
)
return
extendWithFaceExpressions
(
parentResult
,
faceExpressions
)
}
...
...
@@ -74,6 +73,10 @@ export class PredictAllFaceExpressionsWithFaceAlignmentTask<
TSource
extends
WithFaceLandmarks
<
WithFaceDetection
<
{}
>>
>
extends
PredictAllFaceExpressionsTask
<
TSource
>
{
withAgeAndGender
():
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictAllAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptors
():
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeAllFaceDescriptorsTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
...
...
@@ -83,6 +86,10 @@ export class PredictSingleFaceExpressionsWithFaceAlignmentTask<
TSource
extends
WithFaceLandmarks
<
WithFaceDetection
<
{}
>>
>
extends
PredictSingleFaceExpressionsTask
<
TSource
>
{
withAgeAndGender
():
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
PredictSingleAgeAndGenderWithFaceAlignmentTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
withFaceDescriptor
():
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
{
return
new
ComputeSingleFaceDescriptorTask
<
WithFaceLandmarks
<
TSource
>>
(
this
,
this
.
input
)
}
...
...
src/globalApi/extractFacesAndComputeResults.ts
0 → 100644
View file @
7c7cf2a8
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
TNetInput
}
from
'tfjs-image-recognition-base'
;
import
{
FaceDetection
}
from
'../classes/FaceDetection'
;
import
{
extractFaces
,
extractFaceTensors
}
from
'../dom'
;
import
{
WithFaceDetection
}
from
'../factories/WithFaceDetection'
;
import
{
isWithFaceLandmarks
,
WithFaceLandmarks
}
from
'../factories/WithFaceLandmarks'
;
export
async
function
extractAllFacesAndComputeResults
<
TSource
extends
WithFaceDetection
<
{}
>
,
TResult
>
(
parentResults
:
TSource
[],
input
:
TNetInput
,
computeResults
:
(
faces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
)
=>
Promise
<
TResult
>
,
extractedFaces
?:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
|
null
,
getRectForAlignment
:
(
parentResult
:
WithFaceLandmarks
<
TSource
,
any
>
)
=>
FaceDetection
=
({
alignedRect
})
=>
alignedRect
)
{
const
faceBoxes
=
parentResults
.
map
(
parentResult
=>
isWithFaceLandmarks
(
parentResult
)
?
getRectForAlignment
(
parentResult
)
:
parentResult
.
detection
)
const
faces
:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
=
extractedFaces
||
(
input
instanceof
tf
.
Tensor
?
await
extractFaceTensors
(
input
,
faceBoxes
)
:
await
extractFaces
(
input
,
faceBoxes
)
)
const
results
=
await
computeResults
(
faces
)
faces
.
forEach
(
f
=>
f
instanceof
tf
.
Tensor
&&
f
.
dispose
())
return
results
}
export
async
function
extractSingleFaceAndComputeResult
<
TSource
extends
WithFaceDetection
<
{}
>
,
TResult
>
(
parentResult
:
TSource
,
input
:
TNetInput
,
computeResult
:
(
face
:
HTMLCanvasElement
|
tf
.
Tensor3D
)
=>
Promise
<
TResult
>
,
extractedFaces
?:
Array
<
HTMLCanvasElement
|
tf
.
Tensor3D
>
|
null
,
getRectForAlignment
?:
(
parentResult
:
WithFaceLandmarks
<
TSource
,
any
>
)
=>
FaceDetection
)
{
return
extractAllFacesAndComputeResults
<
TSource
,
TResult
>
(
[
parentResult
],
input
,
async
faces
=>
computeResult
(
faces
[
0
]),
extractedFaces
,
getRectForAlignment
)
}
\ No newline at end of file
src/globalApi/nets.ts
View file @
7c7cf2a8
import
{
TfjsImageRecognitionBase
,
TNetInput
}
from
'tfjs-image-recognition-base'
;
import
{
AgeGenderNet
}
from
'../ageGenderNet/AgeGenderNet'
;
import
{
AgeAndGenderPrediction
}
from
'../ageGenderNet/types'
;
import
{
FaceDetection
}
from
'../classes/FaceDetection'
;
import
{
FaceLandmarks5
}
from
'../classes/FaceLandmarks5'
;
import
{
FaceLandmarks68
}
from
'../classes/FaceLandmarks68'
;
...
...
@@ -26,7 +28,8 @@ export const nets = {
faceLandmark68Net
:
new
FaceLandmark68Net
(),
faceLandmark68TinyNet
:
new
FaceLandmark68TinyNet
(),
faceRecognitionNet
:
new
FaceRecognitionNet
(),
faceExpressionNet
:
new
FaceExpressionNet
()
faceExpressionNet
:
new
FaceExpressionNet
(),
ageGenderNet
:
new
AgeGenderNet
()
}
/**
...
...
@@ -107,16 +110,25 @@ export const computeFaceDescriptor = (input: TNetInput): Promise<Float32Array |
/**
* Recognizes the facial expressions of a face and returns the likelyhood of
* each facial expression.
* Recognizes the facial expressions from a face image.
*
* @param inputs The face image extracted from the bounding box of a face. Can
* also be an array of input images, which will be batch processed.
* @returns
An array of f
acial expressions with corresponding probabilities or array thereof in case of batch input.
* @returns
F
acial expressions with corresponding probabilities or array thereof in case of batch input.
*/
export
const
recognizeFaceExpressions
=
(
input
:
TNetInput
):
Promise
<
FaceExpressions
|
FaceExpressions
[]
>
=>
nets
.
faceExpressionNet
.
predictExpressions
(
input
)
/**
* Predicts age and gender from a face image.
*
* @param inputs The face image extracted from the bounding box of a face. Can
* also be an array of input images, which will be batch processed.
* @returns Predictions with age, gender and gender probability or array thereof in case of batch input.
*/
export
const
predictAgeAndGender
=
(
input
:
TNetInput
):
Promise
<
AgeAndGenderPrediction
|
AgeAndGenderPrediction
[]
>
=>
nets
.
ageGenderNet
.
predictAgeAndGender
(
input
)
export
const
loadSsdMobilenetv1Model
=
(
url
:
string
)
=>
nets
.
ssdMobilenetv1
.
load
(
url
)
export
const
loadTinyFaceDetectorModel
=
(
url
:
string
)
=>
nets
.
tinyFaceDetector
.
load
(
url
)
export
const
loadMtcnnModel
=
(
url
:
string
)
=>
nets
.
mtcnn
.
load
(
url
)
...
...
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