├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── background.html
├── background.js
├── content.js
├── icon.png
├── manifest.json
├── popup.html
├── popup.js
├── third_party
└── deeplearnjs
│ ├── LICENSE
│ ├── deeplearn.0.5.js
│ └── deeplearn_knn_image_classifier.0.4.2.js
├── welcome.html
└── welcome.js
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows [Google's Open Source Community
28 | Guidelines](https://opensource.google.com/conduct/).
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cam Scroller
2 |
3 | Cam Scroller is an open-source Chrome extension that uses your webcam and
4 | [deeplearn.js](https://deeplearnjs.org) to enable scrolling through webpages
5 | using custom gestures that you define.
6 |
7 | The Chrome extension can be found in the Chrome web store at this link: https://chrome.google.com/webstore/detail/cam-scroller/egljnginfcbpehnpfojpbogiopdgjjak
8 |
9 | It makes use of the deeplearn.js [KNN image classifier](https://github.com/PAIR-code/deeplearnjs/blob/master/models/knn_image_classifier/knn_image_classifier.ts)
10 | in the same manner as [Teachable Machine](https://teachablemachine.withgoogle.com/)
11 | and [Cam Arcade](https://deeplearnjs.org/demos/teachable_gaming/).
12 |
13 | In doing so, your webcam images are processed locally on your machine and at no
14 | time is any information collected or sent externally.
15 |
16 | This simple Chrome extension is meant to show, through a minimal example, the
17 | types of experiences that can be enabled through the use of browser-based
18 | machine learning.
19 |
20 | 
21 |
22 | ## Usage
23 |
24 | ### How to install and configure the extension
25 |
26 | 1. Install the extension from the Chrome store.
27 | 1. Upon initial installation, the extension will ask for permission to access
28 | the webcam. After granting permission, you can close the welcome page.
29 | * Note that the extension keeps your webcam open, but at no point is any
30 | information from the webcam ever sent anywhere. All processing happens local
31 | to your machine.
32 | 1. Click the Cam Scroller browser action icon next to the address bar. In the
33 | popup, you should see a display of what your webcam is seeing. Click the "Create
34 | scrolling gestures" button and follow the on-screen instructions to create your
35 | custom scrolling gestures.
36 | * You will be asked to train three different poses: one for scrolling down,
37 | one for scrolling up, and one for the steady state of not scrolling at all.
38 |
39 | From this point on, for any new tab/page you load, scrolling can be
40 | controlled by the gestures you trained. You will see a visual scrolling
41 | indicator on the right side of the page when scrolling is being controlled by
42 | your gestures.
43 |
44 | The KNN image classifier weights for the trained gestures are stored in
45 | Chrome local storage, so the gestures do not have to be retrained when you
46 | close and then relaunch Chrome.
47 |
48 | ### Controls available in the extension
49 |
50 | If you want to temporarily turn off the Cam Scrolling capability,
51 | uncheck the checkbox in the Cam Scroller browser action popup.
52 |
53 | If at any time you wish to retrain the gestures, just click the "Create
54 | scrolling gestures" button again in the extension popup.
55 |
56 | ## Code breakdown
57 |
58 | welcome.[html/js] - Page launched on initial extension installation which
59 | requests webcam access for the extension.
60 |
61 | popup.[html/js] - Browser action popup page. Displays the webcam and has
62 | controls for training the scrolling gestures and enabling/disabling scrolling.
63 | Passes messages to the background page to do the actual processing.
64 |
65 | background.[html/js] - Contains all the machine learning logic for the
66 | extension. Trains the KNN image classifier when in training mode, infers which
67 | scrolling gestures are being performed when in inference mode, and sends
68 | messages to the content script to perform scrolling.
69 |
70 | content.js - Content script running with webpages loaded in Chrome. Calls
71 | window.scrollBy to scroll webpages and places visual indicators on the page when
72 | scrolling.
73 |
74 | ## Notice
75 |
76 | This is not an officially supported Google product.
77 |
--------------------------------------------------------------------------------
/background.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the 'License');
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an 'AS IS' BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | const math = new dl.NDArrayMathGPU();
18 | const NUM_CLASSES = 3;
19 | const K = 5;
20 | const knn = new knn_image_classifier.KNNImageClassifier(NUM_CLASSES, K, math);
21 |
22 | // Do first-time setup to gain access to webcam, if necessary.
23 | chrome.runtime.onInstalled.addListener((details) => {
24 | if (details.reason.search(/install/g) === -1) {
25 | return;
26 | }
27 | chrome.tabs.create({
28 | url: chrome.extension.getURL('welcome.html'),
29 | active: true
30 | });
31 | });
32 |
33 | // Mapping of training commands to KNN class indices. Special commands for
34 | // turning off training and for saving training weights are given negative
35 | // indices to signify that no training is to occur.
36 | const optionToClassIndex = {
37 | 'save': -2,
38 | 'off': -1,
39 | 'noaction': 0,
40 | 'down': 1,
41 | 'up': 2
42 | };
43 | const classIndexToDirection = [null, 'down', 'up'];
44 |
45 | // Current class index being trained, negative means not training.
46 | let classIndexToTrain = -1;
47 |
48 | // True if currently in 'infer' mode, meaning that the webcam is controlling
49 | // scrolling.
50 | let infer = false;
51 |
52 | // The previously-predicted class when in 'infer' mode.
53 | let previousPredictedIndex = -1;
54 |
55 | // Get previously-stored infer checkbox setting, if any.
56 | chrome.storage.local.get('infer', items => {
57 | infer = !!items['infer'];
58 | });
59 |
60 | // Get previously-stored saved trained model parameters, if any.
61 | chrome.storage.local.get('modelParams', params => {
62 | if ('modelParams' in params) {
63 | // Reshape saved model parameters to appropriate dims.
64 | const modelTensors = params.modelParams.map(flat => {
65 | if (flat.length > 0) {
66 | return dl.tensor2d(flat, [flat.length / 1000, 1000]);
67 | } else {
68 | return null;
69 | }
70 | });
71 | // Set saved model parameters on KNN classifier.
72 | knn.setClassLogitsMatrices(modelTensors);
73 | console.log('restored knn weights from storage');
74 | }
75 | });
76 |
77 | // Listener for commands from the extension popup (controller) page.
78 | chrome.extension.onRequest.addListener((request, sender) => {
79 | if ('train' in request) {
80 | if (request.train == 'save') {
81 | // If given a 'save' command then save the current weights from the KNN
82 | // classifier to local storage.
83 | const tensors = knn.getClassLogitsMatrices();
84 | const logitsToSave = tensors.map(tensor => {
85 | if (tensor) {
86 | return Array.from(tensor.flatten().dataSync());
87 | } else {
88 | return [];
89 | }
90 | });
91 | chrome.storage.local.set({
92 | 'modelParams': logitsToSave
93 | });
94 | }
95 | // Get the appropriate class index to train and ensure infer mode is off as
96 | // we are in training.
97 | classIndexToTrain = optionToClassIndex[request.train];
98 | infer = false;
99 | } else if ('infer' in request) {
100 | infer = request.infer;
101 | if (!infer) {
102 | // If infer mode is being disabled then make sure to turn off any current
103 | // scrolling.
104 | handleInfer(-1);
105 | }
106 | } else if ('reset' in request) {
107 | // If given a 'reset' command then clear all saved data from the KNN
108 | // classifier, as retraining will occur.
109 | for (let i = 0; i < NUM_CLASSES; i++) {
110 | knn.clearClass(i);
111 | }
112 | }
113 | });
114 |
115 | const vid = document.querySelector('#webcamVideo');
116 |
117 | // Setup webcam, initialize the KNN classifier model and start the work loop.
118 | async function setupCam() {
119 | navigator.mediaDevices.getUserMedia({
120 | video: true
121 | }).then(mediaStream => {
122 | vid.srcObject = mediaStream;
123 | }).catch((error) => {
124 | console.warn(error);
125 | });
126 | await knn.load();
127 | setTimeout(loop, 50);
128 | }
129 |
130 | // If cam acecss has already been granted to this extension, setup webcam.
131 | chrome.storage.local.get('camAccess', items => {
132 | if (!!items['camAccess']) {
133 | console.log('cam access already exists');
134 | setupCam();
135 | }
136 | });
137 |
138 | // If cam acecss gets granted to this extension, setup webcam.
139 | chrome.storage.onChanged.addListener((changes, namespace) => {
140 | if ('camAccess' in changes) {
141 | console.log('cam access granted');
142 | setupCam();
143 | }
144 | });
145 |
146 | // Work loop function performed every 50ms by the extension.
147 | async function loop() {
148 | if (infer) {
149 | // If in infer mode then predict a class from the current webcam image
150 | // and take appropriate action.
151 | await math.scope(async (keep, track) => {
152 | const image = track(dl.Array3D.fromPixels(vid));
153 | const results = await knn.predictClass(image);
154 | handleInfer(results.classIndex);
155 | });
156 | } else if (classIndexToTrain >= 0) {
157 | // If in training mode, add the current webcam image to the current
158 | // class to train.
159 | await math.scope(async (keep, track) => {
160 | const image = track(dl.Array3D.fromPixels(vid));
161 | await knn.addImage(image, classIndexToTrain);
162 | });
163 | }
164 | // Rerun the loop in 50ms.
165 | setTimeout(loop, 50);
166 | }
167 |
168 | // Handles inferences from the KNN classifier.
169 | function handleInfer(classIndex) {
170 | // If the currently-inferred class is the same as the previously-inferred
171 | // class then there is nothing to be done.
172 | if (classIndex != previousPredictedIndex) {
173 | let tabId = -1;
174 | chrome.tabs.query({
175 | active: true,
176 | currentWindow: true
177 | }, (tabs) => {
178 | // Find the active tab in the browser.
179 | if (tabs.length == 0) {
180 | console.log('no active tab');
181 | return;
182 | }
183 | tabId = tabs[0].id;
184 | const info = {};
185 | // Turn off any current scrolling, as a new scroll command has been
186 | // inferred.
187 | if (previousPredictedIndex >= 1) {
188 | info.off = true;
189 | }
190 | previousPredictedIndex = classIndex;
191 | // Turn on the new scroll direction.
192 | if (classIndex >= 1) {
193 | info.on = {direction: classIndexToDirection[classIndex]};
194 | }
195 | // Send a message to the active tab indicating which scrolling actions
196 | // to start or end.
197 | chrome.tabs.sendMessage(tabId, info);
198 | });
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/content.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // The current timer, saved if timer cancellation is needed.
18 | let timer = -1;
19 |
20 | // The amount to scroll vertically by, in pixels.
21 | let scrollAmount = 0;
22 |
23 | // Scrolls by the currently-set scroll amount and sets a timeout to scroll
24 | // again in 50ms.
25 | function scroller() {
26 | console.log('scrolling by ' + scrollAmount);
27 | window.scrollBy(0, scrollAmount);
28 | timer = setTimeout(scroller, 50);
29 | }
30 |
31 | // Changes the up or down scrolling indicator as specified.
32 | function changeIndicator(indicator, show) {
33 | indicator.style.visibility = show ? 'visible' : 'hidden';
34 | indicator.style.opacity = show ? '1' : '0';
35 | }
36 |
37 | // Listener for messages from the extension background page.
38 | chrome.runtime.onMessage.addListener((request, sender) => {
39 | // If turning scrolling off, clear the timeout and remove any scrolling
40 | // indicators.
41 | if ('off' in request) {
42 | clearTimeout(timer);
43 | changeIndicator(camControlDown, false);
44 | changeIndicator(camControlUp, false);
45 | console.log('off');
46 | }
47 | if ('on' in request) {
48 | // If turning scrolling on then set the appopriate indicator and scroll
49 | // amount then start the scrolling process.
50 | if (request.on.direction == 'down') {
51 | changeIndicator(camControlDown, true);
52 | scrollAmount = 20;
53 | } else if (request.on.direction == 'up') {
54 | changeIndicator(camControlUp, true);
55 | scrollAmount = -20;
56 | }
57 | console.log('on');
58 | scroller();
59 | }
60 | });
61 |
62 | // Create up and down arrow elements for display when scrolling.
63 | // Uses borders to create arrow shapes, transition to enable smooth animations
64 | // of the arrows, and z-index to ensure they display on top of the page
65 | // content.
66 | const camControlUp = document.createElement('div');
67 | camControlUp.style.position = 'fixed';
68 | camControlUp.style.height = '0';
69 | camControlUp.style.width = '0';
70 | camControlUp.style.right = '0';
71 | camControlUp.style.top = '0';
72 | camControlUp.style.borderLeft = '20px solid transparent';
73 | camControlUp.style.borderRight = '20px solid transparent';
74 | camControlUp.style.borderBottom = '40px solid #545454';
75 | camControlUp.style.visibility = 'hidden';
76 | camControlUp.style.transition = 'visibility 1s, opacity 1s';
77 | camControlUp.style.zIndex = '100000';
78 | document.body.appendChild(camControlUp);
79 | const camControlDown = document.createElement('div');
80 | camControlDown.style.position = 'fixed';
81 | camControlDown.style.width = '0';
82 | camControlDown.style.height = '0';
83 | camControlDown.style.right = '0';
84 | camControlDown.style.bottom = '0';
85 | camControlDown.style.borderLeft = '20px solid transparent';
86 | camControlDown.style.borderRight = '20px solid transparent';
87 | camControlDown.style.borderTop = '40px solid #545454';
88 | camControlDown.style.visibility = 'hidden';
89 | camControlDown.style.transition = 'visibility 1s, opacity 1s';
90 | camControlDown.style.zIndex = '100000';
91 | document.body.appendChild(camControlDown);
92 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PAIR-code/cam-scroller/201981ab023587a31ed6ea4b863d2d92d6a7231a/icon.png
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "Cam Scroller",
4 | "description": "This extension lets a user scroll webpages using webcam gestures.",
5 | "version": "0.1",
6 | "browser_action": {
7 | "default_icon": "icon.png",
8 | "default_popup": "popup.html"
9 | },
10 | "content_scripts": [
11 | {
12 | "matches": [
13 | ""
14 | ],
15 | "js": ["content.js"]
16 | }
17 | ],
18 | "background": {
19 | "page": "background.html"
20 | },
21 | "permissions": [
22 | "activeTab",
23 | "storage",
24 | "unlimitedStorage"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | Cam Scroller
18 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/popup.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the 'License');
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an 'AS IS' BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | function turnOffInferring() {
18 | document.getElementById('infer').checked = false;
19 | chrome.storage.local.set({
20 | 'infer': false
21 | }, () => {});
22 | chrome.extension.sendRequest({
23 | infer: false
24 | });
25 | }
26 |
27 | function prepareNoActionTrain() {
28 | chrome.extension.sendRequest({
29 | train: 'off'
30 | });
31 | chrome.extension.sendRequest({
32 | reset: true
33 | });
34 | document.querySelector('#traintext').innerHTML =
35 | 'Training no action in 2 seconds';
36 | setTimeout(startNoActionTrain, 2000);
37 | }
38 |
39 | function startNoActionTrain() {
40 | document.querySelector('#traintext').innerHTML =
41 | 'Training no action for 5 seconds';
42 | chrome.extension.sendRequest({
43 | train: 'noaction'
44 | });
45 | setTimeout(prepareScrollDownTrain, 5000);
46 | }
47 |
48 | function prepareScrollDownTrain() {
49 | chrome.extension.sendRequest({
50 | train: 'off'
51 | });
52 | document.querySelector('#traintext').innerHTML =
53 | 'Training scroll down in 2 seconds';
54 | setTimeout(startScrollDownTrain, 2000);
55 | }
56 |
57 | function startScrollDownTrain() {
58 | document.querySelector('#traintext').innerHTML =
59 | 'Training scroll down for 5 seconds';
60 | chrome.extension.sendRequest({
61 | train: 'down'
62 | });
63 | setTimeout(prepareScrollUpTrain, 5000);
64 | }
65 |
66 | function prepareScrollUpTrain() {
67 | chrome.extension.sendRequest({
68 | train: 'off'
69 | });
70 | document.querySelector('#traintext').innerHTML =
71 | 'Training scroll up in 2 seconds';
72 | setTimeout(startScrollUpTrain, 2000);
73 | }
74 |
75 | function startScrollUpTrain() {
76 | document.querySelector('#traintext').innerHTML =
77 | 'Training scroll up for 5 seconds';
78 | chrome.extension.sendRequest({
79 | train: 'up'
80 | });
81 | setTimeout(finishTraining, 5000);
82 | }
83 |
84 | function finishTraining() {
85 | document.querySelector('#traintext').innerHTML = '';
86 | chrome.extension.sendRequest({
87 | train: 'save'
88 | });
89 | document.getElementById('infer').checked = true;
90 | chrome.storage.local.set({
91 | 'infer': true
92 | }, () => {});
93 | chrome.extension.sendRequest({
94 | infer: true
95 | });
96 | }
97 |
98 | function inferButtonClicked() {
99 | const inferSetting = this.checked;
100 | chrome.storage.local.set({
101 | 'infer': inferSetting
102 | }, () => {});
103 | chrome.extension.sendRequest({
104 | infer: inferSetting
105 | });
106 | }
107 |
108 | function trainClicked() {
109 | turnOffInferring();
110 | prepareNoActionTrain();
111 | }
112 |
113 | function setupCam() {
114 | navigator.mediaDevices.getUserMedia({
115 | video: true
116 | }).then(mediaStream => {
117 | document.querySelector('#webcamVideo').srcObject = mediaStream;
118 | }).catch((error) => {
119 | console.warn(error);
120 | });
121 | }
122 |
123 | setupCam();
124 |
125 | // Setup checkbox with correct initial value.
126 | chrome.storage.local.get('infer', items =>
127 | document.getElementById('infer').checked = !!items['infer']);
128 |
129 | document.getElementById('infer').onclick = inferButtonClicked;
130 | document.getElementById('train').onclick = trainClicked;
131 |
--------------------------------------------------------------------------------
/third_party/deeplearnjs/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/third_party/deeplearnjs/deeplearn_knn_image_classifier.0.4.2.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.knn_image_classifier = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
34 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
35 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
36 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
37 | if (t[2]) _.ops.pop();
38 | _.trys.pop(); continue;
39 | }
40 | op = body.call(thisArg, _);
41 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
42 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
43 | }
44 | };
45 | Object.defineProperty(exports, "__esModule", { value: true });
46 | var dl = (typeof window !== "undefined" ? window['dl'] : typeof global !== "undefined" ? global['dl'] : null);
47 | var deeplearn_squeezenet_1 = require("deeplearn-squeezenet");
48 | var model_util = require("../util");
49 | var KNNImageClassifier = (function () {
50 | function KNNImageClassifier(numClasses, k) {
51 | this.numClasses = numClasses;
52 | this.k = k;
53 | this.classLogitsMatrices = [];
54 | this.classExampleCount = [];
55 | this.varsLoaded = false;
56 | this.squashLogitsDenominator = dl.scalar(300);
57 | for (var i = 0; i < this.numClasses; i++) {
58 | this.classLogitsMatrices.push(null);
59 | this.classExampleCount.push(0);
60 | }
61 | this.squeezeNet = new deeplearn_squeezenet_1.SqueezeNet();
62 | }
63 | KNNImageClassifier.prototype.load = function () {
64 | return __awaiter(this, void 0, void 0, function () {
65 | return __generator(this, function (_a) {
66 | switch (_a.label) {
67 | case 0: return [4, this.squeezeNet.load()];
68 | case 1:
69 | _a.sent();
70 | this.varsLoaded = true;
71 | return [2];
72 | }
73 | });
74 | });
75 | };
76 | KNNImageClassifier.prototype.clearClass = function (classIndex) {
77 | if (classIndex >= this.numClasses) {
78 | console.log('Cannot clear invalid class ${classIndex}');
79 | return;
80 | }
81 | this.classLogitsMatrices[classIndex] = null;
82 | this.classExampleCount[classIndex] = 0;
83 | this.clearTrainLogitsMatrix();
84 | };
85 | KNNImageClassifier.prototype.addImage = function (image, classIndex) {
86 | var _this = this;
87 | if (!this.varsLoaded) {
88 | console.warn('Cannot add images until vars have been loaded.');
89 | return;
90 | }
91 | if (classIndex >= this.numClasses) {
92 | console.warn('Cannot add to invalid class ${classIndex}');
93 | }
94 | this.clearTrainLogitsMatrix();
95 | dl.tidy(function () {
96 | var logits = _this.squeezeNet.predict(image);
97 | var imageLogits = _this.normalizeVector(logits);
98 | var logitsSize = imageLogits.shape[0];
99 | if (_this.classLogitsMatrices[classIndex] == null) {
100 | _this.classLogitsMatrices[classIndex] = imageLogits.as2D(1, logitsSize);
101 | }
102 | else {
103 | var newTrainLogitsMatrix = _this.classLogitsMatrices[classIndex]
104 | .as2D(_this.classExampleCount[classIndex], logitsSize)
105 | .concat(imageLogits.as2D(1, logitsSize), 0);
106 | _this.classLogitsMatrices[classIndex].dispose();
107 | _this.classLogitsMatrices[classIndex] = newTrainLogitsMatrix;
108 | }
109 | dl.keep(_this.classLogitsMatrices[classIndex]);
110 | _this.classExampleCount[classIndex]++;
111 | });
112 | };
113 | KNNImageClassifier.prototype.predict = function (image) {
114 | var _this = this;
115 | if (!this.varsLoaded) {
116 | throw new Error('Cannot predict until vars have been loaded.');
117 | }
118 | return dl.tidy(function () {
119 | var logits = _this.squeezeNet.predict(image);
120 | var imageLogits = _this.normalizeVector(logits);
121 | var logitsSize = imageLogits.shape[0];
122 | if (_this.trainLogitsMatrix == null) {
123 | var newTrainLogitsMatrix = null;
124 | for (var i = 0; i < _this.numClasses; i++) {
125 | newTrainLogitsMatrix = _this.concatWithNulls(newTrainLogitsMatrix, _this.classLogitsMatrices[i]);
126 | }
127 | _this.trainLogitsMatrix = newTrainLogitsMatrix;
128 | }
129 | if (_this.trainLogitsMatrix == null) {
130 | console.warn('Cannot predict without providing training images.');
131 | return null;
132 | }
133 | dl.keep(_this.trainLogitsMatrix);
134 | var numExamples = _this.getNumExamples();
135 | return _this.trainLogitsMatrix.as2D(numExamples, logitsSize)
136 | .matMul(imageLogits.as2D(logitsSize, 1))
137 | .as1D();
138 | });
139 | };
140 | KNNImageClassifier.prototype.predictClass = function (image) {
141 | return __awaiter(this, void 0, void 0, function () {
142 | var imageClass, confidences, knn, numExamples, kVal, topK, _a, _b, topKIndices, indicesForClasses, topKCountsForClasses, i, num, i, classForEntry, topConfidence, i, probability;
143 | return __generator(this, function (_c) {
144 | switch (_c.label) {
145 | case 0:
146 | imageClass = -1;
147 | confidences = new Array(this.numClasses);
148 | if (!this.varsLoaded) {
149 | throw new Error('Cannot predict until vars have been loaded.');
150 | }
151 | knn = this.predict(image).asType('float32');
152 | numExamples = this.getNumExamples();
153 | kVal = Math.min(this.k, numExamples);
154 | _b = (_a = model_util).topK;
155 | return [4, knn.data()];
156 | case 1:
157 | topK = _b.apply(_a, [_c.sent(), kVal]);
158 | knn.dispose();
159 | topKIndices = topK.indices;
160 | if (topKIndices == null) {
161 | return [2, { classIndex: imageClass, confidences: confidences }];
162 | }
163 | indicesForClasses = [];
164 | topKCountsForClasses = [];
165 | for (i = 0; i < this.numClasses; i++) {
166 | topKCountsForClasses.push(0);
167 | num = this.classExampleCount[i];
168 | if (i > 0) {
169 | num += indicesForClasses[i - 1];
170 | }
171 | indicesForClasses.push(num);
172 | }
173 | for (i = 0; i < topKIndices.length; i++) {
174 | for (classForEntry = 0; classForEntry < indicesForClasses.length; classForEntry++) {
175 | if (topKIndices[i] < indicesForClasses[classForEntry]) {
176 | topKCountsForClasses[classForEntry]++;
177 | break;
178 | }
179 | }
180 | }
181 | topConfidence = 0;
182 | for (i = 0; i < this.numClasses; i++) {
183 | probability = topKCountsForClasses[i] / kVal;
184 | if (probability > topConfidence) {
185 | topConfidence = probability;
186 | imageClass = i;
187 | }
188 | confidences[i] = probability;
189 | }
190 | return [2, { classIndex: imageClass, confidences: confidences }];
191 | }
192 | });
193 | });
194 | };
195 | KNNImageClassifier.prototype.getClassExampleCount = function () {
196 | return this.classExampleCount;
197 | };
198 | KNNImageClassifier.prototype.getClassLogitsMatrices = function () {
199 | return this.classLogitsMatrices;
200 | };
201 | KNNImageClassifier.prototype.setClassLogitsMatrices = function (classLogitsMatrices) {
202 | this.classLogitsMatrices = classLogitsMatrices;
203 | this.classExampleCount = classLogitsMatrices.map(function (tensor) { return tensor != null ? tensor.shape[0] : 0; });
204 | this.clearTrainLogitsMatrix();
205 | };
206 | KNNImageClassifier.prototype.clearTrainLogitsMatrix = function () {
207 | if (this.trainLogitsMatrix != null) {
208 | this.trainLogitsMatrix.dispose();
209 | this.trainLogitsMatrix = null;
210 | }
211 | };
212 | KNNImageClassifier.prototype.concatWithNulls = function (ndarray1, ndarray2) {
213 | if (ndarray1 == null && ndarray2 == null) {
214 | return null;
215 | }
216 | if (ndarray1 == null) {
217 | return ndarray2.clone();
218 | }
219 | else if (ndarray2 === null) {
220 | return ndarray1.clone();
221 | }
222 | return ndarray1.concat(ndarray2, 0);
223 | };
224 | KNNImageClassifier.prototype.normalizeVector = function (vec) {
225 | var squashedVec = dl.div(vec, this.squashLogitsDenominator);
226 | var sqrtSum = squashedVec.square().sum().sqrt();
227 | return dl.div(squashedVec, sqrtSum);
228 | };
229 | KNNImageClassifier.prototype.getNumExamples = function () {
230 | var total = 0;
231 | for (var i = 0; i < this.classExampleCount.length; i++) {
232 | total += this.classExampleCount[i];
233 | }
234 | return total;
235 | };
236 | KNNImageClassifier.prototype.dispose = function () {
237 | this.squeezeNet.dispose();
238 | this.clearTrainLogitsMatrix();
239 | this.classLogitsMatrices.forEach(function (classLogitsMatrix) { return classLogitsMatrix.dispose(); });
240 | this.squashLogitsDenominator.dispose();
241 | };
242 | return KNNImageClassifier;
243 | }());
244 | exports.KNNImageClassifier = KNNImageClassifier;
245 |
246 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
247 | },{"../util":7,"deeplearn-squeezenet":4}],3:[function(require,module,exports){
248 | "use strict";
249 | Object.defineProperty(exports, "__esModule", { value: true });
250 | exports.IMAGENET_CLASSES = {
251 | 0: 'tench, Tinca tinca',
252 | 1: 'goldfish, Carassius auratus',
253 | 2: 'great white shark, white shark, man-eater, man-eating shark, ' +
254 | 'Carcharodon carcharias',
255 | 3: 'tiger shark, Galeocerdo cuvieri',
256 | 4: 'hammerhead, hammerhead shark',
257 | 5: 'electric ray, crampfish, numbfish, torpedo',
258 | 6: 'stingray',
259 | 7: 'cock',
260 | 8: 'hen',
261 | 9: 'ostrich, Struthio camelus',
262 | 10: 'brambling, Fringilla montifringilla',
263 | 11: 'goldfinch, Carduelis carduelis',
264 | 12: 'house finch, linnet, Carpodacus mexicanus',
265 | 13: 'junco, snowbird',
266 | 14: 'indigo bunting, indigo finch, indigo bird, Passerina cyanea',
267 | 15: 'robin, American robin, Turdus migratorius',
268 | 16: 'bulbul',
269 | 17: 'jay',
270 | 18: 'magpie',
271 | 19: 'chickadee',
272 | 20: 'water ouzel, dipper',
273 | 21: 'kite',
274 | 22: 'bald eagle, American eagle, Haliaeetus leucocephalus',
275 | 23: 'vulture',
276 | 24: 'great grey owl, great gray owl, Strix nebulosa',
277 | 25: 'European fire salamander, Salamandra salamandra',
278 | 26: 'common newt, Triturus vulgaris',
279 | 27: 'eft',
280 | 28: 'spotted salamander, Ambystoma maculatum',
281 | 29: 'axolotl, mud puppy, Ambystoma mexicanum',
282 | 30: 'bullfrog, Rana catesbeiana',
283 | 31: 'tree frog, tree-frog',
284 | 32: 'tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui',
285 | 33: 'loggerhead, loggerhead turtle, Caretta caretta',
286 | 34: 'leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea',
287 | 35: 'mud turtle',
288 | 36: 'terrapin',
289 | 37: 'box turtle, box tortoise',
290 | 38: 'banded gecko',
291 | 39: 'common iguana, iguana, Iguana iguana',
292 | 40: 'American chameleon, anole, Anolis carolinensis',
293 | 41: 'whiptail, whiptail lizard',
294 | 42: 'agama',
295 | 43: 'frilled lizard, Chlamydosaurus kingi',
296 | 44: 'alligator lizard',
297 | 45: 'Gila monster, Heloderma suspectum',
298 | 46: 'green lizard, Lacerta viridis',
299 | 47: 'African chameleon, Chamaeleo chamaeleon',
300 | 48: 'Komodo dragon, Komodo lizard, dragon lizard, giant lizard, ' +
301 | 'Varanus komodoensis',
302 | 49: 'African crocodile, Nile crocodile, Crocodylus niloticus',
303 | 50: 'American alligator, Alligator mississipiensis',
304 | 51: 'triceratops',
305 | 52: 'thunder snake, worm snake, Carphophis amoenus',
306 | 53: 'ringneck snake, ring-necked snake, ring snake',
307 | 54: 'hognose snake, puff adder, sand viper',
308 | 55: 'green snake, grass snake',
309 | 56: 'king snake, kingsnake',
310 | 57: 'garter snake, grass snake',
311 | 58: 'water snake',
312 | 59: 'vine snake',
313 | 60: 'night snake, Hypsiglena torquata',
314 | 61: 'boa constrictor, Constrictor constrictor',
315 | 62: 'rock python, rock snake, Python sebae',
316 | 63: 'Indian cobra, Naja naja',
317 | 64: 'green mamba',
318 | 65: 'sea snake',
319 | 66: 'horned viper, cerastes, sand viper, horned asp, Cerastes cornutus',
320 | 67: 'diamondback, diamondback rattlesnake, Crotalus adamanteus',
321 | 68: 'sidewinder, horned rattlesnake, Crotalus cerastes',
322 | 69: 'trilobite',
323 | 70: 'harvestman, daddy longlegs, Phalangium opilio',
324 | 71: 'scorpion',
325 | 72: 'black and gold garden spider, Argiope aurantia',
326 | 73: 'barn spider, Araneus cavaticus',
327 | 74: 'garden spider, Aranea diademata',
328 | 75: 'black widow, Latrodectus mactans',
329 | 76: 'tarantula',
330 | 77: 'wolf spider, hunting spider',
331 | 78: 'tick',
332 | 79: 'centipede',
333 | 80: 'black grouse',
334 | 81: 'ptarmigan',
335 | 82: 'ruffed grouse, partridge, Bonasa umbellus',
336 | 83: 'prairie chicken, prairie grouse, prairie fowl',
337 | 84: 'peacock',
338 | 85: 'quail',
339 | 86: 'partridge',
340 | 87: 'African grey, African gray, Psittacus erithacus',
341 | 88: 'macaw',
342 | 89: 'sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita',
343 | 90: 'lorikeet',
344 | 91: 'coucal',
345 | 92: 'bee eater',
346 | 93: 'hornbill',
347 | 94: 'hummingbird',
348 | 95: 'jacamar',
349 | 96: 'toucan',
350 | 97: 'drake',
351 | 98: 'red-breasted merganser, Mergus serrator',
352 | 99: 'goose',
353 | 100: 'black swan, Cygnus atratus',
354 | 101: 'tusker',
355 | 102: 'echidna, spiny anteater, anteater',
356 | 103: 'platypus, duckbill, duckbilled platypus, duck-billed platypus, ' +
357 | 'Ornithorhynchus anatinus',
358 | 104: 'wallaby, brush kangaroo',
359 | 105: 'koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus',
360 | 106: 'wombat',
361 | 107: 'jelly fish',
362 | 108: 'sea anemone, anemone',
363 | 109: 'brain coral',
364 | 110: 'flatworm, platyhelminth',
365 | 111: 'nematode, nematode worm, roundworm',
366 | 112: 'conch',
367 | 113: 'snail',
368 | 114: 'slug',
369 | 115: 'sea slug, nudibranch',
370 | 116: 'chiton, coat-of-mail shell, sea cradle, polyplacophore',
371 | 117: 'chambered nautilus, pearly nautilus, nautilus',
372 | 118: 'Dungeness crab, Cancer magister',
373 | 119: 'rock crab, Cancer irroratus',
374 | 120: 'fiddler crab',
375 | 121: 'king crab, Alaska crab, Alaskan king crab, Alaska king crab, ' +
376 | 'Paralithodes camtschatica',
377 | 122: 'American lobster, Northern lobster, Maine lobster, Homarus americanus',
378 | 123: 'spiny lobster, langouste, rock lobster, crawfish, crayfish, sea ' +
379 | 'crawfish',
380 | 124: 'crayfish, crawfish, crawdad, crawdaddy',
381 | 125: 'hermit crab',
382 | 126: 'isopod',
383 | 127: 'white stork, Ciconia ciconia',
384 | 128: 'black stork, Ciconia nigra',
385 | 129: 'spoonbill',
386 | 130: 'flamingo',
387 | 131: 'little blue heron, Egretta caerulea',
388 | 132: 'American egret, great white heron, Egretta albus',
389 | 133: 'bittern',
390 | 134: 'crane',
391 | 135: 'limpkin, Aramus pictus',
392 | 136: 'European gallinule, Porphyrio porphyrio',
393 | 137: 'American coot, marsh hen, mud hen, water hen, Fulica americana',
394 | 138: 'bustard',
395 | 139: 'ruddy turnstone, Arenaria interpres',
396 | 140: 'red-backed sandpiper, dunlin, Erolia alpina',
397 | 141: 'redshank, Tringa totanus',
398 | 142: 'dowitcher',
399 | 143: 'oystercatcher, oyster catcher',
400 | 144: 'pelican',
401 | 145: 'king penguin, Aptenodytes patagonica',
402 | 146: 'albatross, mollymawk',
403 | 147: 'grey whale, gray whale, devilfish, Eschrichtius gibbosus, ' +
404 | 'Eschrichtius robustus',
405 | 148: 'killer whale, killer, orca, grampus, sea wolf, Orcinus orca',
406 | 149: 'dugong, Dugong dugon',
407 | 150: 'sea lion',
408 | 151: 'Chihuahua',
409 | 152: 'Japanese spaniel',
410 | 153: 'Maltese dog, Maltese terrier, Maltese',
411 | 154: 'Pekinese, Pekingese, Peke',
412 | 155: 'Shih-Tzu',
413 | 156: 'Blenheim spaniel',
414 | 157: 'papillon',
415 | 158: 'toy terrier',
416 | 159: 'Rhodesian ridgeback',
417 | 160: 'Afghan hound, Afghan',
418 | 161: 'basset, basset hound',
419 | 162: 'beagle',
420 | 163: 'bloodhound, sleuthhound',
421 | 164: 'bluetick',
422 | 165: 'black-and-tan coonhound',
423 | 166: 'Walker hound, Walker foxhound',
424 | 167: 'English foxhound',
425 | 168: 'redbone',
426 | 169: 'borzoi, Russian wolfhound',
427 | 170: 'Irish wolfhound',
428 | 171: 'Italian greyhound',
429 | 172: 'whippet',
430 | 173: 'Ibizan hound, Ibizan Podenco',
431 | 174: 'Norwegian elkhound, elkhound',
432 | 175: 'otterhound, otter hound',
433 | 176: 'Saluki, gazelle hound',
434 | 177: 'Scottish deerhound, deerhound',
435 | 178: 'Weimaraner',
436 | 179: 'Staffordshire bullterrier, Staffordshire bull terrier',
437 | 180: 'American Staffordshire terrier, Staffordshire terrier, American pit ' +
438 | 'bull terrier, pit bull terrier',
439 | 181: 'Bedlington terrier',
440 | 182: 'Border terrier',
441 | 183: 'Kerry blue terrier',
442 | 184: 'Irish terrier',
443 | 185: 'Norfolk terrier',
444 | 186: 'Norwich terrier',
445 | 187: 'Yorkshire terrier',
446 | 188: 'wire-haired fox terrier',
447 | 189: 'Lakeland terrier',
448 | 190: 'Sealyham terrier, Sealyham',
449 | 191: 'Airedale, Airedale terrier',
450 | 192: 'cairn, cairn terrier',
451 | 193: 'Australian terrier',
452 | 194: 'Dandie Dinmont, Dandie Dinmont terrier',
453 | 195: 'Boston bull, Boston terrier',
454 | 196: 'miniature schnauzer',
455 | 197: 'giant schnauzer',
456 | 198: 'standard schnauzer',
457 | 199: 'Scotch terrier, Scottish terrier, Scottie',
458 | 200: 'Tibetan terrier, chrysanthemum dog',
459 | 201: 'silky terrier, Sydney silky',
460 | 202: 'soft-coated wheaten terrier',
461 | 203: 'West Highland white terrier',
462 | 204: 'Lhasa, Lhasa apso',
463 | 205: 'flat-coated retriever',
464 | 206: 'curly-coated retriever',
465 | 207: 'golden retriever',
466 | 208: 'Labrador retriever',
467 | 209: 'Chesapeake Bay retriever',
468 | 210: 'German short-haired pointer',
469 | 211: 'vizsla, Hungarian pointer',
470 | 212: 'English setter',
471 | 213: 'Irish setter, red setter',
472 | 214: 'Gordon setter',
473 | 215: 'Brittany spaniel',
474 | 216: 'clumber, clumber spaniel',
475 | 217: 'English springer, English springer spaniel',
476 | 218: 'Welsh springer spaniel',
477 | 219: 'cocker spaniel, English cocker spaniel, cocker',
478 | 220: 'Sussex spaniel',
479 | 221: 'Irish water spaniel',
480 | 222: 'kuvasz',
481 | 223: 'schipperke',
482 | 224: 'groenendael',
483 | 225: 'malinois',
484 | 226: 'briard',
485 | 227: 'kelpie',
486 | 228: 'komondor',
487 | 229: 'Old English sheepdog, bobtail',
488 | 230: 'Shetland sheepdog, Shetland sheep dog, Shetland',
489 | 231: 'collie',
490 | 232: 'Border collie',
491 | 233: 'Bouvier des Flandres, Bouviers des Flandres',
492 | 234: 'Rottweiler',
493 | 235: 'German shepherd, German shepherd dog, German police dog, alsatian',
494 | 236: 'Doberman, Doberman pinscher',
495 | 237: 'miniature pinscher',
496 | 238: 'Greater Swiss Mountain dog',
497 | 239: 'Bernese mountain dog',
498 | 240: 'Appenzeller',
499 | 241: 'EntleBucher',
500 | 242: 'boxer',
501 | 243: 'bull mastiff',
502 | 244: 'Tibetan mastiff',
503 | 245: 'French bulldog',
504 | 246: 'Great Dane',
505 | 247: 'Saint Bernard, St Bernard',
506 | 248: 'Eskimo dog, husky',
507 | 249: 'malamute, malemute, Alaskan malamute',
508 | 250: 'Siberian husky',
509 | 251: 'dalmatian, coach dog, carriage dog',
510 | 252: 'affenpinscher, monkey pinscher, monkey dog',
511 | 253: 'basenji',
512 | 254: 'pug, pug-dog',
513 | 255: 'Leonberg',
514 | 256: 'Newfoundland, Newfoundland dog',
515 | 257: 'Great Pyrenees',
516 | 258: 'Samoyed, Samoyede',
517 | 259: 'Pomeranian',
518 | 260: 'chow, chow chow',
519 | 261: 'keeshond',
520 | 262: 'Brabancon griffon',
521 | 263: 'Pembroke, Pembroke Welsh corgi',
522 | 264: 'Cardigan, Cardigan Welsh corgi',
523 | 265: 'toy poodle',
524 | 266: 'miniature poodle',
525 | 267: 'standard poodle',
526 | 268: 'Mexican hairless',
527 | 269: 'timber wolf, grey wolf, gray wolf, Canis lupus',
528 | 270: 'white wolf, Arctic wolf, Canis lupus tundrarum',
529 | 271: 'red wolf, maned wolf, Canis rufus, Canis niger',
530 | 272: 'coyote, prairie wolf, brush wolf, Canis latrans',
531 | 273: 'dingo, warrigal, warragal, Canis dingo',
532 | 274: 'dhole, Cuon alpinus',
533 | 275: 'African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus',
534 | 276: 'hyena, hyaena',
535 | 277: 'red fox, Vulpes vulpes',
536 | 278: 'kit fox, Vulpes macrotis',
537 | 279: 'Arctic fox, white fox, Alopex lagopus',
538 | 280: 'grey fox, gray fox, Urocyon cinereoargenteus',
539 | 281: 'tabby, tabby cat',
540 | 282: 'tiger cat',
541 | 283: 'Persian cat',
542 | 284: 'Siamese cat, Siamese',
543 | 285: 'Egyptian cat',
544 | 286: 'cougar, puma, catamount, mountain lion, painter, panther, ' +
545 | 'Felis concolor',
546 | 287: 'lynx, catamount',
547 | 288: 'leopard, Panthera pardus',
548 | 289: 'snow leopard, ounce, Panthera uncia',
549 | 290: 'jaguar, panther, Panthera onca, Felis onca',
550 | 291: 'lion, king of beasts, Panthera leo',
551 | 292: 'tiger, Panthera tigris',
552 | 293: 'cheetah, chetah, Acinonyx jubatus',
553 | 294: 'brown bear, bruin, Ursus arctos',
554 | 295: 'American black bear, black bear, Ursus americanus, Euarctos ' +
555 | 'americanus',
556 | 296: 'ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus',
557 | 297: 'sloth bear, Melursus ursinus, Ursus ursinus',
558 | 298: 'mongoose',
559 | 299: 'meerkat, mierkat',
560 | 300: 'tiger beetle',
561 | 301: 'ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle',
562 | 302: 'ground beetle, carabid beetle',
563 | 303: 'long-horned beetle, longicorn, longicorn beetle',
564 | 304: 'leaf beetle, chrysomelid',
565 | 305: 'dung beetle',
566 | 306: 'rhinoceros beetle',
567 | 307: 'weevil',
568 | 308: 'fly',
569 | 309: 'bee',
570 | 310: 'ant, emmet, pismire',
571 | 311: 'grasshopper, hopper',
572 | 312: 'cricket',
573 | 313: 'walking stick, walkingstick, stick insect',
574 | 314: 'cockroach, roach',
575 | 315: 'mantis, mantid',
576 | 316: 'cicada, cicala',
577 | 317: 'leafhopper',
578 | 318: 'lacewing, lacewing fly',
579 | 319: 'dragonfly, darning needle, devil\'s darning needle, sewing needle, ' +
580 | 'snake feeder, snake doctor, mosquito hawk, skeeter hawk',
581 | 320: 'damselfly',
582 | 321: 'admiral',
583 | 322: 'ringlet, ringlet butterfly',
584 | 323: 'monarch, monarch butterfly, milkweed butterfly, Danaus plexippus',
585 | 324: 'cabbage butterfly',
586 | 325: 'sulphur butterfly, sulfur butterfly',
587 | 326: 'lycaenid, lycaenid butterfly',
588 | 327: 'starfish, sea star',
589 | 328: 'sea urchin',
590 | 329: 'sea cucumber, holothurian',
591 | 330: 'wood rabbit, cottontail, cottontail rabbit',
592 | 331: 'hare',
593 | 332: 'Angora, Angora rabbit',
594 | 333: 'hamster',
595 | 334: 'porcupine, hedgehog',
596 | 335: 'fox squirrel, eastern fox squirrel, Sciurus niger',
597 | 336: 'marmot',
598 | 337: 'beaver',
599 | 338: 'guinea pig, Cavia cobaya',
600 | 339: 'sorrel',
601 | 340: 'zebra',
602 | 341: 'hog, pig, grunter, squealer, Sus scrofa',
603 | 342: 'wild boar, boar, Sus scrofa',
604 | 343: 'warthog',
605 | 344: 'hippopotamus, hippo, river horse, Hippopotamus amphibius',
606 | 345: 'ox',
607 | 346: 'water buffalo, water ox, Asiatic buffalo, Bubalus bubalis',
608 | 347: 'bison',
609 | 348: 'ram, tup',
610 | 349: 'bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky ' +
611 | 'Mountain sheep, Ovis canadensis',
612 | 350: 'ibex, Capra ibex',
613 | 351: 'hartebeest',
614 | 352: 'impala, Aepyceros melampus',
615 | 353: 'gazelle',
616 | 354: 'Arabian camel, dromedary, Camelus dromedarius',
617 | 355: 'llama',
618 | 356: 'weasel',
619 | 357: 'mink',
620 | 358: 'polecat, fitch, foulmart, foumart, Mustela putorius',
621 | 359: 'black-footed ferret, ferret, Mustela nigripes',
622 | 360: 'otter',
623 | 361: 'skunk, polecat, wood pussy',
624 | 362: 'badger',
625 | 363: 'armadillo',
626 | 364: 'three-toed sloth, ai, Bradypus tridactylus',
627 | 365: 'orangutan, orang, orangutang, Pongo pygmaeus',
628 | 366: 'gorilla, Gorilla gorilla',
629 | 367: 'chimpanzee, chimp, Pan troglodytes',
630 | 368: 'gibbon, Hylobates lar',
631 | 369: 'siamang, Hylobates syndactylus, Symphalangus syndactylus',
632 | 370: 'guenon, guenon monkey',
633 | 371: 'patas, hussar monkey, Erythrocebus patas',
634 | 372: 'baboon',
635 | 373: 'macaque',
636 | 374: 'langur',
637 | 375: 'colobus, colobus monkey',
638 | 376: 'proboscis monkey, Nasalis larvatus',
639 | 377: 'marmoset',
640 | 378: 'capuchin, ringtail, Cebus capucinus',
641 | 379: 'howler monkey, howler',
642 | 380: 'titi, titi monkey',
643 | 381: 'spider monkey, Ateles geoffroyi',
644 | 382: 'squirrel monkey, Saimiri sciureus',
645 | 383: 'Madagascar cat, ring-tailed lemur, Lemur catta',
646 | 384: 'indri, indris, Indri indri, Indri brevicaudatus',
647 | 385: 'Indian elephant, Elephas maximus',
648 | 386: 'African elephant, Loxodonta africana',
649 | 387: 'lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens',
650 | 388: 'giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca',
651 | 389: 'barracouta, snoek',
652 | 390: 'eel',
653 | 391: 'coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus ' +
654 | 'kisutch',
655 | 392: 'rock beauty, Holocanthus tricolor',
656 | 393: 'anemone fish',
657 | 394: 'sturgeon',
658 | 395: 'gar, garfish, garpike, billfish, Lepisosteus osseus',
659 | 396: 'lionfish',
660 | 397: 'puffer, pufferfish, blowfish, globefish',
661 | 398: 'abacus',
662 | 399: 'abaya',
663 | 400: 'academic gown, academic robe, judge\'s robe',
664 | 401: 'accordion, piano accordion, squeeze box',
665 | 402: 'acoustic guitar',
666 | 403: 'aircraft carrier, carrier, flattop, attack aircraft carrier',
667 | 404: 'airliner',
668 | 405: 'airship, dirigible',
669 | 406: 'altar',
670 | 407: 'ambulance',
671 | 408: 'amphibian, amphibious vehicle',
672 | 409: 'analog clock',
673 | 410: 'apiary, bee house',
674 | 411: 'apron',
675 | 412: 'ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, ' +
676 | 'dustbin, trash barrel, trash bin',
677 | 413: 'assault rifle, assault gun',
678 | 414: 'backpack, back pack, knapsack, packsack, rucksack, haversack',
679 | 415: 'bakery, bakeshop, bakehouse',
680 | 416: 'balance beam, beam',
681 | 417: 'balloon',
682 | 418: 'ballpoint, ballpoint pen, ballpen, Biro',
683 | 419: 'Band Aid',
684 | 420: 'banjo',
685 | 421: 'bannister, banister, balustrade, balusters, handrail',
686 | 422: 'barbell',
687 | 423: 'barber chair',
688 | 424: 'barbershop',
689 | 425: 'barn',
690 | 426: 'barometer',
691 | 427: 'barrel, cask',
692 | 428: 'barrow, garden cart, lawn cart, wheelbarrow',
693 | 429: 'baseball',
694 | 430: 'basketball',
695 | 431: 'bassinet',
696 | 432: 'bassoon',
697 | 433: 'bathing cap, swimming cap',
698 | 434: 'bath towel',
699 | 435: 'bathtub, bathing tub, bath, tub',
700 | 436: 'beach wagon, station wagon, wagon, estate car, beach waggon, station ' +
701 | 'waggon, waggon',
702 | 437: 'beacon, lighthouse, beacon light, pharos',
703 | 438: 'beaker',
704 | 439: 'bearskin, busby, shako',
705 | 440: 'beer bottle',
706 | 441: 'beer glass',
707 | 442: 'bell cote, bell cot',
708 | 443: 'bib',
709 | 444: 'bicycle-built-for-two, tandem bicycle, tandem',
710 | 445: 'bikini, two-piece',
711 | 446: 'binder, ring-binder',
712 | 447: 'binoculars, field glasses, opera glasses',
713 | 448: 'birdhouse',
714 | 449: 'boathouse',
715 | 450: 'bobsled, bobsleigh, bob',
716 | 451: 'bolo tie, bolo, bola tie, bola',
717 | 452: 'bonnet, poke bonnet',
718 | 453: 'bookcase',
719 | 454: 'bookshop, bookstore, bookstall',
720 | 455: 'bottlecap',
721 | 456: 'bow',
722 | 457: 'bow tie, bow-tie, bowtie',
723 | 458: 'brass, memorial tablet, plaque',
724 | 459: 'brassiere, bra, bandeau',
725 | 460: 'breakwater, groin, groyne, mole, bulwark, seawall, jetty',
726 | 461: 'breastplate, aegis, egis',
727 | 462: 'broom',
728 | 463: 'bucket, pail',
729 | 464: 'buckle',
730 | 465: 'bulletproof vest',
731 | 466: 'bullet train, bullet',
732 | 467: 'butcher shop, meat market',
733 | 468: 'cab, hack, taxi, taxicab',
734 | 469: 'caldron, cauldron',
735 | 470: 'candle, taper, wax light',
736 | 471: 'cannon',
737 | 472: 'canoe',
738 | 473: 'can opener, tin opener',
739 | 474: 'cardigan',
740 | 475: 'car mirror',
741 | 476: 'carousel, carrousel, merry-go-round, roundabout, whirligig',
742 | 477: 'carpenter\'s kit, tool kit',
743 | 478: 'carton',
744 | 479: 'car wheel',
745 | 480: 'cash machine, cash dispenser, automated teller machine, automatic ' +
746 | 'teller machine, automated teller, automatic teller, ATM',
747 | 481: 'cassette',
748 | 482: 'cassette player',
749 | 483: 'castle',
750 | 484: 'catamaran',
751 | 485: 'CD player',
752 | 486: 'cello, violoncello',
753 | 487: 'cellular telephone, cellular phone, cellphone, cell, mobile phone',
754 | 488: 'chain',
755 | 489: 'chainlink fence',
756 | 490: 'chain mail, ring mail, mail, chain armor, chain armour, ring armor, ' +
757 | 'ring armour',
758 | 491: 'chain saw, chainsaw',
759 | 492: 'chest',
760 | 493: 'chiffonier, commode',
761 | 494: 'chime, bell, gong',
762 | 495: 'china cabinet, china closet',
763 | 496: 'Christmas stocking',
764 | 497: 'church, church building',
765 | 498: 'cinema, movie theater, movie theatre, movie house, picture palace',
766 | 499: 'cleaver, meat cleaver, chopper',
767 | 500: 'cliff dwelling',
768 | 501: 'cloak',
769 | 502: 'clog, geta, patten, sabot',
770 | 503: 'cocktail shaker',
771 | 504: 'coffee mug',
772 | 505: 'coffeepot',
773 | 506: 'coil, spiral, volute, whorl, helix',
774 | 507: 'combination lock',
775 | 508: 'computer keyboard, keypad',
776 | 509: 'confectionery, confectionary, candy store',
777 | 510: 'container ship, containership, container vessel',
778 | 511: 'convertible',
779 | 512: 'corkscrew, bottle screw',
780 | 513: 'cornet, horn, trumpet, trump',
781 | 514: 'cowboy boot',
782 | 515: 'cowboy hat, ten-gallon hat',
783 | 516: 'cradle',
784 | 517: 'crane',
785 | 518: 'crash helmet',
786 | 519: 'crate',
787 | 520: 'crib, cot',
788 | 521: 'Crock Pot',
789 | 522: 'croquet ball',
790 | 523: 'crutch',
791 | 524: 'cuirass',
792 | 525: 'dam, dike, dyke',
793 | 526: 'desk',
794 | 527: 'desktop computer',
795 | 528: 'dial telephone, dial phone',
796 | 529: 'diaper, nappy, napkin',
797 | 530: 'digital clock',
798 | 531: 'digital watch',
799 | 532: 'dining table, board',
800 | 533: 'dishrag, dishcloth',
801 | 534: 'dishwasher, dish washer, dishwashing machine',
802 | 535: 'disk brake, disc brake',
803 | 536: 'dock, dockage, docking facility',
804 | 537: 'dogsled, dog sled, dog sleigh',
805 | 538: 'dome',
806 | 539: 'doormat, welcome mat',
807 | 540: 'drilling platform, offshore rig',
808 | 541: 'drum, membranophone, tympan',
809 | 542: 'drumstick',
810 | 543: 'dumbbell',
811 | 544: 'Dutch oven',
812 | 545: 'electric fan, blower',
813 | 546: 'electric guitar',
814 | 547: 'electric locomotive',
815 | 548: 'entertainment center',
816 | 549: 'envelope',
817 | 550: 'espresso maker',
818 | 551: 'face powder',
819 | 552: 'feather boa, boa',
820 | 553: 'file, file cabinet, filing cabinet',
821 | 554: 'fireboat',
822 | 555: 'fire engine, fire truck',
823 | 556: 'fire screen, fireguard',
824 | 557: 'flagpole, flagstaff',
825 | 558: 'flute, transverse flute',
826 | 559: 'folding chair',
827 | 560: 'football helmet',
828 | 561: 'forklift',
829 | 562: 'fountain',
830 | 563: 'fountain pen',
831 | 564: 'four-poster',
832 | 565: 'freight car',
833 | 566: 'French horn, horn',
834 | 567: 'frying pan, frypan, skillet',
835 | 568: 'fur coat',
836 | 569: 'garbage truck, dustcart',
837 | 570: 'gasmask, respirator, gas helmet',
838 | 571: 'gas pump, gasoline pump, petrol pump, island dispenser',
839 | 572: 'goblet',
840 | 573: 'go-kart',
841 | 574: 'golf ball',
842 | 575: 'golfcart, golf cart',
843 | 576: 'gondola',
844 | 577: 'gong, tam-tam',
845 | 578: 'gown',
846 | 579: 'grand piano, grand',
847 | 580: 'greenhouse, nursery, glasshouse',
848 | 581: 'grille, radiator grille',
849 | 582: 'grocery store, grocery, food market, market',
850 | 583: 'guillotine',
851 | 584: 'hair slide',
852 | 585: 'hair spray',
853 | 586: 'half track',
854 | 587: 'hammer',
855 | 588: 'hamper',
856 | 589: 'hand blower, blow dryer, blow drier, hair dryer, hair drier',
857 | 590: 'hand-held computer, hand-held microcomputer',
858 | 591: 'handkerchief, hankie, hanky, hankey',
859 | 592: 'hard disc, hard disk, fixed disk',
860 | 593: 'harmonica, mouth organ, harp, mouth harp',
861 | 594: 'harp',
862 | 595: 'harvester, reaper',
863 | 596: 'hatchet',
864 | 597: 'holster',
865 | 598: 'home theater, home theatre',
866 | 599: 'honeycomb',
867 | 600: 'hook, claw',
868 | 601: 'hoopskirt, crinoline',
869 | 602: 'horizontal bar, high bar',
870 | 603: 'horse cart, horse-cart',
871 | 604: 'hourglass',
872 | 605: 'iPod',
873 | 606: 'iron, smoothing iron',
874 | 607: 'jack-o\'-lantern',
875 | 608: 'jean, blue jean, denim',
876 | 609: 'jeep, landrover',
877 | 610: 'jersey, T-shirt, tee shirt',
878 | 611: 'jigsaw puzzle',
879 | 612: 'jinrikisha, ricksha, rickshaw',
880 | 613: 'joystick',
881 | 614: 'kimono',
882 | 615: 'knee pad',
883 | 616: 'knot',
884 | 617: 'lab coat, laboratory coat',
885 | 618: 'ladle',
886 | 619: 'lampshade, lamp shade',
887 | 620: 'laptop, laptop computer',
888 | 621: 'lawn mower, mower',
889 | 622: 'lens cap, lens cover',
890 | 623: 'letter opener, paper knife, paperknife',
891 | 624: 'library',
892 | 625: 'lifeboat',
893 | 626: 'lighter, light, igniter, ignitor',
894 | 627: 'limousine, limo',
895 | 628: 'liner, ocean liner',
896 | 629: 'lipstick, lip rouge',
897 | 630: 'Loafer',
898 | 631: 'lotion',
899 | 632: 'loudspeaker, speaker, speaker unit, loudspeaker system, speaker ' +
900 | 'system',
901 | 633: 'loupe, jeweler\'s loupe',
902 | 634: 'lumbermill, sawmill',
903 | 635: 'magnetic compass',
904 | 636: 'mailbag, postbag',
905 | 637: 'mailbox, letter box',
906 | 638: 'maillot',
907 | 639: 'maillot, tank suit',
908 | 640: 'manhole cover',
909 | 641: 'maraca',
910 | 642: 'marimba, xylophone',
911 | 643: 'mask',
912 | 644: 'matchstick',
913 | 645: 'maypole',
914 | 646: 'maze, labyrinth',
915 | 647: 'measuring cup',
916 | 648: 'medicine chest, medicine cabinet',
917 | 649: 'megalith, megalithic structure',
918 | 650: 'microphone, mike',
919 | 651: 'microwave, microwave oven',
920 | 652: 'military uniform',
921 | 653: 'milk can',
922 | 654: 'minibus',
923 | 655: 'miniskirt, mini',
924 | 656: 'minivan',
925 | 657: 'missile',
926 | 658: 'mitten',
927 | 659: 'mixing bowl',
928 | 660: 'mobile home, manufactured home',
929 | 661: 'Model T',
930 | 662: 'modem',
931 | 663: 'monastery',
932 | 664: 'monitor',
933 | 665: 'moped',
934 | 666: 'mortar',
935 | 667: 'mortarboard',
936 | 668: 'mosque',
937 | 669: 'mosquito net',
938 | 670: 'motor scooter, scooter',
939 | 671: 'mountain bike, all-terrain bike, off-roader',
940 | 672: 'mountain tent',
941 | 673: 'mouse, computer mouse',
942 | 674: 'mousetrap',
943 | 675: 'moving van',
944 | 676: 'muzzle',
945 | 677: 'nail',
946 | 678: 'neck brace',
947 | 679: 'necklace',
948 | 680: 'nipple',
949 | 681: 'notebook, notebook computer',
950 | 682: 'obelisk',
951 | 683: 'oboe, hautboy, hautbois',
952 | 684: 'ocarina, sweet potato',
953 | 685: 'odometer, hodometer, mileometer, milometer',
954 | 686: 'oil filter',
955 | 687: 'organ, pipe organ',
956 | 688: 'oscilloscope, scope, cathode-ray oscilloscope, CRO',
957 | 689: 'overskirt',
958 | 690: 'oxcart',
959 | 691: 'oxygen mask',
960 | 692: 'packet',
961 | 693: 'paddle, boat paddle',
962 | 694: 'paddlewheel, paddle wheel',
963 | 695: 'padlock',
964 | 696: 'paintbrush',
965 | 697: 'pajama, pyjama, pj\'s, jammies',
966 | 698: 'palace',
967 | 699: 'panpipe, pandean pipe, syrinx',
968 | 700: 'paper towel',
969 | 701: 'parachute, chute',
970 | 702: 'parallel bars, bars',
971 | 703: 'park bench',
972 | 704: 'parking meter',
973 | 705: 'passenger car, coach, carriage',
974 | 706: 'patio, terrace',
975 | 707: 'pay-phone, pay-station',
976 | 708: 'pedestal, plinth, footstall',
977 | 709: 'pencil box, pencil case',
978 | 710: 'pencil sharpener',
979 | 711: 'perfume, essence',
980 | 712: 'Petri dish',
981 | 713: 'photocopier',
982 | 714: 'pick, plectrum, plectron',
983 | 715: 'pickelhaube',
984 | 716: 'picket fence, paling',
985 | 717: 'pickup, pickup truck',
986 | 718: 'pier',
987 | 719: 'piggy bank, penny bank',
988 | 720: 'pill bottle',
989 | 721: 'pillow',
990 | 722: 'ping-pong ball',
991 | 723: 'pinwheel',
992 | 724: 'pirate, pirate ship',
993 | 725: 'pitcher, ewer',
994 | 726: 'plane, carpenter\'s plane, woodworking plane',
995 | 727: 'planetarium',
996 | 728: 'plastic bag',
997 | 729: 'plate rack',
998 | 730: 'plow, plough',
999 | 731: 'plunger, plumber\'s helper',
1000 | 732: 'Polaroid camera, Polaroid Land camera',
1001 | 733: 'pole',
1002 | 734: 'police van, police wagon, paddy wagon, patrol wagon, wagon, black ' +
1003 | 'Maria',
1004 | 735: 'poncho',
1005 | 736: 'pool table, billiard table, snooker table',
1006 | 737: 'pop bottle, soda bottle',
1007 | 738: 'pot, flowerpot',
1008 | 739: 'potter\'s wheel',
1009 | 740: 'power drill',
1010 | 741: 'prayer rug, prayer mat',
1011 | 742: 'printer',
1012 | 743: 'prison, prison house',
1013 | 744: 'projectile, missile',
1014 | 745: 'projector',
1015 | 746: 'puck, hockey puck',
1016 | 747: 'punching bag, punch bag, punching ball, punchball',
1017 | 748: 'purse',
1018 | 749: 'quill, quill pen',
1019 | 750: 'quilt, comforter, comfort, puff',
1020 | 751: 'racer, race car, racing car',
1021 | 752: 'racket, racquet',
1022 | 753: 'radiator',
1023 | 754: 'radio, wireless',
1024 | 755: 'radio telescope, radio reflector',
1025 | 756: 'rain barrel',
1026 | 757: 'recreational vehicle, RV, R.V.',
1027 | 758: 'reel',
1028 | 759: 'reflex camera',
1029 | 760: 'refrigerator, icebox',
1030 | 761: 'remote control, remote',
1031 | 762: 'restaurant, eating house, eating place, eatery',
1032 | 763: 'revolver, six-gun, six-shooter',
1033 | 764: 'rifle',
1034 | 765: 'rocking chair, rocker',
1035 | 766: 'rotisserie',
1036 | 767: 'rubber eraser, rubber, pencil eraser',
1037 | 768: 'rugby ball',
1038 | 769: 'rule, ruler',
1039 | 770: 'running shoe',
1040 | 771: 'safe',
1041 | 772: 'safety pin',
1042 | 773: 'saltshaker, salt shaker',
1043 | 774: 'sandal',
1044 | 775: 'sarong',
1045 | 776: 'sax, saxophone',
1046 | 777: 'scabbard',
1047 | 778: 'scale, weighing machine',
1048 | 779: 'school bus',
1049 | 780: 'schooner',
1050 | 781: 'scoreboard',
1051 | 782: 'screen, CRT screen',
1052 | 783: 'screw',
1053 | 784: 'screwdriver',
1054 | 785: 'seat belt, seatbelt',
1055 | 786: 'sewing machine',
1056 | 787: 'shield, buckler',
1057 | 788: 'shoe shop, shoe-shop, shoe store',
1058 | 789: 'shoji',
1059 | 790: 'shopping basket',
1060 | 791: 'shopping cart',
1061 | 792: 'shovel',
1062 | 793: 'shower cap',
1063 | 794: 'shower curtain',
1064 | 795: 'ski',
1065 | 796: 'ski mask',
1066 | 797: 'sleeping bag',
1067 | 798: 'slide rule, slipstick',
1068 | 799: 'sliding door',
1069 | 800: 'slot, one-armed bandit',
1070 | 801: 'snorkel',
1071 | 802: 'snowmobile',
1072 | 803: 'snowplow, snowplough',
1073 | 804: 'soap dispenser',
1074 | 805: 'soccer ball',
1075 | 806: 'sock',
1076 | 807: 'solar dish, solar collector, solar furnace',
1077 | 808: 'sombrero',
1078 | 809: 'soup bowl',
1079 | 810: 'space bar',
1080 | 811: 'space heater',
1081 | 812: 'space shuttle',
1082 | 813: 'spatula',
1083 | 814: 'speedboat',
1084 | 815: 'spider web, spider\'s web',
1085 | 816: 'spindle',
1086 | 817: 'sports car, sport car',
1087 | 818: 'spotlight, spot',
1088 | 819: 'stage',
1089 | 820: 'steam locomotive',
1090 | 821: 'steel arch bridge',
1091 | 822: 'steel drum',
1092 | 823: 'stethoscope',
1093 | 824: 'stole',
1094 | 825: 'stone wall',
1095 | 826: 'stopwatch, stop watch',
1096 | 827: 'stove',
1097 | 828: 'strainer',
1098 | 829: 'streetcar, tram, tramcar, trolley, trolley car',
1099 | 830: 'stretcher',
1100 | 831: 'studio couch, day bed',
1101 | 832: 'stupa, tope',
1102 | 833: 'submarine, pigboat, sub, U-boat',
1103 | 834: 'suit, suit of clothes',
1104 | 835: 'sundial',
1105 | 836: 'sunglass',
1106 | 837: 'sunglasses, dark glasses, shades',
1107 | 838: 'sunscreen, sunblock, sun blocker',
1108 | 839: 'suspension bridge',
1109 | 840: 'swab, swob, mop',
1110 | 841: 'sweatshirt',
1111 | 842: 'swimming trunks, bathing trunks',
1112 | 843: 'swing',
1113 | 844: 'switch, electric switch, electrical switch',
1114 | 845: 'syringe',
1115 | 846: 'table lamp',
1116 | 847: 'tank, army tank, armored combat vehicle, armoured combat vehicle',
1117 | 848: 'tape player',
1118 | 849: 'teapot',
1119 | 850: 'teddy, teddy bear',
1120 | 851: 'television, television system',
1121 | 852: 'tennis ball',
1122 | 853: 'thatch, thatched roof',
1123 | 854: 'theater curtain, theatre curtain',
1124 | 855: 'thimble',
1125 | 856: 'thresher, thrasher, threshing machine',
1126 | 857: 'throne',
1127 | 858: 'tile roof',
1128 | 859: 'toaster',
1129 | 860: 'tobacco shop, tobacconist shop, tobacconist',
1130 | 861: 'toilet seat',
1131 | 862: 'torch',
1132 | 863: 'totem pole',
1133 | 864: 'tow truck, tow car, wrecker',
1134 | 865: 'toyshop',
1135 | 866: 'tractor',
1136 | 867: 'trailer truck, tractor trailer, trucking rig, rig, articulated ' +
1137 | 'lorry, semi',
1138 | 868: 'tray',
1139 | 869: 'trench coat',
1140 | 870: 'tricycle, trike, velocipede',
1141 | 871: 'trimaran',
1142 | 872: 'tripod',
1143 | 873: 'triumphal arch',
1144 | 874: 'trolleybus, trolley coach, trackless trolley',
1145 | 875: 'trombone',
1146 | 876: 'tub, vat',
1147 | 877: 'turnstile',
1148 | 878: 'typewriter keyboard',
1149 | 879: 'umbrella',
1150 | 880: 'unicycle, monocycle',
1151 | 881: 'upright, upright piano',
1152 | 882: 'vacuum, vacuum cleaner',
1153 | 883: 'vase',
1154 | 884: 'vault',
1155 | 885: 'velvet',
1156 | 886: 'vending machine',
1157 | 887: 'vestment',
1158 | 888: 'viaduct',
1159 | 889: 'violin, fiddle',
1160 | 890: 'volleyball',
1161 | 891: 'waffle iron',
1162 | 892: 'wall clock',
1163 | 893: 'wallet, billfold, notecase, pocketbook',
1164 | 894: 'wardrobe, closet, press',
1165 | 895: 'warplane, military plane',
1166 | 896: 'washbasin, handbasin, washbowl, lavabo, wash-hand basin',
1167 | 897: 'washer, automatic washer, washing machine',
1168 | 898: 'water bottle',
1169 | 899: 'water jug',
1170 | 900: 'water tower',
1171 | 901: 'whiskey jug',
1172 | 902: 'whistle',
1173 | 903: 'wig',
1174 | 904: 'window screen',
1175 | 905: 'window shade',
1176 | 906: 'Windsor tie',
1177 | 907: 'wine bottle',
1178 | 908: 'wing',
1179 | 909: 'wok',
1180 | 910: 'wooden spoon',
1181 | 911: 'wool, woolen, woollen',
1182 | 912: 'worm fence, snake fence, snake-rail fence, Virginia fence',
1183 | 913: 'wreck',
1184 | 914: 'yawl',
1185 | 915: 'yurt',
1186 | 916: 'web site, website, internet site, site',
1187 | 917: 'comic book',
1188 | 918: 'crossword puzzle, crossword',
1189 | 919: 'street sign',
1190 | 920: 'traffic light, traffic signal, stoplight',
1191 | 921: 'book jacket, dust cover, dust jacket, dust wrapper',
1192 | 922: 'menu',
1193 | 923: 'plate',
1194 | 924: 'guacamole',
1195 | 925: 'consomme',
1196 | 926: 'hot pot, hotpot',
1197 | 927: 'trifle',
1198 | 928: 'ice cream, icecream',
1199 | 929: 'ice lolly, lolly, lollipop, popsicle',
1200 | 930: 'French loaf',
1201 | 931: 'bagel, beigel',
1202 | 932: 'pretzel',
1203 | 933: 'cheeseburger',
1204 | 934: 'hotdog, hot dog, red hot',
1205 | 935: 'mashed potato',
1206 | 936: 'head cabbage',
1207 | 937: 'broccoli',
1208 | 938: 'cauliflower',
1209 | 939: 'zucchini, courgette',
1210 | 940: 'spaghetti squash',
1211 | 941: 'acorn squash',
1212 | 942: 'butternut squash',
1213 | 943: 'cucumber, cuke',
1214 | 944: 'artichoke, globe artichoke',
1215 | 945: 'bell pepper',
1216 | 946: 'cardoon',
1217 | 947: 'mushroom',
1218 | 948: 'Granny Smith',
1219 | 949: 'strawberry',
1220 | 950: 'orange',
1221 | 951: 'lemon',
1222 | 952: 'fig',
1223 | 953: 'pineapple, ananas',
1224 | 954: 'banana',
1225 | 955: 'jackfruit, jak, jack',
1226 | 956: 'custard apple',
1227 | 957: 'pomegranate',
1228 | 958: 'hay',
1229 | 959: 'carbonara',
1230 | 960: 'chocolate sauce, chocolate syrup',
1231 | 961: 'dough',
1232 | 962: 'meat loaf, meatloaf',
1233 | 963: 'pizza, pizza pie',
1234 | 964: 'potpie',
1235 | 965: 'burrito',
1236 | 966: 'red wine',
1237 | 967: 'espresso',
1238 | 968: 'cup',
1239 | 969: 'eggnog',
1240 | 970: 'alp',
1241 | 971: 'bubble',
1242 | 972: 'cliff, drop, drop-off',
1243 | 973: 'coral reef',
1244 | 974: 'geyser',
1245 | 975: 'lakeside, lakeshore',
1246 | 976: 'promontory, headland, head, foreland',
1247 | 977: 'sandbar, sand bar',
1248 | 978: 'seashore, coast, seacoast, sea-coast',
1249 | 979: 'valley, vale',
1250 | 980: 'volcano',
1251 | 981: 'ballplayer, baseball player',
1252 | 982: 'groom, bridegroom',
1253 | 983: 'scuba diver',
1254 | 984: 'rapeseed',
1255 | 985: 'daisy',
1256 | 986: 'yellow lady\'s slipper, yellow lady-slipper, Cypripedium calceolus, ' +
1257 | 'Cypripedium parviflorum',
1258 | 987: 'corn',
1259 | 988: 'acorn',
1260 | 989: 'hip, rose hip, rosehip',
1261 | 990: 'buckeye, horse chestnut, conker',
1262 | 991: 'coral fungus',
1263 | 992: 'agaric',
1264 | 993: 'gyromitra',
1265 | 994: 'stinkhorn, carrion fungus',
1266 | 995: 'earthstar',
1267 | 996: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola ' +
1268 | 'frondosa',
1269 | 997: 'bolete',
1270 | 998: 'ear, spike, capitulum',
1271 | 999: 'toilet tissue, toilet paper, bathroom tissue'
1272 | };
1273 |
1274 | },{}],4:[function(require,module,exports){
1275 | "use strict";
1276 | Object.defineProperty(exports, "__esModule", { value: true });
1277 | var squeezenet_1 = require("./squeezenet");
1278 | exports.SqueezeNet = squeezenet_1.SqueezeNet;
1279 |
1280 | },{"./squeezenet":5}],5:[function(require,module,exports){
1281 | (function (global){
1282 | "use strict";
1283 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1284 | return new (P || (P = Promise))(function (resolve, reject) {
1285 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1286 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1287 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
1288 | step((generator = generator.apply(thisArg, _arguments || [])).next());
1289 | });
1290 | };
1291 | var __generator = (this && this.__generator) || function (thisArg, body) {
1292 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
1293 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
1294 | function verb(n) { return function (v) { return step([n, v]); }; }
1295 | function step(op) {
1296 | if (f) throw new TypeError("Generator is already executing.");
1297 | while (_) try {
1298 | if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
1299 | if (y = 0, t) op = [0, t.value];
1300 | switch (op[0]) {
1301 | case 0: case 1: t = op; break;
1302 | case 4: _.label++; return { value: op[1], done: false };
1303 | case 5: _.label++; y = op[1]; op = [0]; continue;
1304 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
1305 | default:
1306 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
1307 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
1308 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
1309 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
1310 | if (t[2]) _.ops.pop();
1311 | _.trys.pop(); continue;
1312 | }
1313 | op = body.call(thisArg, _);
1314 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
1315 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
1316 | }
1317 | };
1318 | Object.defineProperty(exports, "__esModule", { value: true });
1319 | var dl = (typeof window !== "undefined" ? window['dl'] : typeof global !== "undefined" ? global['dl'] : null);
1320 | var model_util = require("../util");
1321 | var imagenet_classes_1 = require("./imagenet_classes");
1322 | var GOOGLE_CLOUD_STORAGE_DIR = 'https://storage.googleapis.com/learnjs-data/checkpoint_zoo/';
1323 | var SqueezeNet = (function () {
1324 | function SqueezeNet() {
1325 | this.preprocessOffset = dl.tensor1d([103.939, 116.779, 123.68]);
1326 | }
1327 | SqueezeNet.prototype.load = function () {
1328 | return __awaiter(this, void 0, void 0, function () {
1329 | var checkpointLoader, _a;
1330 | return __generator(this, function (_b) {
1331 | switch (_b.label) {
1332 | case 0:
1333 | checkpointLoader = new dl.CheckpointLoader(GOOGLE_CLOUD_STORAGE_DIR + 'squeezenet1_1/');
1334 | _a = this;
1335 | return [4, checkpointLoader.getAllVariables()];
1336 | case 1:
1337 | _a.variables = _b.sent();
1338 | return [2];
1339 | }
1340 | });
1341 | });
1342 | };
1343 | SqueezeNet.prototype.predict = function (input) {
1344 | return this.predictWithActivation(input).logits;
1345 | };
1346 | SqueezeNet.prototype.predictWithActivation = function (input, activationName) {
1347 | var _this = this;
1348 | return dl.tidy(function () {
1349 | var activation;
1350 | var preprocessedInput = dl.sub(input.asType('float32'), _this.preprocessOffset);
1351 | var conv1relu = preprocessedInput
1352 | .conv2d(_this.variables['conv1_W:0'], 2, 0)
1353 | .add(_this.variables['conv1_b:0'])
1354 | .relu();
1355 | if (activationName === 'conv_1') {
1356 | activation = conv1relu;
1357 | }
1358 | var pool1 = conv1relu.maxPool(3, 2, 0);
1359 | if (activationName === 'maxpool_1') {
1360 | activation = pool1;
1361 | }
1362 | var fire2 = _this.fireModule(pool1, 2);
1363 | if (activationName === 'fire2') {
1364 | activation = fire2;
1365 | }
1366 | var fire3 = _this.fireModule(fire2, 3);
1367 | if (activationName === 'fire3') {
1368 | activation = fire3;
1369 | }
1370 | var pool2 = fire3.maxPool(3, 2, 'valid');
1371 | if (activationName === 'maxpool_2') {
1372 | activation = pool2;
1373 | }
1374 | var fire4 = _this.fireModule(pool2, 4);
1375 | if (activationName === 'fire4') {
1376 | activation = fire4;
1377 | }
1378 | var fire5 = _this.fireModule(fire4, 5);
1379 | if (activationName === 'fire5') {
1380 | activation = fire5;
1381 | }
1382 | var pool3 = fire5.maxPool(3, 2, 0);
1383 | if (activationName === 'maxpool_3') {
1384 | activation = pool3;
1385 | }
1386 | var fire6 = _this.fireModule(pool3, 6);
1387 | if (activationName === 'fire6') {
1388 | activation = fire6;
1389 | }
1390 | var fire7 = _this.fireModule(fire6, 7);
1391 | if (activationName === 'fire7') {
1392 | activation = fire7;
1393 | }
1394 | var fire8 = _this.fireModule(fire7, 8);
1395 | if (activationName === 'fire8') {
1396 | activation = fire8;
1397 | }
1398 | var fire9 = _this.fireModule(fire8, 9);
1399 | if (activationName === 'fire9') {
1400 | activation = fire9;
1401 | }
1402 | var conv10 = fire9.conv2d(_this.variables['conv10_W:0'], 1, 0)
1403 | .add(_this.variables['conv10_b:0']);
1404 | if (activationName === 'conv10') {
1405 | activation = conv10;
1406 | }
1407 | return {
1408 | logits: dl.avgPool(conv10, conv10.shape[0], 1, 0).as1D(),
1409 | activation: activation
1410 | };
1411 | });
1412 | };
1413 | SqueezeNet.prototype.fireModule = function (input, fireId) {
1414 | var y = dl.conv2d(input, this.variables["fire" + fireId + "/squeeze1x1_W:0"], 1, 0)
1415 | .add(this.variables["fire" + fireId + "/squeeze1x1_b:0"])
1416 | .relu();
1417 | var left = dl.conv2d(y, this.variables["fire" + fireId + "/expand1x1_W:0"], 1, 0)
1418 | .add(this.variables["fire" + fireId + "/expand1x1_b:0"])
1419 | .relu();
1420 | var right = dl.conv2d(y, this.variables["fire" + fireId + "/expand3x3_W:0"], 1, 1)
1421 | .add(this.variables["fire" + fireId + "/expand3x3_b:0"])
1422 | .relu();
1423 | return left.concat(right, 2);
1424 | };
1425 | SqueezeNet.prototype.getTopKClasses = function (logits, topK) {
1426 | return __awaiter(this, void 0, void 0, function () {
1427 | var predictions, topk, _a, _b, topkIndices, topkValues, topClassesToProbability, i;
1428 | return __generator(this, function (_c) {
1429 | switch (_c.label) {
1430 | case 0:
1431 | predictions = dl.tidy(function () {
1432 | return dl.softmax(logits).asType('float32');
1433 | });
1434 | _b = (_a = model_util).topK;
1435 | return [4, predictions.data()];
1436 | case 1:
1437 | topk = _b.apply(_a, [_c.sent(), topK]);
1438 | predictions.dispose();
1439 | topkIndices = topk.indices;
1440 | topkValues = topk.values;
1441 | topClassesToProbability = {};
1442 | for (i = 0; i < topkIndices.length; i++) {
1443 | topClassesToProbability[imagenet_classes_1.IMAGENET_CLASSES[topkIndices[i]]] = topkValues[i];
1444 | }
1445 | return [2, topClassesToProbability];
1446 | }
1447 | });
1448 | });
1449 | };
1450 | SqueezeNet.prototype.dispose = function () {
1451 | this.preprocessOffset.dispose();
1452 | for (var varName in this.variables) {
1453 | this.variables[varName].dispose();
1454 | }
1455 | };
1456 | return SqueezeNet;
1457 | }());
1458 | exports.SqueezeNet = SqueezeNet;
1459 |
1460 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1461 | },{"../util":6,"./imagenet_classes":3}],6:[function(require,module,exports){
1462 | "use strict";
1463 | Object.defineProperty(exports, "__esModule", { value: true });
1464 | function topK(values, k) {
1465 | var valuesAndIndices = [];
1466 | for (var i = 0; i < values.length; i++) {
1467 | valuesAndIndices.push({ value: values[i], index: i });
1468 | }
1469 | valuesAndIndices.sort(function (a, b) {
1470 | return b.value - a.value;
1471 | });
1472 | var topkValues = new Float32Array(k);
1473 | var topkIndices = new Int32Array(k);
1474 | for (var i = 0; i < k; i++) {
1475 | topkValues[i] = valuesAndIndices[i].value;
1476 | topkIndices[i] = valuesAndIndices[i].index;
1477 | }
1478 | return { values: topkValues, indices: topkIndices };
1479 | }
1480 | exports.topK = topK;
1481 |
1482 | },{}],7:[function(require,module,exports){
1483 | arguments[4][6][0].apply(exports,arguments)
1484 | },{"dup":6}]},{},[1])(1)
1485 | });
--------------------------------------------------------------------------------
/welcome.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
Please grant the browser access to the webcam to use this extension
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/welcome.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | navigator.mediaDevices.getUserMedia({
17 | video: true
18 | }).then(stream => {
19 | document.querySelector('#status').innerHTML =
20 | 'Webcam access granted for extension, please close this tab';
21 | chrome.storage.local.set({
22 | 'camAccess': true
23 | }, () => {});
24 | })
25 | .catch(err => {
26 | document.querySelector('#status').innerHTML =
27 | 'Error getting webcam access for extension: ' + err.toString();
28 | console.error(err);
29 | });
30 |
--------------------------------------------------------------------------------