1
+ // Copyright (c) 2019 ml5
2
+ //
3
+ // This software is released under the MIT License.
4
+ // https://opensource.org/licenses/MIT
5
+
6
+ /*
7
+ COCO-SSD Object detection
8
+ Wraps the coco-ssd model in tfjs to be used in ml5
9
+ */
10
+ import * as tf from "@tensorflow/tfjs" ;
11
+ import * as cocoSsd from "@tensorflow-models/coco-ssd" ;
12
+ import callCallback from "../utils/callcallback" ;
13
+ import handleArguments from "../utils/handleArguments" ;
14
+
15
+ const DEFAULTS = {
16
+ base : "lite_mobilenet_v2" ,
17
+ modelUrl : undefined ,
18
+ } ;
19
+
20
+ export class CocoSsdBase {
21
+ /**
22
+ * Create CocoSsd model. Works on video and images.
23
+ * @param {function } constructorCallback - Optional. A callback function that is called once the model has loaded. If no callback is provided, it will return a promise
24
+ * that will be resolved once the model has loaded.
25
+ */
26
+ constructor ( video , options , constructorCallback ) {
27
+ this . video = video || null ;
28
+ this . modelReady = false ;
29
+ this . isPredicting = false ;
30
+ this . config = {
31
+ base : options . base || DEFAULTS . base ,
32
+ modelUrl : options . modelUrl || DEFAULTS . modelUrl ,
33
+ } ;
34
+ this . callback = constructorCallback ;
35
+
36
+ this . ready = callCallback ( this . loadModel ( ) , this . callback ) ;
37
+ }
38
+
39
+ /**
40
+ * load model
41
+ */
42
+ async loadModel ( ) {
43
+ this . model = await cocoSsd . load ( this . config ) ;
44
+
45
+ this . modelReady = true ;
46
+ return this ;
47
+ }
48
+
49
+ /**
50
+ * @typedef {Object } ObjectDetectorPrediction
51
+ * @property {number } x - top left x coordinate of the prediction box in pixels.
52
+ * @property {number } y - top left y coordinate of the prediction box in pixels.
53
+ * @property {number } width - width of the prediction box in pixels.
54
+ * @property {number } height - height of the prediction box in pixels.
55
+ * @property {string } label - the label given.
56
+ * @property {number } confidence - the confidence score (0 to 1).
57
+ * @property {ObjectDetectorPredictionNormalized } normalized - a normalized object of the predicition
58
+ */
59
+
60
+ /**
61
+ * @typedef {Object } ObjectDetectorPredictionNormalized
62
+ * @property {number } x - top left x coordinate of the prediction box (0 to 1).
63
+ * @property {number } y - top left y coordinate of the prediction box (0 to 1).
64
+ * @property {number } width - width of the prediction box (0 to 1).
65
+ * @property {number } height - height of the prediction box (0 to 1).
66
+ */
67
+ /**
68
+ * Detect objects that are in video, returns bounding box, label, and confidence scores
69
+ * @param {HTMLVideoElement|HTMLImageElement|HTMLCanvasElement|ImageData } subject - Subject of the detection.
70
+ * @returns {ObjectDetectorPrediction }
71
+ */
72
+ async detectInternal ( imgToPredict ) {
73
+ this . isPredicting = true ;
74
+ const predictions = await this . model . detect ( imgToPredict ) ;
75
+ const formattedPredictions = predictions . map ( prediction => {
76
+ return {
77
+ label : prediction . class ,
78
+ confidence : prediction . score ,
79
+ x : prediction . bbox [ 0 ] ,
80
+ y : prediction . bbox [ 1 ] ,
81
+ width : prediction . bbox [ 2 ] ,
82
+ height : prediction . bbox [ 3 ] ,
83
+ normalized : {
84
+ x : prediction . bbox [ 0 ] / imgToPredict . width ,
85
+ y : prediction . bbox [ 1 ] / imgToPredict . height ,
86
+ width : prediction . bbox [ 2 ] / imgToPredict . width ,
87
+ height : prediction . bbox [ 3 ] / imgToPredict . height ,
88
+ } ,
89
+ } ;
90
+ } ) ;
91
+ this . isPredicting = false ;
92
+ return formattedPredictions ;
93
+ }
94
+
95
+ /**
96
+ * Detect objects that are in video, returns bounding box, label, and confidence scores
97
+ * @param {HTMLVideoElement|HTMLImageElement|HTMLCanvasElement|ImageData } subject - Subject of the detection.
98
+ * @param {function } callback - Optional. A callback function that is called once the model has loaded. If no callback is provided, it will return a promise
99
+ * that will be resolved once the prediction is done.
100
+ * @returns {ObjectDetectorPrediction }
101
+ */
102
+ async detect ( inputOrCallback , cb ) {
103
+ await this . ready ;
104
+ await tf . nextFrame ( ) ;
105
+
106
+ const args = handleArguments ( this . video , inputOrCallback , cb ) ;
107
+ args . require ( "image" , "Detection subject not supported" ) ;
108
+
109
+ return callCallback ( this . detectInternal ( args . image ) , args . callback ) ;
110
+ }
111
+ }
112
+
113
+ export const CocoSsd = ( ...inputs ) => {
114
+ const { video, options = { } , callback } = handleArguments ( ...inputs ) ;
115
+ return new CocoSsdBase ( video , options , callback ) ;
116
+ } ;
117
+
118
+ // export default CocoSsd;
0 commit comments