@tensorflow-models/coco-ssd
Advanced tools
Comparing version 2.0.3 to 2.0.4
@@ -0,1 +1,17 @@ | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
export interface ObjectDetectionClass { | ||
@@ -2,0 +18,0 @@ name: string; |
@@ -1,4 +0,18 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CLASSES = { | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
export const CLASSES = { | ||
1: { | ||
@@ -5,0 +19,0 @@ name: '/m/01g317', |
/** | ||
* @license | ||
* Copyright 2020 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
* @license | ||
* Copyright 2020 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-converter'), require('@tensorflow/tfjs-core')) : | ||
typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-converter', '@tensorflow/tfjs-core'], factory) : | ||
(factory((global.cocoSsd = {}),global.tf,global.tf)); | ||
}(this, (function (exports,tfconv,tf) { 'use strict'; | ||
(global = global || self, factory(global.cocoSsd = global.cocoSsd || {}, global.tfconv, global.tf)); | ||
}(this, (function (exports, tfconv, tf) { 'use strict'; | ||
@@ -75,19 +75,18 @@ /*! ***************************************************************************** | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
var CLASSES = { | ||
@@ -496,4 +495,22 @@ 1: { | ||
var version = '2.0.3'; | ||
/** @license See the LICENSE file. */ | ||
// This code is auto-generated, do not modify this file! | ||
var version = '2.0.4'; | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
var BASE_PATH = 'https://storage.googleapis.com/tfjs-models/savedmodel/'; | ||
@@ -520,6 +537,6 @@ function load(config) { | ||
objectDetection = new ObjectDetection(base, modelUrl); | ||
return [4, objectDetection.load()]; | ||
return [4 /*yield*/, objectDetection.load()]; | ||
case 1: | ||
_a.sent(); | ||
return [2, objectDetection]; | ||
return [2 /*return*/, objectDetection]; | ||
} | ||
@@ -529,3 +546,3 @@ }); | ||
} | ||
var ObjectDetection = (function () { | ||
var ObjectDetection = /** @class */ (function () { | ||
function ObjectDetection(base, modelUrl) { | ||
@@ -545,10 +562,10 @@ this.modelPath = | ||
_a = this; | ||
return [4, tfconv.loadGraphModel(this.modelPath)]; | ||
return [4 /*yield*/, tfconv.loadGraphModel(this.modelPath)]; | ||
case 1: | ||
_a.model = _b.sent(); | ||
zeroTensor = tf.zeros([1, 300, 300, 3], 'int32'); | ||
return [4, this.model.executeAsync(zeroTensor)]; | ||
return [4 /*yield*/, this.model.executeAsync(zeroTensor)]; | ||
case 2: | ||
result = _b.sent(); | ||
return [4, Promise.all(result.map(function (t) { return t.data(); }))]; | ||
return [4 /*yield*/, Promise.all(result.map(function (t) { return t.data(); }))]; | ||
case 3: | ||
@@ -558,3 +575,3 @@ _b.sent(); | ||
zeroTensor.dispose(); | ||
return [2]; | ||
return [2 /*return*/]; | ||
} | ||
@@ -564,3 +581,14 @@ }); | ||
}; | ||
ObjectDetection.prototype.infer = function (img, maxNumBoxes) { | ||
/** | ||
* Infers through the model. | ||
* | ||
* @param img The image to classify. Can be a tensor or a DOM element image, | ||
* video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
ObjectDetection.prototype.infer = function (img, maxNumBoxes, minScore) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -575,2 +603,3 @@ var batched, height, width, result, scores, boxes, _a, maxScores, classes, prevBackend, indexTensor, indexes; | ||
} | ||
// Reshape to a single-element batch so we can pass it to executeAsync. | ||
return img.expandDims(0); | ||
@@ -580,3 +609,3 @@ }); | ||
width = batched.shape[2]; | ||
return [4, this.model.executeAsync(batched)]; | ||
return [4 /*yield*/, this.model.executeAsync(batched)]; | ||
case 1: | ||
@@ -586,15 +615,18 @@ result = _b.sent(); | ||
boxes = result[1].dataSync(); | ||
// clean the webgl tensors | ||
batched.dispose(); | ||
tf.dispose(result); | ||
_a = __read(this.calculateMaxScores(scores, result[0].shape[1], result[0].shape[2]), 2), maxScores = _a[0], classes = _a[1]; | ||
_a = this.calculateMaxScores(scores, result[0].shape[1], result[0].shape[2]), maxScores = _a[0], classes = _a[1]; | ||
prevBackend = tf.getBackend(); | ||
// run post process in cpu | ||
tf.setBackend('cpu'); | ||
indexTensor = tf.tidy(function () { | ||
var boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]); | ||
return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, 0.5, 0.5); | ||
return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, minScore, minScore); | ||
}); | ||
indexes = indexTensor.dataSync(); | ||
indexTensor.dispose(); | ||
// restore previous backend | ||
tf.setBackend(prevBackend); | ||
return [2, this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes)]; | ||
return [2 /*return*/, this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes)]; | ||
} | ||
@@ -645,10 +677,27 @@ }); | ||
}; | ||
ObjectDetection.prototype.detect = function (img, maxNumBoxes) { | ||
/** | ||
* Detect objects for an image returning a list of bounding boxes with | ||
* assocated class and score. | ||
* | ||
* @param img The image to detect objects from. Can be a tensor or a DOM | ||
* element image, video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
ObjectDetection.prototype.detect = function (img, maxNumBoxes, minScore) { | ||
if (maxNumBoxes === void 0) { maxNumBoxes = 20; } | ||
if (minScore === void 0) { minScore = 0.5; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2, this.infer(img, maxNumBoxes)]; | ||
return [2 /*return*/, this.infer(img, maxNumBoxes, minScore)]; | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Dispose the tensors allocated by the model. You should call this when you | ||
* are done with the model. | ||
*/ | ||
ObjectDetection.prototype.dispose = function () { | ||
@@ -662,4 +711,4 @@ if (this.model != null) { | ||
exports.ObjectDetection = ObjectDetection; | ||
exports.load = load; | ||
exports.ObjectDetection = ObjectDetection; | ||
exports.version = version; | ||
@@ -670,1 +719,2 @@ | ||
}))); | ||
//# sourceMappingURL=coco-ssd.js.map |
/** | ||
* @license | ||
* Copyright 2020 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
!function(e,a){"object"==typeof exports&&"undefined"!=typeof module?a(exports,require("@tensorflow/tfjs-converter"),require("@tensorflow/tfjs-core")):"function"==typeof define&&define.amd?define(["exports","@tensorflow/tfjs-converter","@tensorflow/tfjs-core"],a):a(e.cocoSsd={},e.tf,e.tf)}(this,function(e,a,i){"use strict";function n(e,a,i,n){return new(i||(i=Promise))(function(t,m){function d(e){try{r(n.next(e))}catch(e){m(e)}}function s(e){try{r(n.throw(e))}catch(e){m(e)}}function r(e){e.done?t(e.value):new i(function(a){a(e.value)}).then(d,s)}r((n=n.apply(e,a||[])).next())})}function t(e,a){var i,n,t,m,d={label:0,sent:function(){if(1&t[0])throw t[1];return t[1]},trys:[],ops:[]};return m={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(m[Symbol.iterator]=function(){return this}),m;function s(m){return function(s){return function(m){if(i)throw new TypeError("Generator is already executing.");for(;d;)try{if(i=1,n&&(t=2&m[0]?n.return:m[0]?n.throw||((t=n.return)&&t.call(n),0):n.next)&&!(t=t.call(n,m[1])).done)return t;switch(n=0,t&&(m=[2&m[0],t.value]),m[0]){case 0:case 1:t=m;break;case 4:return d.label++,{value:m[1],done:!1};case 5:d.label++,n=m[1],m=[0];continue;case 7:m=d.ops.pop(),d.trys.pop();continue;default:if(!(t=(t=d.trys).length>0&&t[t.length-1])&&(6===m[0]||2===m[0])){d=0;continue}if(3===m[0]&&(!t||m[1]>t[0]&&m[1]<t[3])){d.label=m[1];break}if(6===m[0]&&d.label<t[1]){d.label=t[1],t=m;break}if(t&&d.label<t[2]){d.label=t[2],d.ops.push(m);break}t[2]&&d.ops.pop(),d.trys.pop();continue}m=a.call(e,d)}catch(e){m=[6,e],n=0}finally{i=t=0}if(5&m[0])throw m[1];return{value:m[0]?m[1]:void 0,done:!0}}([m,s])}}}var m={1:{name:"/m/01g317",id:1,displayName:"person"},2:{name:"/m/0199g",id:2,displayName:"bicycle"},3:{name:"/m/0k4j",id:3,displayName:"car"},4:{name:"/m/04_sv",id:4,displayName:"motorcycle"},5:{name:"/m/05czz6l",id:5,displayName:"airplane"},6:{name:"/m/01bjv",id:6,displayName:"bus"},7:{name:"/m/07jdr",id:7,displayName:"train"},8:{name:"/m/07r04",id:8,displayName:"truck"},9:{name:"/m/019jd",id:9,displayName:"boat"},10:{name:"/m/015qff",id:10,displayName:"traffic light"},11:{name:"/m/01pns0",id:11,displayName:"fire hydrant"},13:{name:"/m/02pv19",id:13,displayName:"stop sign"},14:{name:"/m/015qbp",id:14,displayName:"parking meter"},15:{name:"/m/0cvnqh",id:15,displayName:"bench"},16:{name:"/m/015p6",id:16,displayName:"bird"},17:{name:"/m/01yrx",id:17,displayName:"cat"},18:{name:"/m/0bt9lr",id:18,displayName:"dog"},19:{name:"/m/03k3r",id:19,displayName:"horse"},20:{name:"/m/07bgp",id:20,displayName:"sheep"},21:{name:"/m/01xq0k1",id:21,displayName:"cow"},22:{name:"/m/0bwd_0j",id:22,displayName:"elephant"},23:{name:"/m/01dws",id:23,displayName:"bear"},24:{name:"/m/0898b",id:24,displayName:"zebra"},25:{name:"/m/03bk1",id:25,displayName:"giraffe"},27:{name:"/m/01940j",id:27,displayName:"backpack"},28:{name:"/m/0hnnb",id:28,displayName:"umbrella"},31:{name:"/m/080hkjn",id:31,displayName:"handbag"},32:{name:"/m/01rkbr",id:32,displayName:"tie"},33:{name:"/m/01s55n",id:33,displayName:"suitcase"},34:{name:"/m/02wmf",id:34,displayName:"frisbee"},35:{name:"/m/071p9",id:35,displayName:"skis"},36:{name:"/m/06__v",id:36,displayName:"snowboard"},37:{name:"/m/018xm",id:37,displayName:"sports ball"},38:{name:"/m/02zt3",id:38,displayName:"kite"},39:{name:"/m/03g8mr",id:39,displayName:"baseball bat"},40:{name:"/m/03grzl",id:40,displayName:"baseball glove"},41:{name:"/m/06_fw",id:41,displayName:"skateboard"},42:{name:"/m/019w40",id:42,displayName:"surfboard"},43:{name:"/m/0dv9c",id:43,displayName:"tennis racket"},44:{name:"/m/04dr76w",id:44,displayName:"bottle"},46:{name:"/m/09tvcd",id:46,displayName:"wine glass"},47:{name:"/m/08gqpm",id:47,displayName:"cup"},48:{name:"/m/0dt3t",id:48,displayName:"fork"},49:{name:"/m/04ctx",id:49,displayName:"knife"},50:{name:"/m/0cmx8",id:50,displayName:"spoon"},51:{name:"/m/04kkgm",id:51,displayName:"bowl"},52:{name:"/m/09qck",id:52,displayName:"banana"},53:{name:"/m/014j1m",id:53,displayName:"apple"},54:{name:"/m/0l515",id:54,displayName:"sandwich"},55:{name:"/m/0cyhj_",id:55,displayName:"orange"},56:{name:"/m/0hkxq",id:56,displayName:"broccoli"},57:{name:"/m/0fj52s",id:57,displayName:"carrot"},58:{name:"/m/01b9xk",id:58,displayName:"hot dog"},59:{name:"/m/0663v",id:59,displayName:"pizza"},60:{name:"/m/0jy4k",id:60,displayName:"donut"},61:{name:"/m/0fszt",id:61,displayName:"cake"},62:{name:"/m/01mzpv",id:62,displayName:"chair"},63:{name:"/m/02crq1",id:63,displayName:"couch"},64:{name:"/m/03fp41",id:64,displayName:"potted plant"},65:{name:"/m/03ssj5",id:65,displayName:"bed"},67:{name:"/m/04bcr3",id:67,displayName:"dining table"},70:{name:"/m/09g1w",id:70,displayName:"toilet"},72:{name:"/m/07c52",id:72,displayName:"tv"},73:{name:"/m/01c648",id:73,displayName:"laptop"},74:{name:"/m/020lf",id:74,displayName:"mouse"},75:{name:"/m/0qjjc",id:75,displayName:"remote"},76:{name:"/m/01m2v",id:76,displayName:"keyboard"},77:{name:"/m/050k8",id:77,displayName:"cell phone"},78:{name:"/m/0fx9l",id:78,displayName:"microwave"},79:{name:"/m/029bxz",id:79,displayName:"oven"},80:{name:"/m/01k6s3",id:80,displayName:"toaster"},81:{name:"/m/0130jx",id:81,displayName:"sink"},82:{name:"/m/040b_t",id:82,displayName:"refrigerator"},84:{name:"/m/0bt_c3",id:84,displayName:"book"},85:{name:"/m/01x3z",id:85,displayName:"clock"},86:{name:"/m/02s195",id:86,displayName:"vase"},87:{name:"/m/01lsmm",id:87,displayName:"scissors"},88:{name:"/m/0kmg4",id:88,displayName:"teddy bear"},89:{name:"/m/03wvsk",id:89,displayName:"hair drier"},90:{name:"/m/012xff",id:90,displayName:"toothbrush"}},d="https://storage.googleapis.com/tfjs-models/savedmodel/";var s=function(){function e(e,a){this.modelPath=a||""+d+this.getPrefix(e)+"/model.json"}return e.prototype.getPrefix=function(e){return"lite_mobilenet_v2"===e?"ssd"+e:"ssd_"+e},e.prototype.load=function(){return n(this,void 0,void 0,function(){var e,n,m;return t(this,function(t){switch(t.label){case 0:return e=this,[4,a.loadGraphModel(this.modelPath)];case 1:return e.model=t.sent(),n=i.zeros([1,300,300,3],"int32"),[4,this.model.executeAsync(n)];case 2:return m=t.sent(),[4,Promise.all(m.map(function(e){return e.data()}))];case 3:return t.sent(),m.map(function(e){return e.dispose()}),n.dispose(),[2]}})})},e.prototype.infer=function(e,a){return n(this,void 0,void 0,function(){var n,m,d,s,r,o,l,p,c,y,u,f;return t(this,function(t){switch(t.label){case 0:return n=i.tidy(function(){return e instanceof i.Tensor||(e=i.browser.fromPixels(e)),e.expandDims(0)}),m=n.shape[1],d=n.shape[2],[4,this.model.executeAsync(n)];case 1:return s=t.sent(),r=s[0].dataSync(),o=s[1].dataSync(),n.dispose(),i.dispose(s),l=function(e,a){var i="function"==typeof Symbol&&e[Symbol.iterator];if(!i)return e;var n,t,m=i.call(e),d=[];try{for(;(void 0===a||a-- >0)&&!(n=m.next()).done;)d.push(n.value)}catch(e){t={error:e}}finally{try{n&&!n.done&&(i=m.return)&&i.call(m)}finally{if(t)throw t.error}}return d}(this.calculateMaxScores(r,s[0].shape[1],s[0].shape[2]),2),p=l[0],c=l[1],y=i.getBackend(),i.setBackend("cpu"),u=i.tidy(function(){var e=i.tensor2d(o,[s[1].shape[1],s[1].shape[3]]);return i.image.nonMaxSuppression(e,p,a,.5,.5)}),f=u.dataSync(),u.dispose(),i.setBackend(y),[2,this.buildDetectedObjects(d,m,o,p,f,c)]}})})},e.prototype.buildDetectedObjects=function(e,a,i,n,t,d){for(var s=t.length,r=[],o=0;o<s;o++){for(var l=[],p=0;p<4;p++)l[p]=i[4*t[o]+p];var c=l[0]*a,y=l[1]*e,u=l[2]*a,f=l[3]*e;l[0]=y,l[1]=c,l[2]=f-y,l[3]=u-c,r.push({bbox:l,class:m[d[t[o]]+1].displayName,score:n[t[o]]})}return r},e.prototype.calculateMaxScores=function(e,a,i){for(var n=[],t=[],m=0;m<a;m++){for(var d=Number.MIN_VALUE,s=-1,r=0;r<i;r++)e[m*i+r]>d&&(d=e[m*i+r],s=r);n[m]=d,t[m]=s}return[n,t]},e.prototype.detect=function(e,a){return void 0===a&&(a=20),n(this,void 0,void 0,function(){return t(this,function(i){return[2,this.infer(e,a)]})})},e.prototype.dispose=function(){null!=this.model&&this.model.dispose()},e}();e.load=function(e){return void 0===e&&(e={}),n(this,void 0,void 0,function(){var a,n,m;return t(this,function(t){switch(t.label){case 0:if(null==i)throw new Error("Cannot find TensorFlow.js. If you are using a <script> tag, please also include @tensorflow/tfjs on the page before using this model.");if(a=e.base||"lite_mobilenet_v2",n=e.modelUrl,-1===["mobilenet_v1","mobilenet_v2","lite_mobilenet_v2"].indexOf(a))throw new Error("ObjectDetection constructed with invalid base model "+a+". Valid names are 'mobilenet_v1', 'mobilenet_v2' and 'lite_mobilenet_v2'.");return[4,(m=new s(a,n)).load()];case 1:return t.sent(),[2,m]}})})},e.ObjectDetection=s,e.version="2.0.3",Object.defineProperty(e,"__esModule",{value:!0})}); | ||
* @license | ||
* Copyright 2020 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
!function(e,a){"object"==typeof exports&&"undefined"!=typeof module?a(exports,require("@tensorflow/tfjs-converter"),require("@tensorflow/tfjs-core")):"function"==typeof define&&define.amd?define(["exports","@tensorflow/tfjs-converter","@tensorflow/tfjs-core"],a):a((e=e||self).cocoSsd=e.cocoSsd||{},e.tfconv,e.tf)}(this,(function(e,a,i){"use strict";function n(e,a,i,n){return new(i||(i=Promise))((function(m,t){function d(e){try{o(n.next(e))}catch(e){t(e)}}function s(e){try{o(n.throw(e))}catch(e){t(e)}}function o(e){e.done?m(e.value):new i((function(a){a(e.value)})).then(d,s)}o((n=n.apply(e,a||[])).next())}))}function m(e,a){var i,n,m,t,d={label:0,sent:function(){if(1&m[0])throw m[1];return m[1]},trys:[],ops:[]};return t={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(t[Symbol.iterator]=function(){return this}),t;function s(t){return function(s){return function(t){if(i)throw new TypeError("Generator is already executing.");for(;d;)try{if(i=1,n&&(m=2&t[0]?n.return:t[0]?n.throw||((m=n.return)&&m.call(n),0):n.next)&&!(m=m.call(n,t[1])).done)return m;switch(n=0,m&&(t=[2&t[0],m.value]),t[0]){case 0:case 1:m=t;break;case 4:return d.label++,{value:t[1],done:!1};case 5:d.label++,n=t[1],t=[0];continue;case 7:t=d.ops.pop(),d.trys.pop();continue;default:if(!(m=d.trys,(m=m.length>0&&m[m.length-1])||6!==t[0]&&2!==t[0])){d=0;continue}if(3===t[0]&&(!m||t[1]>m[0]&&t[1]<m[3])){d.label=t[1];break}if(6===t[0]&&d.label<m[1]){d.label=m[1],m=t;break}if(m&&d.label<m[2]){d.label=m[2],d.ops.push(t);break}m[2]&&d.ops.pop(),d.trys.pop();continue}t=a.call(e,d)}catch(e){t=[6,e],n=0}finally{i=m=0}if(5&t[0])throw t[1];return{value:t[0]?t[1]:void 0,done:!0}}([t,s])}}}var t={1:{name:"/m/01g317",id:1,displayName:"person"},2:{name:"/m/0199g",id:2,displayName:"bicycle"},3:{name:"/m/0k4j",id:3,displayName:"car"},4:{name:"/m/04_sv",id:4,displayName:"motorcycle"},5:{name:"/m/05czz6l",id:5,displayName:"airplane"},6:{name:"/m/01bjv",id:6,displayName:"bus"},7:{name:"/m/07jdr",id:7,displayName:"train"},8:{name:"/m/07r04",id:8,displayName:"truck"},9:{name:"/m/019jd",id:9,displayName:"boat"},10:{name:"/m/015qff",id:10,displayName:"traffic light"},11:{name:"/m/01pns0",id:11,displayName:"fire hydrant"},13:{name:"/m/02pv19",id:13,displayName:"stop sign"},14:{name:"/m/015qbp",id:14,displayName:"parking meter"},15:{name:"/m/0cvnqh",id:15,displayName:"bench"},16:{name:"/m/015p6",id:16,displayName:"bird"},17:{name:"/m/01yrx",id:17,displayName:"cat"},18:{name:"/m/0bt9lr",id:18,displayName:"dog"},19:{name:"/m/03k3r",id:19,displayName:"horse"},20:{name:"/m/07bgp",id:20,displayName:"sheep"},21:{name:"/m/01xq0k1",id:21,displayName:"cow"},22:{name:"/m/0bwd_0j",id:22,displayName:"elephant"},23:{name:"/m/01dws",id:23,displayName:"bear"},24:{name:"/m/0898b",id:24,displayName:"zebra"},25:{name:"/m/03bk1",id:25,displayName:"giraffe"},27:{name:"/m/01940j",id:27,displayName:"backpack"},28:{name:"/m/0hnnb",id:28,displayName:"umbrella"},31:{name:"/m/080hkjn",id:31,displayName:"handbag"},32:{name:"/m/01rkbr",id:32,displayName:"tie"},33:{name:"/m/01s55n",id:33,displayName:"suitcase"},34:{name:"/m/02wmf",id:34,displayName:"frisbee"},35:{name:"/m/071p9",id:35,displayName:"skis"},36:{name:"/m/06__v",id:36,displayName:"snowboard"},37:{name:"/m/018xm",id:37,displayName:"sports ball"},38:{name:"/m/02zt3",id:38,displayName:"kite"},39:{name:"/m/03g8mr",id:39,displayName:"baseball bat"},40:{name:"/m/03grzl",id:40,displayName:"baseball glove"},41:{name:"/m/06_fw",id:41,displayName:"skateboard"},42:{name:"/m/019w40",id:42,displayName:"surfboard"},43:{name:"/m/0dv9c",id:43,displayName:"tennis racket"},44:{name:"/m/04dr76w",id:44,displayName:"bottle"},46:{name:"/m/09tvcd",id:46,displayName:"wine glass"},47:{name:"/m/08gqpm",id:47,displayName:"cup"},48:{name:"/m/0dt3t",id:48,displayName:"fork"},49:{name:"/m/04ctx",id:49,displayName:"knife"},50:{name:"/m/0cmx8",id:50,displayName:"spoon"},51:{name:"/m/04kkgm",id:51,displayName:"bowl"},52:{name:"/m/09qck",id:52,displayName:"banana"},53:{name:"/m/014j1m",id:53,displayName:"apple"},54:{name:"/m/0l515",id:54,displayName:"sandwich"},55:{name:"/m/0cyhj_",id:55,displayName:"orange"},56:{name:"/m/0hkxq",id:56,displayName:"broccoli"},57:{name:"/m/0fj52s",id:57,displayName:"carrot"},58:{name:"/m/01b9xk",id:58,displayName:"hot dog"},59:{name:"/m/0663v",id:59,displayName:"pizza"},60:{name:"/m/0jy4k",id:60,displayName:"donut"},61:{name:"/m/0fszt",id:61,displayName:"cake"},62:{name:"/m/01mzpv",id:62,displayName:"chair"},63:{name:"/m/02crq1",id:63,displayName:"couch"},64:{name:"/m/03fp41",id:64,displayName:"potted plant"},65:{name:"/m/03ssj5",id:65,displayName:"bed"},67:{name:"/m/04bcr3",id:67,displayName:"dining table"},70:{name:"/m/09g1w",id:70,displayName:"toilet"},72:{name:"/m/07c52",id:72,displayName:"tv"},73:{name:"/m/01c648",id:73,displayName:"laptop"},74:{name:"/m/020lf",id:74,displayName:"mouse"},75:{name:"/m/0qjjc",id:75,displayName:"remote"},76:{name:"/m/01m2v",id:76,displayName:"keyboard"},77:{name:"/m/050k8",id:77,displayName:"cell phone"},78:{name:"/m/0fx9l",id:78,displayName:"microwave"},79:{name:"/m/029bxz",id:79,displayName:"oven"},80:{name:"/m/01k6s3",id:80,displayName:"toaster"},81:{name:"/m/0130jx",id:81,displayName:"sink"},82:{name:"/m/040b_t",id:82,displayName:"refrigerator"},84:{name:"/m/0bt_c3",id:84,displayName:"book"},85:{name:"/m/01x3z",id:85,displayName:"clock"},86:{name:"/m/02s195",id:86,displayName:"vase"},87:{name:"/m/01lsmm",id:87,displayName:"scissors"},88:{name:"/m/0kmg4",id:88,displayName:"teddy bear"},89:{name:"/m/03wvsk",id:89,displayName:"hair drier"},90:{name:"/m/012xff",id:90,displayName:"toothbrush"}};var d=function(){function e(e,a){this.modelPath=a||"https://storage.googleapis.com/tfjs-models/savedmodel/"+this.getPrefix(e)+"/model.json"}return e.prototype.getPrefix=function(e){return"lite_mobilenet_v2"===e?"ssd"+e:"ssd_"+e},e.prototype.load=function(){return n(this,void 0,void 0,(function(){var e,n,t;return m(this,(function(m){switch(m.label){case 0:return e=this,[4,a.loadGraphModel(this.modelPath)];case 1:return e.model=m.sent(),n=i.zeros([1,300,300,3],"int32"),[4,this.model.executeAsync(n)];case 2:return t=m.sent(),[4,Promise.all(t.map((function(e){return e.data()})))];case 3:return m.sent(),t.map((function(e){return e.dispose()})),n.dispose(),[2]}}))}))},e.prototype.infer=function(e,a,t){return n(this,void 0,void 0,(function(){var n,d,s,o,r,l,p,c,y,u,f,b;return m(this,(function(m){switch(m.label){case 0:return n=i.tidy((function(){return e instanceof i.Tensor||(e=i.browser.fromPixels(e)),e.expandDims(0)})),d=n.shape[1],s=n.shape[2],[4,this.model.executeAsync(n)];case 1:return o=m.sent(),r=o[0].dataSync(),l=o[1].dataSync(),n.dispose(),i.dispose(o),p=this.calculateMaxScores(r,o[0].shape[1],o[0].shape[2]),c=p[0],y=p[1],u=i.getBackend(),i.setBackend("cpu"),f=i.tidy((function(){var e=i.tensor2d(l,[o[1].shape[1],o[1].shape[3]]);return i.image.nonMaxSuppression(e,c,a,t,t)})),b=f.dataSync(),f.dispose(),i.setBackend(u),[2,this.buildDetectedObjects(s,d,l,c,b,y)]}}))}))},e.prototype.buildDetectedObjects=function(e,a,i,n,m,d){for(var s=m.length,o=[],r=0;r<s;r++){for(var l=[],p=0;p<4;p++)l[p]=i[4*m[r]+p];var c=l[0]*a,y=l[1]*e,u=l[2]*a,f=l[3]*e;l[0]=y,l[1]=c,l[2]=f-y,l[3]=u-c,o.push({bbox:l,class:t[d[m[r]]+1].displayName,score:n[m[r]]})}return o},e.prototype.calculateMaxScores=function(e,a,i){for(var n=[],m=[],t=0;t<a;t++){for(var d=Number.MIN_VALUE,s=-1,o=0;o<i;o++)e[t*i+o]>d&&(d=e[t*i+o],s=o);n[t]=d,m[t]=s}return[n,m]},e.prototype.detect=function(e,a,i){return void 0===a&&(a=20),void 0===i&&(i=.5),n(this,void 0,void 0,(function(){return m(this,(function(n){return[2,this.infer(e,a,i)]}))}))},e.prototype.dispose=function(){null!=this.model&&this.model.dispose()},e}();e.ObjectDetection=d,e.load=function(e){return void 0===e&&(e={}),n(this,void 0,void 0,(function(){var a,n,t;return m(this,(function(m){switch(m.label){case 0:if(null==i)throw new Error("Cannot find TensorFlow.js. If you are using a <script> tag, please also include @tensorflow/tfjs on the page before using this model.");if(a=e.base||"lite_mobilenet_v2",n=e.modelUrl,-1===["mobilenet_v1","mobilenet_v2","lite_mobilenet_v2"].indexOf(a))throw new Error("ObjectDetection constructed with invalid base model "+a+". Valid names are 'mobilenet_v1', 'mobilenet_v2' and 'lite_mobilenet_v2'.");return[4,(t=new d(a,n)).load()];case 1:return m.sent(),[2,t]}}))}))},e.version="2.0.4",Object.defineProperty(e,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=coco-ssd.min.js.map |
@@ -0,1 +1,17 @@ | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
import * as tf from '@tensorflow/tfjs-core'; | ||
@@ -9,2 +25,13 @@ export { version } from './version'; | ||
} | ||
/** | ||
* Coco-ssd model loading is configurable using the following config dictionary. | ||
* | ||
* `base`: ObjectDetectionBaseModel. It determines wich PoseNet architecture | ||
* to load. The supported architectures are: 'mobilenet_v1', 'mobilenet_v2' and | ||
* 'lite_mobilenet_v2'. It is default to 'lite_mobilenet_v2'. | ||
* | ||
* `modelUrl`: An optional string that specifies custom url of the model. This | ||
* is useful for area/countries that don't have access to the model hosted on | ||
* GCP. | ||
*/ | ||
export interface ModelConfig { | ||
@@ -21,7 +48,34 @@ base?: ObjectDetectionBaseModel; | ||
load(): Promise<void>; | ||
/** | ||
* Infers through the model. | ||
* | ||
* @param img The image to classify. Can be a tensor or a DOM element image, | ||
* video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
private infer; | ||
private buildDetectedObjects; | ||
private calculateMaxScores; | ||
detect(img: tf.Tensor3D | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, maxNumBoxes?: number): Promise<DetectedObject[]>; | ||
/** | ||
* Detect objects for an image returning a list of bounding boxes with | ||
* assocated class and score. | ||
* | ||
* @param img The image to detect objects from. Can be a tensor or a DOM | ||
* element image, video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
detect(img: tf.Tensor3D | ImageData | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, maxNumBoxes?: number, minScore?: number): Promise<DetectedObject[]>; | ||
/** | ||
* Dispose the tensors allocated by the model. You should call this when you | ||
* are done with the model. | ||
*/ | ||
dispose(): void; | ||
} |
@@ -1,169 +0,114 @@ | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
/** | ||
* @license | ||
* Copyright 2019 Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/ | ||
import * as tfconv from '@tensorflow/tfjs-converter'; | ||
import * as tf from '@tensorflow/tfjs-core'; | ||
import { CLASSES } from './classes'; | ||
const BASE_PATH = 'https://storage.googleapis.com/tfjs-models/savedmodel/'; | ||
export { version } from './version'; | ||
export async function load(config = {}) { | ||
if (tf == null) { | ||
throw new Error(`Cannot find TensorFlow.js. If you are using a <script> tag, please ` + | ||
`also include @tensorflow/tfjs on the page before using this model.`); | ||
} | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
const base = config.base || 'lite_mobilenet_v2'; | ||
const modelUrl = config.modelUrl; | ||
if (['mobilenet_v1', 'mobilenet_v2', 'lite_mobilenet_v2'].indexOf(base) === | ||
-1) { | ||
throw new Error(`ObjectDetection constructed with invalid base model ` + | ||
`${base}. Valid names are 'mobilenet_v1',` + | ||
` 'mobilenet_v2' and 'lite_mobilenet_v2'.`); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tfconv = require("@tensorflow/tfjs-converter"); | ||
var tf = require("@tensorflow/tfjs-core"); | ||
var classes_1 = require("./classes"); | ||
var BASE_PATH = 'https://storage.googleapis.com/tfjs-models/savedmodel/'; | ||
var version_1 = require("./version"); | ||
exports.version = version_1.version; | ||
function load(config) { | ||
if (config === void 0) { config = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var base, modelUrl, objectDetection; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (tf == null) { | ||
throw new Error("Cannot find TensorFlow.js. If you are using a <script> tag, please " + | ||
"also include @tensorflow/tfjs on the page before using this model."); | ||
} | ||
base = config.base || 'lite_mobilenet_v2'; | ||
modelUrl = config.modelUrl; | ||
if (['mobilenet_v1', 'mobilenet_v2', 'lite_mobilenet_v2'].indexOf(base) === | ||
-1) { | ||
throw new Error("ObjectDetection constructed with invalid base model " + | ||
(base + ". Valid names are 'mobilenet_v1',") + | ||
" 'mobilenet_v2' and 'lite_mobilenet_v2'."); | ||
} | ||
objectDetection = new ObjectDetection(base, modelUrl); | ||
return [4, objectDetection.load()]; | ||
case 1: | ||
_a.sent(); | ||
return [2, objectDetection]; | ||
} | ||
}); | ||
}); | ||
const objectDetection = new ObjectDetection(base, modelUrl); | ||
await objectDetection.load(); | ||
return objectDetection; | ||
} | ||
exports.load = load; | ||
var ObjectDetection = (function () { | ||
function ObjectDetection(base, modelUrl) { | ||
export class ObjectDetection { | ||
constructor(base, modelUrl) { | ||
this.modelPath = | ||
modelUrl || "" + BASE_PATH + this.getPrefix(base) + "/model.json"; | ||
modelUrl || `${BASE_PATH}${this.getPrefix(base)}/model.json`; | ||
} | ||
ObjectDetection.prototype.getPrefix = function (base) { | ||
return base === 'lite_mobilenet_v2' ? "ssd" + base : "ssd_" + base; | ||
}; | ||
ObjectDetection.prototype.load = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, zeroTensor, result; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a = this; | ||
return [4, tfconv.loadGraphModel(this.modelPath)]; | ||
case 1: | ||
_a.model = _b.sent(); | ||
zeroTensor = tf.zeros([1, 300, 300, 3], 'int32'); | ||
return [4, this.model.executeAsync(zeroTensor)]; | ||
case 2: | ||
result = _b.sent(); | ||
return [4, Promise.all(result.map(function (t) { return t.data(); }))]; | ||
case 3: | ||
_b.sent(); | ||
result.map(function (t) { return t.dispose(); }); | ||
zeroTensor.dispose(); | ||
return [2]; | ||
} | ||
}); | ||
getPrefix(base) { | ||
return base === 'lite_mobilenet_v2' ? `ssd${base}` : `ssd_${base}`; | ||
} | ||
async load() { | ||
this.model = await tfconv.loadGraphModel(this.modelPath); | ||
const zeroTensor = tf.zeros([1, 300, 300, 3], 'int32'); | ||
// Warmup the model. | ||
const result = await this.model.executeAsync(zeroTensor); | ||
await Promise.all(result.map(t => t.data())); | ||
result.map(t => t.dispose()); | ||
zeroTensor.dispose(); | ||
} | ||
/** | ||
* Infers through the model. | ||
* | ||
* @param img The image to classify. Can be a tensor or a DOM element image, | ||
* video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
async infer(img, maxNumBoxes, minScore) { | ||
const batched = tf.tidy(() => { | ||
if (!(img instanceof tf.Tensor)) { | ||
img = tf.browser.fromPixels(img); | ||
} | ||
// Reshape to a single-element batch so we can pass it to executeAsync. | ||
return img.expandDims(0); | ||
}); | ||
}; | ||
ObjectDetection.prototype.infer = function (img, maxNumBoxes) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var batched, height, width, result, scores, boxes, _a, maxScores, classes, prevBackend, indexTensor, indexes; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
batched = tf.tidy(function () { | ||
if (!(img instanceof tf.Tensor)) { | ||
img = tf.browser.fromPixels(img); | ||
} | ||
return img.expandDims(0); | ||
}); | ||
height = batched.shape[1]; | ||
width = batched.shape[2]; | ||
return [4, this.model.executeAsync(batched)]; | ||
case 1: | ||
result = _b.sent(); | ||
scores = result[0].dataSync(); | ||
boxes = result[1].dataSync(); | ||
batched.dispose(); | ||
tf.dispose(result); | ||
_a = __read(this.calculateMaxScores(scores, result[0].shape[1], result[0].shape[2]), 2), maxScores = _a[0], classes = _a[1]; | ||
prevBackend = tf.getBackend(); | ||
tf.setBackend('cpu'); | ||
indexTensor = tf.tidy(function () { | ||
var boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]); | ||
return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, 0.5, 0.5); | ||
}); | ||
indexes = indexTensor.dataSync(); | ||
indexTensor.dispose(); | ||
tf.setBackend(prevBackend); | ||
return [2, this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes)]; | ||
} | ||
}); | ||
const height = batched.shape[1]; | ||
const width = batched.shape[2]; | ||
// model returns two tensors: | ||
// 1. box classification score with shape of [1, 1917, 90] | ||
// 2. box location with shape of [1, 1917, 1, 4] | ||
// where 1917 is the number of box detectors, 90 is the number of classes. | ||
// and 4 is the four coordinates of the box. | ||
const result = await this.model.executeAsync(batched); | ||
const scores = result[0].dataSync(); | ||
const boxes = result[1].dataSync(); | ||
// clean the webgl tensors | ||
batched.dispose(); | ||
tf.dispose(result); | ||
const [maxScores, classes] = this.calculateMaxScores(scores, result[0].shape[1], result[0].shape[2]); | ||
const prevBackend = tf.getBackend(); | ||
// run post process in cpu | ||
tf.setBackend('cpu'); | ||
const indexTensor = tf.tidy(() => { | ||
const boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]); | ||
return tf.image.nonMaxSuppression(boxes2, maxScores, maxNumBoxes, minScore, minScore); | ||
}); | ||
}; | ||
ObjectDetection.prototype.buildDetectedObjects = function (width, height, boxes, scores, indexes, classes) { | ||
var count = indexes.length; | ||
var objects = []; | ||
for (var i = 0; i < count; i++) { | ||
var bbox = []; | ||
for (var j = 0; j < 4; j++) { | ||
const indexes = indexTensor.dataSync(); | ||
indexTensor.dispose(); | ||
// restore previous backend | ||
tf.setBackend(prevBackend); | ||
return this.buildDetectedObjects(width, height, boxes, maxScores, indexes, classes); | ||
} | ||
buildDetectedObjects(width, height, boxes, scores, indexes, classes) { | ||
const count = indexes.length; | ||
const objects = []; | ||
for (let i = 0; i < count; i++) { | ||
const bbox = []; | ||
for (let j = 0; j < 4; j++) { | ||
bbox[j] = boxes[indexes[i] * 4 + j]; | ||
} | ||
var minY = bbox[0] * height; | ||
var minX = bbox[1] * width; | ||
var maxY = bbox[2] * height; | ||
var maxX = bbox[3] * width; | ||
const minY = bbox[0] * height; | ||
const minX = bbox[1] * width; | ||
const maxY = bbox[2] * height; | ||
const maxX = bbox[3] * width; | ||
bbox[0] = minX; | ||
@@ -175,3 +120,3 @@ bbox[1] = minY; | ||
bbox: bbox, | ||
class: classes_1.CLASSES[classes[indexes[i]] + 1].displayName, | ||
class: CLASSES[classes[indexes[i]] + 1].displayName, | ||
score: scores[indexes[i]] | ||
@@ -181,10 +126,10 @@ }); | ||
return objects; | ||
}; | ||
ObjectDetection.prototype.calculateMaxScores = function (scores, numBoxes, numClasses) { | ||
var maxes = []; | ||
var classes = []; | ||
for (var i = 0; i < numBoxes; i++) { | ||
var max = Number.MIN_VALUE; | ||
var index = -1; | ||
for (var j = 0; j < numClasses; j++) { | ||
} | ||
calculateMaxScores(scores, numBoxes, numClasses) { | ||
const maxes = []; | ||
const classes = []; | ||
for (let i = 0; i < numBoxes; i++) { | ||
let max = Number.MIN_VALUE; | ||
let index = -1; | ||
for (let j = 0; j < numClasses; j++) { | ||
if (scores[i * numClasses + j] > max) { | ||
@@ -199,19 +144,28 @@ max = scores[i * numClasses + j]; | ||
return [maxes, classes]; | ||
}; | ||
ObjectDetection.prototype.detect = function (img, maxNumBoxes) { | ||
if (maxNumBoxes === void 0) { maxNumBoxes = 20; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2, this.infer(img, maxNumBoxes)]; | ||
}); | ||
}); | ||
}; | ||
ObjectDetection.prototype.dispose = function () { | ||
} | ||
/** | ||
* Detect objects for an image returning a list of bounding boxes with | ||
* assocated class and score. | ||
* | ||
* @param img The image to detect objects from. Can be a tensor or a DOM | ||
* element image, video, or canvas. | ||
* @param maxNumBoxes The maximum number of bounding boxes of detected | ||
* objects. There can be multiple objects of the same class, but at different | ||
* locations. Defaults to 20. | ||
* @param minScore The minimum score of the returned bounding boxes | ||
* of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
*/ | ||
async detect(img, maxNumBoxes = 20, minScore = 0.5) { | ||
return this.infer(img, maxNumBoxes, minScore); | ||
} | ||
/** | ||
* Dispose the tensors allocated by the model. You should call this when you | ||
* are done with the model. | ||
*/ | ||
dispose() { | ||
if (this.model != null) { | ||
this.model.dispose(); | ||
} | ||
}; | ||
return ObjectDetection; | ||
}()); | ||
exports.ObjectDetection = ObjectDetection; | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,3 @@ | ||
declare const version = "2.0.3"; | ||
/** @license See the LICENSE file. */ | ||
declare const version = "2.0.4"; | ||
export { version }; |
@@ -1,5 +0,5 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var version = '2.0.3'; | ||
exports.version = version; | ||
/** @license See the LICENSE file. */ | ||
// This code is auto-generated, do not modify this file! | ||
const version = '2.0.4'; | ||
export { version }; | ||
//# sourceMappingURL=version.js.map |
{ | ||
"name": "@tensorflow-models/coco-ssd", | ||
"version": "2.0.3", | ||
"version": "2.0.4", | ||
"description": "Object detection model (coco-ssd) in TensorFlow.js", | ||
@@ -16,20 +16,22 @@ "main": "dist/index.js", | ||
"peerDependencies": { | ||
"@tensorflow/tfjs-converter": "^1.2.5", | ||
"@tensorflow/tfjs-core": "^1.2.6" | ||
"@tensorflow/tfjs-converter": "^2.0.1", | ||
"@tensorflow/tfjs-core": "^2.0.1" | ||
}, | ||
"devDependencies": { | ||
"@tensorflow/tfjs-converter": "^1.2.5", | ||
"@tensorflow/tfjs-core": "^1.2.6", | ||
"@rollup/plugin-commonjs": "^11.0.2", | ||
"@rollup/plugin-node-resolve": "^7.1.1", | ||
"@rollup/plugin-typescript": "^3.0.0", | ||
"@tensorflow/tfjs-backend-cpu": "^2.0.1", | ||
"@tensorflow/tfjs-converter": "^2.0.1", | ||
"@tensorflow/tfjs-core": "^2.0.1", | ||
"@types/jasmine": "~2.8.8", | ||
"babel-core": "~6.26.0", | ||
"babel-plugin-transform-runtime": "~6.23.0", | ||
"jasmine": "~3.3.1", | ||
"jasmine-core": "~3.3.0", | ||
"rollup": "~0.60.7", | ||
"rollup-plugin-node-resolve": "~3.3.0", | ||
"rollup-plugin-typescript2": "~0.15.0", | ||
"rollup-plugin-uglify": "~3.0.0", | ||
"ts-node": "~5.0.0", | ||
"jasmine-core": "~3.5.0", | ||
"rollup": "~2.3.2", | ||
"rollup-plugin-terser": "~5.3.0", | ||
"rollup-plugin-visualizer": "~3.3.2", | ||
"ts-node": "~8.8.2", | ||
"tslint": "~5.18.0", | ||
"typescript": "3.3.3333", | ||
"typescript": "~3.5.3", | ||
"yalc": "~1.0.0-pre.21" | ||
@@ -41,6 +43,6 @@ }, | ||
"publish-local": "yarn build && rollup -c && yalc push", | ||
"build-npm": "yarn build && rollup -c", | ||
"test": "yarn build && ts-node run_tests.ts" | ||
"build-npm": "yarn build && rollup -c --visualize --npm", | ||
"test": "yarn build && ts-node --skip-ignore -P tsconfig.test.json run_tests.ts" | ||
}, | ||
"license": "Apache-2.0" | ||
} |
@@ -8,3 +8,3 @@ # Object Detection (coco-ssd) | ||
This model detects objects defined in the COCO dataset, which is a large-scale object detection, segmentation, and captioning dataset. You can find more information [here](http://cocodataset.org/#home). The model is capable of detecting [90 classes of objects](./src/classes.ts). (SSD stands for Single Shot MultiBox Detection). | ||
This model detects objects defined in the COCO dataset, which is a large-scale object detection, segmentation, and captioning dataset. You can find more information [here](http://cocodataset.org/#home). The model is capable of detecting [80 classes of objects](./src/classes.ts). (SSD stands for Single Shot MultiBox Detection). | ||
@@ -102,3 +102,3 @@ This TensorFlow.js model does not require you to know about machine learning. | ||
img: tf.Tensor3D | ImageData | HTMLImageElement | | ||
HTMLCanvasElement | HTMLVideoElement, maxDetectionSize: number | ||
HTMLCanvasElement | HTMLVideoElement, maxNumBoxes: number, minScore: number | ||
) | ||
@@ -111,2 +111,3 @@ ``` | ||
- **maxNumBoxes:** The maximum number of bounding boxes of detected objects. There can be multiple objects of the same class, but at different locations. Defaults to 20. | ||
- **minScore:** The minimum score of the returned bounding boxes of detected objects. Value between 0 and 1. Defaults to 0.5. | ||
@@ -113,0 +114,0 @@ Returns an array of classes and probabilities that looks like: |
@@ -18,80 +18,151 @@ /** | ||
import node from 'rollup-plugin-node-resolve'; | ||
import typescript from 'rollup-plugin-typescript2'; | ||
import uglify from 'rollup-plugin-uglify'; | ||
import commonjs from '@rollup/plugin-commonjs'; | ||
import resolve from '@rollup/plugin-node-resolve'; | ||
import typescript from '@rollup/plugin-typescript'; | ||
import {terser} from 'rollup-plugin-terser'; | ||
import visualizer from 'rollup-plugin-visualizer'; | ||
const PREAMBLE = `/** | ||
* @license | ||
* Copyright ${(new Date).getFullYear()} Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/`; | ||
* @license | ||
* Copyright ${(new Date).getFullYear()} Google LLC. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* ============================================================================= | ||
*/`; | ||
function minify() { | ||
return uglify({ | ||
output: { | ||
preamble: PREAMBLE, | ||
} | ||
}); | ||
} | ||
function config({ | ||
plugins = [], | ||
output = {}, | ||
external = [], | ||
visualize = false, | ||
tsCompilerOptions = {} | ||
}) { | ||
if (visualize) { | ||
const filename = output.file + '.html'; | ||
plugins.push(visualizer({sourcemap: true, filename})); | ||
console.log(`Will output a bundle visualization in ${filename}`); | ||
} | ||
function config({plugins = [], output = {}}) { | ||
const defaultTsOptions = { | ||
include: ['src/**/*.ts'], | ||
module: 'ES2015', | ||
}; | ||
const tsoptions = Object.assign({}, defaultTsOptions, tsCompilerOptions); | ||
return { | ||
input: 'src/index.ts', | ||
plugins: [ | ||
typescript({ | ||
tsconfigOverride: { | ||
compilerOptions: {module: 'ES2015'}, | ||
typescript(tsoptions), resolve(), | ||
// Polyfill require() from dependencies. | ||
commonjs({ | ||
ignore: ['crypto', 'node-fetch', 'util'], | ||
include: 'node_modules/**', | ||
namedExports: { | ||
'./node_modules/seedrandom/index.js': ['alea'], | ||
}, | ||
}), | ||
node(), ...plugins | ||
...plugins | ||
], | ||
output: { | ||
banner: PREAMBLE, | ||
globals: { | ||
'@tensorflow/tfjs-core': 'tf', | ||
'@tensorflow/tfjs-converter': 'tf', | ||
}, | ||
...output | ||
sourcemap: true, | ||
...output, | ||
}, | ||
external: [ | ||
'@tensorflow/tfjs-core', | ||
'@tensorflow/tfjs-converter', | ||
] | ||
external: | ||
['@tensorflow/tfjs-core', '@tensorflow/tfjs-converter', , ...external], | ||
onwarn: warning => { | ||
let {code} = warning; | ||
if (code === 'CIRCULAR_DEPENDENCY' || code === 'CIRCULAR' || | ||
code === 'THIS_IS_UNDEFINED') { | ||
return; | ||
} | ||
console.warn('WARNING: ', warning.toString()); | ||
} | ||
}; | ||
} | ||
export default [ | ||
config({ | ||
module.exports = cmdOptions => { | ||
const bundles = []; | ||
const terserPlugin = terser({output: {preamble: PREAMBLE, comments: false}}); | ||
const name = 'cocoSsd'; | ||
const extend = true; | ||
const browserFormat = 'umd'; | ||
const fileName = 'coco-ssd'; | ||
// Node | ||
bundles.push(config({ | ||
output: { | ||
format: 'umd', | ||
name: 'cocoSsd', | ||
file: 'dist/coco-ssd.js', | ||
} | ||
}), | ||
config({ | ||
plugins: [minify()], | ||
output: { | ||
format: 'umd', | ||
name: 'cocoSsd', | ||
file: 'dist/coco-ssd.min.js', | ||
} | ||
}), | ||
config({ | ||
plugins: [minify()], | ||
output: { | ||
format: 'es', | ||
file: 'dist/coco-ssd.esm.js', | ||
} | ||
}) | ||
]; | ||
format: 'cjs', | ||
name, | ||
extend, | ||
file: `dist/${fileName}.node.js`, | ||
freeze: false | ||
}, | ||
tsCompilerOptions: {target: 'es5'} | ||
})); | ||
if (cmdOptions.ci || cmdOptions.npm) { | ||
// Browser default minified (ES5) | ||
bundles.push(config({ | ||
plugins: [terserPlugin], | ||
output: { | ||
format: browserFormat, | ||
name, | ||
extend, | ||
file: `dist/${fileName}.min.js`, | ||
freeze: false | ||
}, | ||
tsCompilerOptions: {target: 'es5'}, | ||
visualize: cmdOptions.visualize | ||
})); | ||
} | ||
if (cmdOptions.npm) { | ||
// Browser default unminified (ES5) | ||
bundles.push(config({ | ||
output: { | ||
format: browserFormat, | ||
name, | ||
extend, | ||
file: `dist/${fileName}.js`, | ||
freeze: false | ||
}, | ||
tsCompilerOptions: {target: 'es5'} | ||
})); | ||
// Browser ES2017 | ||
bundles.push(config({ | ||
output: { | ||
format: browserFormat, | ||
name, | ||
extend, | ||
file: `dist/${fileName}.es2017.js` | ||
}, | ||
tsCompilerOptions: {target: 'es2017'} | ||
})); | ||
// Browser ES2017 minified | ||
bundles.push(config({ | ||
plugins: [terserPlugin], | ||
output: { | ||
format: browserFormat, | ||
name, | ||
extend, | ||
file: `dist/${fileName}.es2017.min.js` | ||
}, | ||
tsCompilerOptions: {target: 'es2017'} | ||
})); | ||
} | ||
return bundles; | ||
}; |
@@ -19,5 +19,25 @@ | ||
// Use the CPU backend for running tests. | ||
import '@tensorflow/tfjs-backend-cpu'; | ||
// tslint:disable-next-line:no-imports-from-dist | ||
import * as jasmine_util from '@tensorflow/tfjs-core/dist/jasmine_util'; | ||
import {runTests} from '../test_util'; | ||
runTests(jasmine_util); | ||
// tslint:disable-next-line:no-require-imports | ||
const jasmineCtor = require('jasmine'); | ||
// tslint:disable-next-line:no-require-imports | ||
Error.stackTraceLimit = Infinity; | ||
process.on('unhandledRejection', e => { | ||
throw e; | ||
}); | ||
jasmine_util.setTestEnvs( | ||
[{name: 'test-cocossd', backendName: 'cpu', flags: {}}]); | ||
const unitTests = 'src/**/*_test.ts'; | ||
const runner = new jasmineCtor(); | ||
runner.loadConfig({spec_files: [unitTests], random: false}); | ||
runner.execute(); |
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"noImplicitAny": false, | ||
"sourceMap": true, | ||
"removeComments": true, | ||
"preserveConstEnums": true, | ||
"declaration": true, | ||
"target": "es5", | ||
"lib": [ | ||
"es2015", | ||
"dom" | ||
], | ||
"outDir": "./dist", | ||
"noUnusedLocals": true, | ||
"noImplicitReturns": true, | ||
"noImplicitThis": true, | ||
"alwaysStrict": true, | ||
"noUnusedParameters": false, | ||
"pretty": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"allowUnreachableCode": false, | ||
"downlevelIteration": true | ||
}, | ||
"extends": "../tsconfig", | ||
"include": [ | ||
"src/**/*" | ||
"src/" | ||
], | ||
"exclude": [ | ||
"dist/", | ||
"src/**/*_test.ts" | ||
] | ||
} | ||
"node_modules/" | ||
], | ||
"compilerOptions": { | ||
"outDir": "./dist" | ||
} | ||
} |
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
213543
23
3104
142
17
1
3
1