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
542dc68c
Commit
542dc68c
authored
Aug 04, 2018
by
vincent
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
prepare tinyYolov2 for using depthwise seperable conv2ds + retraining
parent
f81d35ad
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
194 additions
and
84 deletions
+194
-84
BoundingBox.ts
src/BoundingBox.ts
+12
-0
extractWeightsFactory.ts
src/commons/extractWeightsFactory.ts
+1
-0
nonMaxSuppression.ts
src/commons/nonMaxSuppression.ts
+2
-13
index.ts
src/index.ts
+1
-0
iou.ts
src/iou.ts
+12
-0
TinyYolov2.ts
src/tinyYolov2/TinyYolov2.ts
+75
-44
config.ts
src/tinyYolov2/config.ts
+9
-0
convWithBatchNorm.ts
src/tinyYolov2/convWithBatchNorm.ts
+14
-6
extractParams.ts
src/tinyYolov2/extractParams.ts
+37
-13
types.ts
src/tinyYolov2/types.ts
+23
-8
utils.ts
src/utils.ts
+8
-0
No files found.
src/BoundingBox.ts
View file @
542dc68c
import
{
Rect
}
from
'./Rect'
;
import
{
Rect
}
from
'./Rect'
;
import
{
Dimensions
}
from
'./types'
;
import
{
isDimensions
}
from
'./utils'
;
export
class
BoundingBox
{
export
class
BoundingBox
{
constructor
(
constructor
(
...
@@ -33,6 +35,10 @@ export class BoundingBox {
...
@@ -33,6 +35,10 @@ export class BoundingBox {
return
this
.
bottom
-
this
.
top
return
this
.
bottom
-
this
.
top
}
}
public
get
area
()
:
number
{
return
this
.
width
*
this
.
height
}
public
toSquare
():
BoundingBox
{
public
toSquare
():
BoundingBox
{
let
{
left
,
top
,
right
,
bottom
}
=
this
let
{
left
,
top
,
right
,
bottom
}
=
this
...
@@ -100,6 +106,12 @@ export class BoundingBox {
...
@@ -100,6 +106,12 @@ export class BoundingBox {
).
toSquare
().
round
()
).
toSquare
().
round
()
}
}
public
rescale
(
s
:
Dimensions
|
number
)
{
const
scaleX
=
isDimensions
(
s
)
?
(
s
as
Dimensions
).
width
:
s
as
number
const
scaleY
=
isDimensions
(
s
)
?
(
s
as
Dimensions
).
height
:
s
as
number
return
new
BoundingBox
(
this
.
left
*
scaleX
,
this
.
top
*
scaleY
,
this
.
right
*
scaleX
,
this
.
bottom
*
scaleY
)
}
public
toRect
():
Rect
{
public
toRect
():
Rect
{
return
new
Rect
(
this
.
left
,
this
.
top
,
this
.
width
,
this
.
height
)
return
new
Rect
(
this
.
left
,
this
.
top
,
this
.
width
,
this
.
height
)
}
}
...
...
src/commons/extractWeightsFactory.ts
View file @
542dc68c
...
@@ -2,6 +2,7 @@ export function extractWeightsFactory(weights: Float32Array) {
...
@@ -2,6 +2,7 @@ export function extractWeightsFactory(weights: Float32Array) {
let
remainingWeights
=
weights
let
remainingWeights
=
weights
function
extractWeights
(
numWeights
:
number
):
Float32Array
{
function
extractWeights
(
numWeights
:
number
):
Float32Array
{
console
.
log
(
numWeights
)
const
ret
=
remainingWeights
.
slice
(
0
,
numWeights
)
const
ret
=
remainingWeights
.
slice
(
0
,
numWeights
)
remainingWeights
=
remainingWeights
.
slice
(
numWeights
)
remainingWeights
=
remainingWeights
.
slice
(
numWeights
)
return
ret
return
ret
...
...
src/commons/nonMaxSuppression.ts
View file @
542dc68c
import
{
BoundingBox
}
from
'../BoundingBox'
;
import
{
BoundingBox
}
from
'../BoundingBox'
;
import
{
iou
}
from
'../iou'
;
export
function
nonMaxSuppression
(
export
function
nonMaxSuppression
(
boxes
:
BoundingBox
[],
boxes
:
BoundingBox
[],
...
@@ -7,10 +8,6 @@ export function nonMaxSuppression(
...
@@ -7,10 +8,6 @@ export function nonMaxSuppression(
isIOU
:
boolean
=
true
isIOU
:
boolean
=
true
):
number
[]
{
):
number
[]
{
const
areas
=
boxes
.
map
(
box
=>
(
box
.
width
+
1
)
*
(
box
.
height
+
1
)
)
let
indicesSortedByScore
=
scores
let
indicesSortedByScore
=
scores
.
map
((
score
,
boxIndex
)
=>
({
score
,
boxIndex
}))
.
map
((
score
,
boxIndex
)
=>
({
score
,
boxIndex
}))
.
sort
((
c1
,
c2
)
=>
c1
.
score
-
c2
.
score
)
.
sort
((
c1
,
c2
)
=>
c1
.
score
-
c2
.
score
)
...
@@ -31,15 +28,7 @@ export function nonMaxSuppression(
...
@@ -31,15 +28,7 @@ export function nonMaxSuppression(
const
currBox
=
boxes
[
curr
]
const
currBox
=
boxes
[
curr
]
const
idxBox
=
boxes
[
idx
]
const
idxBox
=
boxes
[
idx
]
const
width
=
Math
.
max
(
0.0
,
Math
.
min
(
currBox
.
right
,
idxBox
.
right
)
-
Math
.
max
(
currBox
.
left
,
idxBox
.
left
)
+
1
)
outputs
.
push
(
iou
(
currBox
,
idxBox
,
isIOU
))
const
height
=
Math
.
max
(
0.0
,
Math
.
min
(
currBox
.
bottom
,
idxBox
.
bottom
)
-
Math
.
max
(
currBox
.
top
,
idxBox
.
top
)
+
1
)
const
interSection
=
width
*
height
const
out
=
isIOU
?
interSection
/
(
areas
[
curr
]
+
areas
[
idx
]
-
interSection
)
:
interSection
/
Math
.
min
(
areas
[
curr
],
areas
[
idx
])
outputs
.
push
(
out
)
}
}
indicesSortedByScore
=
indicesSortedByScore
.
filter
(
indicesSortedByScore
=
indicesSortedByScore
.
filter
(
...
...
src/index.ts
View file @
542dc68c
...
@@ -19,6 +19,7 @@ export * from './faceDetectionNet';
...
@@ -19,6 +19,7 @@ export * from './faceDetectionNet';
export
*
from
'./faceLandmarkNet'
;
export
*
from
'./faceLandmarkNet'
;
export
*
from
'./faceRecognitionNet'
;
export
*
from
'./faceRecognitionNet'
;
export
*
from
'./globalApi'
;
export
*
from
'./globalApi'
;
export
*
from
'./iou'
;
export
*
from
'./mtcnn'
;
export
*
from
'./mtcnn'
;
export
*
from
'./padToSquare'
;
export
*
from
'./padToSquare'
;
export
*
from
'./tinyYolov2'
;
export
*
from
'./tinyYolov2'
;
...
...
src/iou.ts
0 → 100644
View file @
542dc68c
import
{
BoundingBox
}
from
'./BoundingBox'
;
export
function
iou
(
box1
:
BoundingBox
,
box2
:
BoundingBox
,
isIOU
:
boolean
=
true
)
{
const
width
=
Math
.
max
(
0.0
,
Math
.
min
(
box1
.
right
,
box2
.
right
)
-
Math
.
max
(
box1
.
left
,
box2
.
left
)
+
1
)
const
height
=
Math
.
max
(
0.0
,
Math
.
min
(
box1
.
bottom
,
box2
.
bottom
)
-
Math
.
max
(
box1
.
top
,
box2
.
top
)
+
1
)
const
interSection
=
width
*
height
return
isIOU
?
interSection
/
(
box1
.
area
+
box2
.
area
-
interSection
)
:
interSection
/
Math
.
min
(
box1
.
area
,
box2
.
area
)
}
\ No newline at end of file
src/tinyYolov2/TinyYolov2.ts
View file @
542dc68c
...
@@ -6,19 +6,34 @@ import { NeuralNetwork } from '../commons/NeuralNetwork';
...
@@ -6,19 +6,34 @@ import { NeuralNetwork } from '../commons/NeuralNetwork';
import
{
nonMaxSuppression
}
from
'../commons/nonMaxSuppression'
;
import
{
nonMaxSuppression
}
from
'../commons/nonMaxSuppression'
;
import
{
FaceDetection
}
from
'../FaceDetection'
;
import
{
FaceDetection
}
from
'../FaceDetection'
;
import
{
NetInput
}
from
'../NetInput'
;
import
{
NetInput
}
from
'../NetInput'
;
import
{
Point
}
from
'../Point'
;
import
{
toNetInput
}
from
'../toNetInput'
;
import
{
toNetInput
}
from
'../toNetInput'
;
import
{
TNetInput
}
from
'../types'
;
import
{
TNetInput
}
from
'../types'
;
import
{
BOX_ANCHORS
,
INPUT_SIZES
,
IOU_THRESHOLD
,
NUM_BOXES
}
from
'./config'
;
import
{
sigmoid
}
from
'../utils'
;
import
{
BOX_ANCHORS
,
BOX_ANCHORS_SEPARABLE
,
INPUT_SIZES
,
IOU_THRESHOLD
,
NUM_BOXES
}
from
'./config'
;
import
{
convWithBatchNorm
}
from
'./convWithBatchNorm'
;
import
{
convWithBatchNorm
}
from
'./convWithBatchNorm'
;
import
{
extractParams
}
from
'./extractParams'
;
import
{
extractParams
}
from
'./extractParams'
;
import
{
getDefaultParams
}
from
'./getDefaultParams'
;
import
{
getDefaultParams
}
from
'./getDefaultParams'
;
import
{
loadQuantizedParams
}
from
'./loadQuantizedParams'
;
import
{
loadQuantizedParams
}
from
'./loadQuantizedParams'
;
import
{
NetParams
,
TinyYolov2ForwardParams
}
from
'./types'
;
import
{
NetParams
,
PostProcessingParams
,
TinyYolov2ForwardParams
}
from
'./types'
;
export
class
TinyYolov2
extends
NeuralNetwork
<
NetParams
>
{
export
class
TinyYolov2
extends
NeuralNetwork
<
NetParams
>
{
constructor
()
{
private
_hasSeparableConvs
:
boolean
private
_anchors
:
Point
[]
constructor
(
hasSeparableConvs
:
boolean
=
false
)
{
super
(
'TinyYolov2'
)
super
(
'TinyYolov2'
)
this
.
_hasSeparableConvs
=
hasSeparableConvs
this
.
_anchors
=
hasSeparableConvs
?
BOX_ANCHORS_SEPARABLE
:
BOX_ANCHORS
}
public
get
hasSeparableConvs
():
boolean
{
return
this
.
_hasSeparableConvs
}
public
get
anchors
():
Point
[]
{
return
this
.
_anchors
}
}
public
forwardInput
(
input
:
NetInput
,
inputSize
:
number
):
tf
.
Tensor4D
{
public
forwardInput
(
input
:
NetInput
,
inputSize
:
number
):
tf
.
Tensor4D
{
...
@@ -30,7 +45,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
...
@@ -30,7 +45,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
}
}
const
out
=
tf
.
tidy
(()
=>
{
const
out
=
tf
.
tidy
(()
=>
{
const
batchTensor
=
input
.
toBatchTensor
(
inputSize
,
false
).
div
(
tf
.
scalar
(
255
))
.
toFloat
()
as
tf
.
Tensor4D
const
batchTensor
=
input
.
toBatchTensor
(
inputSize
,
false
).
div
(
tf
.
scalar
(
255
))
as
tf
.
Tensor4D
let
out
=
convWithBatchNorm
(
batchTensor
,
params
.
conv0
)
let
out
=
convWithBatchNorm
(
batchTensor
,
params
.
conv0
)
out
=
tf
.
maxPool
(
out
,
[
2
,
2
],
[
2
,
2
],
'same'
)
out
=
tf
.
maxPool
(
out
,
[
2
,
2
],
[
2
,
2
],
'same'
)
...
@@ -72,39 +87,74 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
...
@@ -72,39 +87,74 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
const
netInput
=
await
toNetInput
(
input
,
true
)
const
netInput
=
await
toNetInput
(
input
,
true
)
const
out
=
await
this
.
forwardInput
(
netInput
,
inputSize
)
const
out
=
await
this
.
forwardInput
(
netInput
,
inputSize
)
const
numCells
=
out
.
shape
[
1
]
const
inputDimensions
=
{
width
:
netInput
.
getInputWidth
(
0
),
height
:
netInput
.
getInputHeight
(
0
)
}
const
paddings
=
new
Point
(
(
netInput
.
getPaddings
(
0
).
x
+
netInput
.
getInputWidth
(
0
))
/
netInput
.
getInputWidth
(
0
),
(
netInput
.
getPaddings
(
0
).
y
+
netInput
.
getInputHeight
(
0
))
/
netInput
.
getInputHeight
(
0
)
)
const
results
=
this
.
postProcess
(
out
,
{
scoreThreshold
,
paddings
})
const
boxes
=
results
.
map
(
res
=>
res
.
box
)
const
scores
=
results
.
map
(
res
=>
res
.
score
)
out
.
dispose
()
const
indices
=
nonMaxSuppression
(
boxes
.
map
(
box
=>
box
.
rescale
(
inputSize
)),
scores
,
IOU_THRESHOLD
,
true
)
const
detections
=
indices
.
map
(
idx
=>
new
FaceDetection
(
scores
[
idx
],
boxes
[
idx
].
toRect
(),
inputDimensions
)
)
return
detections
}
public
postProcess
(
outputTensor
:
tf
.
Tensor4D
,
{
scoreThreshold
,
paddings
}:
PostProcessingParams
)
{
const
numCells
=
outputTensor
.
shape
[
1
]
const
[
boxesTensor
,
scoresTensor
]
=
tf
.
tidy
(()
=>
{
const
[
boxesTensor
,
scoresTensor
]
=
tf
.
tidy
(()
=>
{
const
reshaped
=
out
.
reshape
([
numCells
,
numCells
,
NUM_BOXES
,
6
])
const
reshaped
=
outputTensor
.
reshape
([
numCells
,
numCells
,
NUM_BOXES
,
this
.
hasSeparableConvs
?
5
:
6
])
out
.
dispose
()
const
boxes
=
reshaped
.
slice
([
0
,
0
,
0
,
0
],
[
numCells
,
numCells
,
NUM_BOXES
,
4
])
const
boxes
=
reshaped
.
slice
([
0
,
0
,
0
,
0
],
[
numCells
,
numCells
,
NUM_BOXES
,
4
])
const
scores
=
reshaped
.
slice
([
0
,
0
,
0
,
4
],
[
numCells
,
numCells
,
NUM_BOXES
,
1
])
const
scores
=
reshaped
.
slice
([
0
,
0
,
0
,
4
],
[
numCells
,
numCells
,
NUM_BOXES
,
1
])
return
[
boxes
,
scores
]
return
[
boxes
,
scores
]
})
})
const
expit
=
(
x
:
number
):
number
=>
1
/
(
1
+
Math
.
exp
(
-
x
))
const
results
=
[]
const
paddedHeightRelative
=
(
netInput
.
getPaddings
(
0
).
y
+
netInput
.
getInputHeight
(
0
))
/
netInput
.
getInputHeight
(
0
)
const
paddedWidthRelative
=
(
netInput
.
getPaddings
(
0
).
x
+
netInput
.
getInputWidth
(
0
))
/
netInput
.
getInputWidth
(
0
)
const
boxes
:
BoundingBox
[]
=
[]
const
scores
:
number
[]
=
[]
for
(
let
row
=
0
;
row
<
numCells
;
row
++
)
{
for
(
let
row
=
0
;
row
<
numCells
;
row
++
)
{
for
(
let
col
=
0
;
col
<
numCells
;
col
++
)
{
for
(
let
col
=
0
;
col
<
numCells
;
col
++
)
{
for
(
let
box
=
0
;
box
<
NUM_BOXES
;
box
++
)
{
for
(
let
anchor
=
0
;
anchor
<
NUM_BOXES
;
anchor
++
)
{
const
score
=
expit
(
scoresTensor
.
get
(
row
,
col
,
box
,
0
))
const
score
=
sigmoid
(
scoresTensor
.
get
(
row
,
col
,
anchor
,
0
))
if
(
score
>
scoreThreshold
)
{
if
(
score
>
scoreThreshold
)
{
const
ctX
=
((
col
+
expit
(
boxesTensor
.
get
(
row
,
col
,
box
,
0
)))
/
numCells
)
*
paddedWidthRelative
const
ctX
=
((
col
+
sigmoid
(
boxesTensor
.
get
(
row
,
col
,
anchor
,
0
)))
/
numCells
)
*
paddings
.
x
const
ctY
=
((
row
+
expit
(
boxesTensor
.
get
(
row
,
col
,
box
,
1
)))
/
numCells
)
*
paddedHeightRelative
const
ctY
=
((
row
+
sigmoid
(
boxesTensor
.
get
(
row
,
col
,
anchor
,
1
)))
/
numCells
)
*
paddings
.
y
const
width
=
((
Math
.
exp
(
boxesTensor
.
get
(
row
,
col
,
box
,
2
))
*
BOX_ANCHORS
[
box
].
x
)
/
numCells
)
*
paddedWidthRelative
const
width
=
((
Math
.
exp
(
boxesTensor
.
get
(
row
,
col
,
anchor
,
2
))
*
this
.
anchors
[
anchor
].
x
)
/
numCells
)
*
paddings
.
x
const
height
=
((
Math
.
exp
(
boxesTensor
.
get
(
row
,
col
,
box
,
3
))
*
BOX_ANCHORS
[
box
].
y
)
/
numCells
)
*
paddedHeightRelative
const
height
=
((
Math
.
exp
(
boxesTensor
.
get
(
row
,
col
,
anchor
,
3
))
*
this
.
anchors
[
anchor
].
y
)
/
numCells
)
*
paddings
.
y
const
x
=
(
ctX
-
(
width
/
2
))
const
x
=
(
ctX
-
(
width
/
2
))
const
y
=
(
ctY
-
(
height
/
2
))
const
y
=
(
ctY
-
(
height
/
2
))
boxes
.
push
(
new
BoundingBox
(
x
,
y
,
x
+
width
,
y
+
height
))
results
.
push
({
scores
.
push
(
score
)
box
:
new
BoundingBox
(
x
,
y
,
x
+
width
,
y
+
height
),
score
,
row
,
col
,
anchor
})
}
}
}
}
}
}
...
@@ -113,27 +163,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
...
@@ -113,27 +163,7 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
boxesTensor
.
dispose
()
boxesTensor
.
dispose
()
scoresTensor
.
dispose
()
scoresTensor
.
dispose
()
const
indices
=
nonMaxSuppression
(
return
results
boxes
.
map
(
box
=>
new
BoundingBox
(
box
.
left
*
inputSize
,
box
.
top
*
inputSize
,
box
.
right
*
inputSize
,
box
.
bottom
*
inputSize
)),
scores
,
IOU_THRESHOLD
,
true
)
const
detections
=
indices
.
map
(
idx
=>
new
FaceDetection
(
scores
[
idx
],
boxes
[
idx
].
toRect
(),
{
width
:
netInput
.
getInputWidth
(
0
),
height
:
netInput
.
getInputHeight
(
0
)
}
)
)
return
detections
}
}
protected
loadQuantizedParams
(
uri
:
string
|
undefined
)
{
protected
loadQuantizedParams
(
uri
:
string
|
undefined
)
{
...
@@ -141,6 +171,6 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
...
@@ -141,6 +171,6 @@ export class TinyYolov2 extends NeuralNetwork<NetParams> {
}
}
protected
extractParams
(
weights
:
Float32Array
)
{
protected
extractParams
(
weights
:
Float32Array
)
{
return
extractParams
(
weights
)
return
extractParams
(
weights
,
this
.
hasSeparableConvs
)
}
}
}
}
\ No newline at end of file
src/tinyYolov2/config.ts
View file @
542dc68c
...
@@ -10,4 +10,12 @@ export const BOX_ANCHORS = [
...
@@ -10,4 +10,12 @@ export const BOX_ANCHORS = [
new
Point
(
4.30971
,
7.04493
),
new
Point
(
4.30971
,
7.04493
),
new
Point
(
10.246
,
4.59428
),
new
Point
(
10.246
,
4.59428
),
new
Point
(
12.6868
,
11.8741
)
new
Point
(
12.6868
,
11.8741
)
]
export
const
BOX_ANCHORS_SEPARABLE
=
[
new
Point
(
1.603231
,
2.094468
),
new
Point
(
6.041143
,
7.080126
),
new
Point
(
2.882459
,
3.518061
),
new
Point
(
4.266906
,
5.178857
),
new
Point
(
9.041765
,
10.66308
)
]
]
\ No newline at end of file
src/tinyYolov2/convWithBatchNorm.ts
View file @
542dc68c
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
leaky
}
from
'./leaky'
;
import
{
leaky
}
from
'./leaky'
;
import
{
ConvWithBatchNorm
}
from
'./types'
;
import
{
ConvWithBatchNorm
,
SeparableConvParams
}
from
'./types'
;
export
function
convWithBatchNorm
(
x
:
tf
.
Tensor4D
,
params
:
ConvWithBatchNorm
):
tf
.
Tensor4D
{
export
function
convWithBatchNorm
(
x
:
tf
.
Tensor4D
,
params
:
ConvWithBatchNorm
|
SeparableConvParams
):
tf
.
Tensor4D
{
return
tf
.
tidy
(()
=>
{
return
tf
.
tidy
(()
=>
{
let
out
=
tf
.
pad
(
x
,
[[
0
,
0
],
[
1
,
1
],
[
1
,
1
],
[
0
,
0
]])
as
tf
.
Tensor4D
let
out
=
tf
.
pad
(
x
,
[[
0
,
0
],
[
1
,
1
],
[
1
,
1
],
[
0
,
0
]])
as
tf
.
Tensor4D
out
=
tf
.
conv2d
(
out
,
params
.
conv
.
filters
,
[
1
,
1
],
'valid'
)
out
=
tf
.
sub
(
out
,
params
.
bn
.
sub
)
if
(
params
instanceof
SeparableConvParams
)
{
out
=
tf
.
mul
(
out
,
params
.
bn
.
truediv
)
out
=
tf
.
separableConv2d
(
out
,
params
.
depthwise_filter
,
params
.
pointwise_filter
,
[
1
,
1
],
'same'
)
out
=
tf
.
add
(
out
,
params
.
conv
.
bias
)
out
=
tf
.
add
(
out
,
params
.
bias
)
}
else
{
out
=
tf
.
conv2d
(
out
,
params
.
conv
.
filters
,
[
1
,
1
],
'valid'
)
out
=
tf
.
sub
(
out
,
params
.
bn
.
sub
)
out
=
tf
.
mul
(
out
,
params
.
bn
.
truediv
)
out
=
tf
.
add
(
out
,
params
.
conv
.
bias
)
}
return
leaky
(
out
)
return
leaky
(
out
)
})
})
}
}
\ No newline at end of file
src/tinyYolov2/extractParams.ts
View file @
542dc68c
...
@@ -3,7 +3,7 @@ import * as tf from '@tensorflow/tfjs-core';
...
@@ -3,7 +3,7 @@ import * as tf from '@tensorflow/tfjs-core';
import
{
extractConvParamsFactory
}
from
'../commons/extractConvParamsFactory'
;
import
{
extractConvParamsFactory
}
from
'../commons/extractConvParamsFactory'
;
import
{
extractWeightsFactory
}
from
'../commons/extractWeightsFactory'
;
import
{
extractWeightsFactory
}
from
'../commons/extractWeightsFactory'
;
import
{
ExtractWeightsFunction
,
ParamMapping
}
from
'../commons/types'
;
import
{
ExtractWeightsFunction
,
ParamMapping
}
from
'../commons/types'
;
import
{
BatchNorm
,
ConvWithBatchNorm
,
NetParams
}
from
'./types'
;
import
{
BatchNorm
,
ConvWithBatchNorm
,
NetParams
,
SeparableConvParams
}
from
'./types'
;
function
extractorsFactory
(
extractWeights
:
ExtractWeightsFunction
,
paramMappings
:
ParamMapping
[])
{
function
extractorsFactory
(
extractWeights
:
ExtractWeightsFunction
,
paramMappings
:
ParamMapping
[])
{
...
@@ -30,14 +30,34 @@ function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings
...
@@ -30,14 +30,34 @@ function extractorsFactory(extractWeights: ExtractWeightsFunction, paramMappings
return
{
conv
,
bn
}
return
{
conv
,
bn
}
}
}
function
extractSeparableConvParams
(
channelsIn
:
number
,
channelsOut
:
number
,
mappedPrefix
:
string
):
SeparableConvParams
{
console
.
log
(
mappedPrefix
)
const
depthwise_filter
=
tf
.
tensor4d
(
extractWeights
(
3
*
3
*
channelsIn
),
[
3
,
3
,
channelsIn
,
1
])
const
pointwise_filter
=
tf
.
tensor4d
(
extractWeights
(
channelsIn
*
channelsOut
),
[
1
,
1
,
channelsIn
,
channelsOut
])
const
bias
=
tf
.
tensor1d
(
extractWeights
(
channelsOut
))
console
.
log
(
'done'
)
paramMappings
.
push
(
{
paramPath
:
`
${
mappedPrefix
}
/depthwise_filter`
},
{
paramPath
:
`
${
mappedPrefix
}
/pointwise_filter`
},
{
paramPath
:
`
${
mappedPrefix
}
/bias`
}
)
return
new
SeparableConvParams
(
depthwise_filter
,
pointwise_filter
,
bias
)
}
return
{
return
{
extractConvParams
,
extractConvParams
,
extractConvWithBatchNormParams
extractConvWithBatchNormParams
,
extractSeparableConvParams
}
}
}
}
export
function
extractParams
(
weights
:
Float32Array
):
{
params
:
NetParams
,
paramMappings
:
ParamMapping
[]
}
{
export
function
extractParams
(
weights
:
Float32Array
,
hasSeparableConvs
:
boolean
):
{
params
:
NetParams
,
paramMappings
:
ParamMapping
[]
}
{
const
{
const
{
extractWeights
,
extractWeights
,
...
@@ -48,18 +68,22 @@ export function extractParams(weights: Float32Array): { params: NetParams, param
...
@@ -48,18 +68,22 @@ export function extractParams(weights: Float32Array): { params: NetParams, param
const
{
const
{
extractConvParams
,
extractConvParams
,
extractConvWithBatchNormParams
extractConvWithBatchNormParams
,
extractSeparableConvParams
}
=
extractorsFactory
(
extractWeights
,
paramMappings
)
}
=
extractorsFactory
(
extractWeights
,
paramMappings
)
const
conv0
=
extractConvWithBatchNormParams
(
3
,
16
,
'conv0'
)
const
extractConvFn
=
hasSeparableConvs
?
extractSeparableConvParams
:
extractConvWithBatchNormParams
const
conv1
=
extractConvWithBatchNormParams
(
16
,
32
,
'conv1'
)
const
numAnchorEncodings
=
hasSeparableConvs
?
5
:
6
const
conv2
=
extractConvWithBatchNormParams
(
32
,
64
,
'conv2'
)
const
conv3
=
extractConvWithBatchNormParams
(
64
,
128
,
'conv3'
)
const
conv0
=
extractConvFn
(
3
,
16
,
'conv0'
,)
const
conv4
=
extractConvWithBatchNormParams
(
128
,
256
,
'conv4'
)
const
conv1
=
extractConvFn
(
16
,
32
,
'conv1'
)
const
conv5
=
extractConvWithBatchNormParams
(
256
,
512
,
'conv5'
)
const
conv2
=
extractConvFn
(
32
,
64
,
'conv2'
)
const
conv6
=
extractConvWithBatchNormParams
(
512
,
1024
,
'conv6'
)
const
conv3
=
extractConvFn
(
64
,
128
,
'conv3'
)
const
conv7
=
extractConvWithBatchNormParams
(
1024
,
1024
,
'conv7'
)
const
conv4
=
extractConvFn
(
128
,
256
,
'conv4'
)
const
conv8
=
extractConvParams
(
1024
,
30
,
1
,
'conv8'
)
const
conv5
=
extractConvFn
(
256
,
512
,
'conv5'
)
const
conv6
=
extractConvFn
(
512
,
1024
,
'conv6'
)
const
conv7
=
extractConvFn
(
1024
,
1024
,
'conv7'
)
const
conv8
=
extractConvParams
(
1024
,
5
*
numAnchorEncodings
,
1
,
'conv8'
)
if
(
getRemainingWeights
().
length
!==
0
)
{
if
(
getRemainingWeights
().
length
!==
0
)
{
throw
new
Error
(
`weights remaing after extract:
${
getRemainingWeights
().
length
}
`
)
throw
new
Error
(
`weights remaing after extract:
${
getRemainingWeights
().
length
}
`
)
...
...
src/tinyYolov2/types.ts
View file @
542dc68c
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
*
as
tf
from
'@tensorflow/tfjs-core'
;
import
{
ConvParams
}
from
'../commons/types'
;
import
{
ConvParams
}
from
'../commons/types'
;
import
{
Point
}
from
'../Point'
;
export
type
BatchNorm
=
{
export
type
BatchNorm
=
{
sub
:
tf
.
Tensor1D
sub
:
tf
.
Tensor1D
truediv
:
tf
.
Tensor1D
truediv
:
tf
.
Tensor1D
}
}
export
class
SeparableConvParams
{
constructor
(
public
depthwise_filter
:
tf
.
Tensor4D
,
public
pointwise_filter
:
tf
.
Tensor4D
,
public
bias
:
tf
.
Tensor1D
)
{}
}
export
type
ConvWithBatchNorm
=
{
export
type
ConvWithBatchNorm
=
{
conv
:
ConvParams
conv
:
ConvParams
bn
:
BatchNorm
bn
:
BatchNorm
}
}
export
type
NetParams
=
{
export
type
NetParams
=
{
conv0
:
ConvWithBatchNorm
conv0
:
ConvWithBatchNorm
|
SeparableConvParams
conv1
:
ConvWithBatchNorm
conv1
:
ConvWithBatchNorm
|
SeparableConvParams
conv2
:
ConvWithBatchNorm
conv2
:
ConvWithBatchNorm
|
SeparableConvParams
conv3
:
ConvWithBatchNorm
conv3
:
ConvWithBatchNorm
|
SeparableConvParams
conv4
:
ConvWithBatchNorm
conv4
:
ConvWithBatchNorm
|
SeparableConvParams
conv5
:
ConvWithBatchNorm
conv5
:
ConvWithBatchNorm
|
SeparableConvParams
conv6
:
ConvWithBatchNorm
conv6
:
ConvWithBatchNorm
|
SeparableConvParams
conv7
:
ConvWithBatchNorm
conv7
:
ConvWithBatchNorm
|
SeparableConvParams
conv8
:
ConvParams
conv8
:
ConvParams
}
}
...
@@ -34,4 +43,9 @@ export enum SizeType {
...
@@ -34,4 +43,9 @@ export enum SizeType {
export
type
TinyYolov2ForwardParams
=
{
export
type
TinyYolov2ForwardParams
=
{
inputSize
?:
SizeType
|
number
inputSize
?:
SizeType
|
number
scoreThreshold
?:
number
scoreThreshold
?:
number
}
export
type
PostProcessingParams
=
{
scoreThreshold
:
number
paddings
:
Point
}
}
\ No newline at end of file
src/utils.ts
View file @
542dc68c
...
@@ -15,6 +15,14 @@ export function round(num: number) {
...
@@ -15,6 +15,14 @@ export function round(num: number) {
return
Math
.
floor
(
num
*
100
)
/
100
return
Math
.
floor
(
num
*
100
)
/
100
}
}
export
function
sigmoid
(
x
:
number
)
{
return
1
/
(
1
+
Math
.
exp
(
-
x
))
}
export
function
isDimensions
(
obj
:
any
):
boolean
{
return
obj
&&
obj
.
width
&&
obj
.
height
}
export
function
resolveInput
(
arg
:
string
|
any
)
{
export
function
resolveInput
(
arg
:
string
|
any
)
{
if
(
typeof
arg
===
'string'
)
{
if
(
typeof
arg
===
'string'
)
{
return
document
.
getElementById
(
arg
)
return
document
.
getElementById
(
arg
)
...
...
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