3
3
// This software is released under the MIT License.
4
4
// https://opensource.org/licenses/MIT
5
5
/* eslint max-len: ["error", { "code": 180 }] */
6
-
7
6
/*
8
7
YOLO Object detection
9
8
Heavily derived from https://github.com/ModelDepot/tfjs-yolo-tiny (ModelDepot: modeldepot.io)
10
9
*/
11
-
12
10
import * as tf from "@tensorflow/tfjs" ;
13
11
import CLASS_NAMES from "./../utils/COCO_CLASSES" ;
14
12
15
13
const DEFAULTS = {
16
14
filterBoxesThreshold : 0.01 ,
17
15
IOUThreshold : 0.4 ,
18
16
classProbThreshold : 0.4 ,
19
- URL : "https://raw.githubusercontent.com/ml5js/ml5-library/master/src/YOLO/model.json"
17
+ URL :
18
+ "https://raw.githubusercontent.com/ml5js/ml5-library/master/src/YOLO/model.json"
20
19
} ;
21
20
22
21
class YOLO {
23
22
constructor ( options ) {
24
- this . filterBoxesThreshold =
25
- options . filterBoxesThreshold || DEFAULTS . filterBoxesThreshold ;
23
+ this . filterBoxesThreshold = options . filterBoxesThreshold || DEFAULTS . filterBoxesThreshold ;
26
24
this . IOUThreshold = options . IOUThreshold || DEFAULTS . IOUThreshold ;
27
- this . classProbThreshold =
28
- options . classProbThreshold || DEFAULTS . classProbThreshold ;
25
+ this . classProbThreshold = options . classProbThreshold || DEFAULTS . classProbThreshold ;
29
26
this . modelURL = options . url || DEFAULTS . URL ;
30
27
this . model = null ;
31
28
this . inputWidth = 416 ;
@@ -112,54 +109,40 @@ class YOLO {
112
109
let img = tf . fromPixels ( input ) ;
113
110
this . imgWidth = img . shape [ 1 ] ;
114
111
this . imgHeight = img . shape [ 0 ] ;
115
- img = tf . image
116
- . resizeBilinear ( img , [ this . inputHeight , this . inputWidth ] )
117
- . toFloat ( )
118
- . div ( tf . scalar ( 255 ) )
119
- . expandDims ( 0 ) ;
112
+ img = tf . image . resizeBilinear ( img , [ this . inputHeight , this . inputWidth ] )
113
+ . toFloat ( )
114
+ . div ( tf . scalar ( 255 ) )
115
+ . expandDims ( 0 ) ;
120
116
//Scale Stuff
121
117
this . scaleX = this . imgHeight / this . inputHeight ;
122
118
this . scaleY = this . imgWidth / this . inputWidth ;
123
119
return img ;
124
120
}
125
121
126
122
async postProccess ( rawPrediction ) {
127
- let results = { totalDetections : 0 , detections : [ ] } ;
123
+ let results = {
124
+ totalDetections : 0 ,
125
+ detections : [ ]
126
+ } ;
128
127
129
128
const [ boxes , boxScores , classes , Indices ] = tf . tidy ( ( ) => {
130
- rawPrediction = tf . reshape ( rawPrediction , [
131
- 13 ,
132
- 13 ,
133
- this . anchorsLength ,
134
- this . classesLength + 5
135
- ] ) ;
129
+ rawPrediction = tf . reshape ( rawPrediction , [ 13 , 13 , this . anchorsLength , this . classesLength + 5 ] ) ;
136
130
// Box Coords
137
- let BoxXY = tf . sigmoid (
138
- rawPrediction . slice ( [ 0 , 0 , 0 , 0 ] , [ 13 , 13 , this . anchorsLength , 2 ] )
139
- ) ;
140
- let BoxWH = tf . exp (
141
- rawPrediction . slice ( [ 0 , 0 , 0 , 2 ] , [ 13 , 13 , this . anchorsLength , 2 ] )
142
- ) ;
131
+ let BoxXY = tf . sigmoid ( rawPrediction . slice ( [ 0 , 0 , 0 , 0 ] , [ 13 , 13 , this . anchorsLength , 2 ] ) ) ;
132
+ let BoxWH = tf . exp ( rawPrediction . slice ( [ 0 , 0 , 0 , 2 ] , [ 13 , 13 , this . anchorsLength , 2 ] ) ) ;
143
133
// ObjectnessScore
144
- let BoxConfidence = tf . sigmoid (
145
- rawPrediction . slice ( [ 0 , 0 , 0 , 4 ] , [ 13 , 13 , this . anchorsLength , 1 ] )
146
- ) ;
134
+ let BoxConfidence = tf . sigmoid ( rawPrediction . slice ( [ 0 , 0 , 0 , 4 ] , [ 13 , 13 , this . anchorsLength , 1 ] ) ) ;
147
135
// ClassProb
148
- let BoxClassProbs = tf . softmax (
149
- rawPrediction . slice (
150
- [ 0 , 0 , 0 , 5 ] ,
151
- [ 13 , 13 , this . anchorsLength , this . classesLength ]
152
- )
153
- ) ;
136
+ let BoxClassProbs = tf . softmax ( rawPrediction . slice ( [ 0 , 0 , 0 , 5 ] , [ 13 , 13 , this . anchorsLength , this . classesLength ] ) ) ;
154
137
155
138
// from boxes with xy wh to x1,y1 x2,y2
156
139
// Mainly for NMS + rescaling
157
140
/*
158
- x1 = x + (h/2)
159
- y1 = y - (w/2)
160
- x2 = x - (h/2)
161
- y2 = y + (w/2)
162
- */
141
+ x1 = x + (h/2)
142
+ y1 = y - (w/2)
143
+ x2 = x - (h/2)
144
+ y2 = y + (w/2)
145
+ */
163
146
// BoxScale
164
147
BoxXY = tf . div ( tf . add ( BoxXY , this . ConvIndex ) , this . ConvDims ) ;
165
148
@@ -180,9 +163,7 @@ class YOLO {
180
163
BoxMins . slice ( [ 0 , 0 , 0 , 0 ] , Size ) ,
181
164
BoxMaxes . slice ( [ 0 , 0 , 0 , 1 ] , Size ) ,
182
165
BoxMaxes . slice ( [ 0 , 0 , 0 , 0 ] , Size )
183
- ] ,
184
- 3
185
- )
166
+ ] , 3 )
186
167
. reshape ( [ 845 , 4 ] ) ;
187
168
188
169
// Filterboxes by objectness threshold
@@ -254,16 +235,7 @@ class YOLO {
254
235
let zipped = [ ] ;
255
236
for ( let i = 0 ; i < scoreArr . length ; i ++ ) {
256
237
// [Score,x,y,w,h,classindex]
257
- zipped . push ( [
258
- scoreArr [ i ] ,
259
- [
260
- boxArr [ 4 * i ] ,
261
- boxArr [ 4 * i + 1 ] ,
262
- boxArr [ 4 * i + 2 ] ,
263
- boxArr [ 4 * i + 3 ]
264
- ] ,
265
- classesArr [ i ]
266
- ] ) ;
238
+ zipped . push ( [ scoreArr [ i ] , [ boxArr [ 4 * i ] , boxArr [ 4 * i + 1 ] , boxArr [ 4 * i + 2 ] , boxArr [ 4 * i + 3 ] ] , classesArr [ i ] ] ) ;
267
239
}
268
240
269
241
// Sort by descending order of scores (first index of zipped array)
@@ -275,18 +247,10 @@ class YOLO {
275
247
let Push = true ;
276
248
for ( let i = 0 ; i < selectedBoxes . length ; i ++ ) {
277
249
// Compare IoU of zipped[1], since that is the box coordinates arr
278
- let w =
279
- Math . min ( box [ 1 ] [ 3 ] , selectedBoxes [ i ] [ 1 ] [ 3 ] ) -
280
- Math . max ( box [ 1 ] [ 1 ] , selectedBoxes [ i ] [ 1 ] [ 1 ] ) ;
281
- let h =
282
- Math . min ( box [ 1 ] [ 2 ] , selectedBoxes [ i ] [ 1 ] [ 2 ] ) -
283
- Math . max ( box [ 1 ] [ 0 ] , selectedBoxes [ i ] [ 1 ] [ 0 ] ) ;
250
+ let w = Math . min ( box [ 1 ] [ 3 ] , selectedBoxes [ i ] [ 1 ] [ 3 ] ) - Math . max ( box [ 1 ] [ 1 ] , selectedBoxes [ i ] [ 1 ] [ 1 ] ) ;
251
+ let h = Math . min ( box [ 1 ] [ 2 ] , selectedBoxes [ i ] [ 1 ] [ 2 ] ) - Math . max ( box [ 1 ] [ 0 ] , selectedBoxes [ i ] [ 1 ] [ 0 ] ) ;
284
252
let Intersection = w < 0 || h < 0 ? 0 : w * h ;
285
- let Union =
286
- ( box [ 1 ] [ 3 ] - box [ 1 ] [ 1 ] ) * ( box [ 1 ] [ 2 ] - box [ 1 ] [ 0 ] ) +
287
- ( selectedBoxes [ i ] [ 1 ] [ 3 ] - selectedBoxes [ i ] [ 1 ] [ 1 ] ) *
288
- ( selectedBoxes [ i ] [ 1 ] [ 2 ] - selectedBoxes [ i ] [ 1 ] [ 0 ] ) -
289
- Intersection ;
253
+ let Union = ( box [ 1 ] [ 3 ] - box [ 1 ] [ 1 ] ) * ( box [ 1 ] [ 2 ] - box [ 1 ] [ 0 ] ) + ( selectedBoxes [ i ] [ 1 ] [ 3 ] - selectedBoxes [ i ] [ 1 ] [ 1 ] ) * ( selectedBoxes [ i ] [ 1 ] [ 2 ] - selectedBoxes [ i ] [ 1 ] [ 0 ] ) - Intersection ;
290
254
let Iou = Intersection / Union ;
291
255
if ( Iou > this . IOUThreshold ) {
292
256
Push = false ;
0 commit comments