Skip to content

Commit 6ffc23e

Browse files
committed
fixed travis-cli errors
1 parent f863868 commit 6ffc23e

File tree

2 files changed

+93
-56
lines changed

2 files changed

+93
-56
lines changed

src/YOLO/index.js

Lines changed: 63 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ Heavily derived from https://github.com/ModelDepot/tfjs-yolo-tiny (ModelDepot: m
99
*/
1010
import * as tf from '@tensorflow/tfjs';
1111
import CLASS_NAMES from './../utils/COCO_CLASSES';
12+
import { iou } from './utils';
1213

1314
const DEFAULTS = {
1415
filterBoxesThreshold: 0.01,
1516
IOUThreshold: 0.4,
1617
classProbThreshold: 0.4,
17-
URL: 'https://raw.githubusercontent.com/ml5js/ml5-library/master/src/YOLO/model.json'
18+
URL: 'https://raw.githubusercontent.com/ml5js/ml5-library/master/src/YOLO/model.json',
1819

1920
};
2021

@@ -92,7 +93,7 @@ class YOLO {
9293
}
9394
}
9495

95-
//does not dispose of the model atm
96+
// does not dispose of the model atm
9697
dispose() {
9798
this.model = null;
9899
tf.disposeconstiables();
@@ -102,17 +103,17 @@ class YOLO {
102103
cache() {
103104
tf.tidy(() => {
104105
const dummy = tf.zeros([0, 416, 416, 3]);
105-
const data = this.model.predict(dummy);
106+
this.model.predict(dummy);
106107
});
107108
}
108109

109110
preProccess(input) {
110111
let img = tf.fromPixels(input);
112+
111113
this.imgWidth = img.shape[1];
112114
this.imgHeight = img.shape[0];
113-
img = tf.image.resizeBilinear(img, [this.inputHeight, this.inputWidth]).toFloat().div(tf.scalar(255)).expandDims(0);
114-
115115

116+
img = tf.image.resizeBilinear(img, [this.inputHeight, this.inputWidth]).toFloat().div(tf.scalar(255)).expandDims(0);
116117

117118
// Scale Stuff
118119
this.scaleX = this.imgHeight / this.inputHeight;
@@ -125,16 +126,15 @@ class YOLO {
125126
totalDetections: 0,
126127
detections: [],
127128
};
128-
const [boxes, boxScores, classes, Indices,] = tf.tidy(() => {
129-
130-
rawPrediction = tf.reshape(rawPrediction, [13, 13, this.anchorsLength, this.classesLength + 5]);
129+
const [boxes, boxScores, classes, Indices] = tf.tidy(() => {
130+
const rawPrediction1 = tf.reshape(rawPrediction, [13, 13, this.anchorsLength, this.classesLength + 5]);
131131
// Box Coords
132-
const boxXY = tf.sigmoid(rawPrediction.slice([0, 0, 0, 0], [13, 13, this.anchorsLength, 2]));
133-
const boxWH = tf.exp(rawPrediction.slice([0, 0, 0, 2], [13, 13, this.anchorsLength, 2]));
132+
const boxxy = tf.sigmoid(rawPrediction1.slice([0, 0, 0, 0], [13, 13, this.anchorsLength, 2]));
133+
const boxwh = tf.exp(rawPrediction1.slice([0, 0, 0, 2], [13, 13, this.anchorsLength, 2]));
134134
// ObjectnessScore
135-
const boxConfidence = tf.sigmoid(rawPrediction.slice([0, 0, 0, 4], [13, 13, this.anchorsLength, 1]));
135+
const boxConfidence = tf.sigmoid(rawPrediction1.slice([0, 0, 0, 4], [13, 13, this.anchorsLength, 1]));
136136
// ClassProb
137-
const boxClassProbs = tf.softmax(rawPrediction.slice([0, 0, 0, 5],[13, 13, this.anchorsLength, this.classesLength]));
137+
const boxClassProbs = tf.softmax(rawPrediction1.slice([0, 0, 0, 5], [13, 13, this.anchorsLength, this.classesLength]));
138138

139139
// from boxes with xy wh to x1,y1 x2,y2
140140
// Mainly for NMS + rescaling
@@ -145,94 +145,91 @@ class YOLO {
145145
y2 = y + (w/2)
146146
*/
147147
// BoxScale
148-
const BoxXY_1 = tf.div(tf.add(boxXY, this.ConvIndex), this.ConvDims);
148+
const boxXY1 = tf.div(tf.add(boxxy, this.ConvIndex), this.ConvDims);
149149

150-
const BoxWH_1 = tf.div(tf.mul(boxWH, this.AnchorsTensor), this.ConvDims);
150+
const boxWH1 = tf.div(tf.mul(boxwh, this.AnchorsTensor), this.ConvDims);
151151

152-
const Div = tf.div(BoxWH_1, tf.scalar(2));
152+
const Div = tf.div(boxWH1, tf.scalar(2));
153153

154-
const boxMins = tf.sub(BoxXY_1, Div);
155-
const boxMaxes = tf.add(BoxXY_1, Div);
154+
const boxMins = tf.sub(boxXY1, Div);
155+
const boxMaxes = tf.add(boxXY1, Div);
156156

157157
const size = [boxMins.shape[0], boxMins.shape[1], boxMins.shape[2], 1];
158158

159159
// main box tensor
160-
const boxes = tf.concat([boxMins.slice([0, 0, 0, 1], Size), boxMins.slice([0, 0, 0, 0], size), boxMaxes.slice([0, 0, 0, 1], size), boxMaxes.slice([0, 0, 0, 0], size)], 3).reshape([845, 4]);
160+
const finalboxes = tf.concat([
161+
boxMins.slice([0, 0, 0, 1], size),
162+
boxMins.slice([0, 0, 0, 0], size),
163+
boxMaxes.slice([0, 0, 0, 1], size),
164+
boxMaxes.slice([0, 0, 0, 0], size),
165+
], 3).reshape([845, 4]);
161166

162167
// Filterboxes by objectness threshold
163168
// not filtering / getting a mask really
164169

165-
const boxConfidence_1 = boxConfidence.squeeze([3]);
166-
const objectnessMask = tf.greaterEqual(boxConfidence_1,tf.scalar(this.filterBoxesThreshold));
170+
const boxConfidence1 = boxConfidence.squeeze([3]);
171+
const objectnessMask = tf.greaterEqual(boxConfidence1, tf.scalar(this.filterBoxesThreshold));
167172

168173
// Filterboxes by class probability threshold
169-
const boxScores = tf.mul(boxConfidence_1, tf.max(boxClassProbs, 3));
170-
const boxClassProbMask = tf.greaterEqual(boxScores,tf.scalar(this.classProbThreshold));
174+
const boxScores1 = tf.mul(boxConfidence1, tf.max(boxClassProbs, 3));
175+
const boxClassProbMask = tf.greaterEqual(boxScores, tf.scalar(this.classProbThreshold));
171176

172177
// getting classes indices
173-
const classes = tf.argMax(boxClassProbs, -1);
178+
const classes1 = tf.argMax(boxClassProbs, -1);
174179

175180
// Final Mask each elem that survived both filters (0x0 0x1 1x0 = fail ) 1x1 = survived
176181
const finalMask = boxClassProbMask.mul(objectnessMask);
177182

178183
const indices = finalMask.flatten().toInt().mul(this.indicesTensor);
179-
return [boxes, boxScores, classes, indices];
184+
return [finalboxes, boxScores1, classes1, indices];
180185
});
181186

182-
//we started at one in the range so we remove 1 now
187+
// we started at one in the range so we remove 1 now
183188

184-
let indicesArr = Array.from(await Indices.data()).filter(i => i > 0).map(i => i - 1);
189+
const indicesArr = Array.from(await Indices.data()).filter(i => i > 0).map(i => i - 1);
185190

186191
if (indicesArr.length === 0) {
187192
boxes.dispose();
188193
boxScores.dispose();
189194
classes.dispose();
190195
return results;
191196
}
192-
const [filteredBoxes, filteredScores, filteredclasses] = tf.tidy(()=>{
193-
const indicesTensor = tf.tensor1d(indicesArr, "int32");
194-
const filteredBoxes = boxes.gather(indicesTensor);
195-
const filteredScores = boxScores.flatten().gather(indicesTensor);
196-
const filteredclasses = classes.flatten().gather(indicesTensor);
197-
198-
// Img Rescale
199-
const Height = tf.scalar(this.imgHeight);
200-
const Width = tf.scalar(this.imgWidth);
201-
const ImageDims = tf.stack([Height, Width, Height, Width]).reshape([1, 4]);
202-
const filteredBoxes_1 = filteredBoxes.mul(ImageDims);
203-
204-
return [filteredBoxes_1, filteredScores, filteredclasses]
205-
})
206-
207-
197+
const [filteredBoxes, filteredScores, filteredclasses] = tf.tidy(() => {
198+
const indicesTensor = tf.tensor1d(indicesArr, 'int32');
199+
const filteredBoxes1 = boxes.gather(indicesTensor);
200+
const filteredScores1 = boxScores.flatten().gather(indicesTensor);
201+
const filteredclasses1 = classes.flatten().gather(indicesTensor);
202+
// Img Rescale
203+
const Height = tf.scalar(this.imgHeight);
204+
const Width = tf.scalar(this.imgWidth);
205+
const ImageDims = tf.stack([Height, Width, Height, Width]).reshape([1, 4]);
206+
const filteredBoxes2 = filteredBoxes1.mul(ImageDims);
207+
return [filteredBoxes2, filteredScores1, filteredclasses1];
208+
});
209+
208210
// NonMaxSuppression
209211
// GreedyNMS
210-
const [boxArr, scoreArr, classesArr] = await Promise.all([filteredBoxes.data(), filteredScores.data(), filteredclasses.data(), ]);
211-
212+
const [boxArr, scoreArr, classesArr] = await Promise.all([filteredBoxes.data(), filteredScores.data(), filteredclasses.data()]);
212213
filteredBoxes.dispose();
213214
filteredScores.dispose();
214215
filteredclasses.dispose();
215216

216-
let zipped = [];
217-
for (let i = 0; i < scoreArr.length; i++) {
217+
const zipped = [];
218+
for (let i = 0; i < scoreArr.length; i += 1) {
218219
// [Score,x,y,w,h,classindex]
219-
zipped.push([scoreArr[i], [boxArr[4 * i], boxArr[4 * i + 1], boxArr[4 * i + 2], boxArr[4 * i + 3]], classesArr[i]]);
220+
zipped.push([scoreArr[i], [boxArr[4 * i], boxArr[(4 * i) + 1], boxArr[(4 * i) + 2], boxArr[(4 * i) + 3]], classesArr[i]]);
220221
}
221222

222223
// Sort by descending order of scores (first index of zipped array)
223224
const sorted = zipped.sort((a, b) => b[0] - a[0]);
224225
const selectedBoxes = [];
225226
// Greedily go through boxes in descending score order and only
226227
// return boxes that are below the IoU threshold.
227-
sorted.forEach(box => {
228+
sorted.forEach((box) => {
228229
let Push = true;
229-
for (let i = 0; i < selectedBoxes.length; i++) {
230+
for (let i = 0; i < selectedBoxes.length; i += 1) {
230231
// Compare IoU of zipped[1], since that is the box coordinates arr
231-
let w =Math.min(box[1][3], selectedBoxes[i][1][3]) - Math.max(box[1][1], selectedBoxes[i][1][1]);
232-
let h =Math.min(box[1][2], selectedBoxes[i][1][2]) - Math.max(box[1][0], selectedBoxes[i][1][0]);
233-
let Intersection = w < 0 || h < 0 ? 0 : w * h;
234-
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;
235-
let Iou = Intersection / Union;
232+
const Iou = iou(box[1], selectedBoxes[i]);
236233
if (Iou > this.IOUThreshold) {
237234
Push = false;
238235
break;
@@ -244,15 +241,25 @@ class YOLO {
244241
// final phase
245242

246243
// add any output you want
247-
for (let id = 0; id < selectedBoxes.length; id++) {
244+
for (let id = 0; id < selectedBoxes.length; id += 1) {
248245
const classProb = selectedBoxes[id][0];
249246
const classProbRounded = Math.round(classProb * 1000) / 10;
250247
const className = this.classNames[selectedBoxes[id][2]];
251248
const classIndex = selectedBoxes[id][2];
252249
const [x1, y1, x2, y2] = selectedBoxes[id][1];
253250
// Need to get this out
254251
// TODO : add a hsla color for later visualization
255-
const resultObj = {id, className, classIndex, classProb, classProbRounded, x1, y1, x2, y2, };
252+
const resultObj = {
253+
id,
254+
className,
255+
classIndex,
256+
classProb,
257+
classProbRounded,
258+
x1,
259+
y1,
260+
x2,
261+
y2,
262+
};
256263
results.detections.push(resultObj);
257264
}
258265
// Misc

src/YOLO/utils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2018 ml5
2+
//
3+
// This software is released under the MIT License.
4+
// https://opensource.org/licenses/MIT
5+
6+
/* eslint max-len: ["error", { "code": 180 }] */
7+
8+
const iou = (box1, box2) => {
9+
/* Implement the intersection over union (IoU) between box1 and box2
10+
Arguments:
11+
box1 -- first box, list object with coordinates (x1, y1, x2, y2)
12+
box2 -- second box, list object with coordinates (x1, y1, x2, y2)
13+
*/
14+
15+
// Calculate the (y1, x1, y2, x2) coordinates of the intersection of box1 and box2. Calculate its Area.
16+
const xi1 = Math.max(box1[0], box2[0]);
17+
const yi1 = Math.max(box1[1], box2[1]);
18+
const xi2 = Math.min(box1[2], box2[2]);
19+
const yi2 = Math.min(box1[3], box2[3]);
20+
const interarea = (yi2 - yi1) * (xi2 - xi1);
21+
22+
// Calculate the Union area by using Formula: Union(A,B) = A + B - Inter(A,B)
23+
const box1area = (box1[2] - box1[0]) * (box1[3] - box1[1]);
24+
const box2area = (box2[2] - box2[0]) * (box2[3] - box2[1]);
25+
const unionarea = (box1area + box2area) - interarea;
26+
27+
// compute the IoU
28+
return interarea / unionarea;
29+
};
30+
export default iou;

0 commit comments

Comments
 (0)