-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Chrome browser plugin deployment example (mobilenet) #285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 1 approvals obtained (waiting on @caisq and @tafsiri)
deployment-examples/README.md, line 12 at r1 (raw file):
TODO(bileschi) :
Improve readme.
deployment-examples/browser-plugin/README.md, line 5 at r1 (raw file):
"copy": "cp src/content.js dist/src/ && cp src/imagenet_classes.js dist/src/",
Improve readme. Add build & installation instructions.
deployment-examples/browser-plugin/src/background.js, line 1 at r1 (raw file):
import 'babel-polyfill';
Needs license
deployment-examples/browser-plugin/src/background.js, line 7 at r1 (raw file):
// Where to load the model from. const MOBILENET_MODEL_PATH = 'https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json'; const IMAGE_SIZE = 224;
Add comments describing the purpose of these constants.
deployment-examples/browser-plugin/src/background.js, line 48 at r1 (raw file):
} async analyzeImage(url, tabId) {
add documentation.
deployment-examples/browser-plugin/src/background.js, line 76 at r1 (raw file):
} async loadImage(src) {
Is this the right way to do this?
deployment-examples/browser-plugin/src/background.js, line 85 at r1 (raw file):
img.onload = function(e) { if ((img.height && img.height > 128) || (img.width && img.width > 128)) { // Set image size for tf!
remove comment.
deployment-examples/browser-plugin/src/background.js, line 97 at r1 (raw file):
} async getTopKClasses(logits, topK) {
describe
deployment-examples/browser-plugin/src/background.js, line 124 at r1 (raw file):
async predict(imgElement) {
describe.
deployment-examples/browser-plugin/src/background.js, line 153 at r1 (raw file):
} var imageClassifier = new ImageClassifier();
const.
deployment-examples/browser-plugin/src/imagenet_classes.js, line 17 at r1 (raw file):
* ============================================================================= */
Consider reducing the classes to just the first one in each.
deployment-examples/web/README.md, line 3 at r1 (raw file):
# TensorFlow.js Deployment Example : Web Web deployment is the most common deployment scenario, and is the pattern used for most of the examples in the tfjs-examples repository. For a good simle example of how to deploy and use a model within a web page, refer to https://github.com/tensorflow/tfjs-examples/tree/master/mobilenet among others.
improve README
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to be
Reviewable status: 0 of 1 approvals obtained (waiting on @caisq and @tafsiri)
a discussion (no related file):
Appears that the manifest is missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi, @caisq, and @tafsiri)
deployment-examples/README.md, line 1 at r1 (raw file):
# TensorFlow.js Deployment Examples
directory naming nit: how about let's just call this folder "deployment", instead of "deployment-examples", for the sake of simplicity?
deployment-examples/browser-plugin/package.json, line 1 at r1 (raw file):
{
Take a look at the cloud build status. It's currently failing. The presubmit script, which is run by cloud build, assumes that there is a package.json file under each and every top-level folder in this repository. In this new directory organization, the script has to be modified accordingly.
deployment-examples/browser-plugin/README.md, line 1 at r1 (raw file):
# TensorFlow.js Deployment Example : Browser Plugin
-
You should include instructions on how to build the Chrome Extension and how to load it in Chrome for testing.
-
Directory naming discussion. Strictly speaking, what you are building is called an "extension", not a "plugin". I think we should replace "plugin" with "extensions" in the file, directory names and the texts.
deployment-examples/browser-plugin/src/background.js, line 1 at r1 (raw file):
mport 'babel-polyfill';
nit: Need license header just like all other .js files in tfjs-examples.
deployment-examples/browser-plugin/src/background.js, line 3 at r1 (raw file):
nit: The style we've been using in tfjs-examples doesn't include these spaces in import statements.
deployment-examples/browser-plugin/src/background.js, line 6 at r1 (raw file):
mobilenet_v1_
Why not MobileNetV2? It's smaller and more accuracy.
If it's not there, it'll be easy to create one, e.g., by doing in python
import tensorflow as tf
mport tensorflowjs as tfjs
model = tf.keras.applications.MobileNetV2()
tfjs.converters.save_keras_model(model, 'mobilenet_v2_1.00_224/model.json'
deployment-examples/browser-plugin/src/background.js, line 10 at r1 (raw file):
Fn(
nit: Google style generally prefers more descriptive and longer names over shorthands like Fn
. Maybe call this clickMenuCallback
.
See https://google.github.io/styleguide/jsguide.html#naming-rules-common-to-all-identifiers
deployment-examples/browser-plugin/src/background.js, line 18 at r1 (raw file):
[
nit: missing a space before [
. Please check your JS style throughout, possibly by imitating the eslint in intent-classifier.
deployment-examples/browser-plugin/src/background.js, line 39 at r1 (raw file):
this.model.predict(tf.zeros([1, IMAGE_SIZE, IMAGE_SIZE, 3])).dispose();
- Add a comment to say this is for warming up the model.
- Note that even though you use
dispose()
, this still leaks a tenor (i.e., the one created withtf.zeros()
). To prevent leakage, do:
tf.tidy(() => {
this.model.predict(...);
});
deployment-examples/browser-plugin/src/background.js, line 42 at r1 (raw file):
ms
nit: add a space before ms
.
deployment-examples/browser-plugin/src/background.js, line 48 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
add documentation.
+1
deployment-examples/browser-plugin/src/background.js, line 50 at r1 (raw file):
log(
Error conditions like this should use console.error()
, instead of console.log()
. Same below.
deployment-examples/browser-plugin/src/background.js, line 55 at r1 (raw file):
The style looks weird. Break it into a separate line.
deployment-examples/browser-plugin/src/background.js, line 55 at r1 (raw file):
5000)
This magic number looks dangerous.
deployment-examples/browser-plugin/src/background.js, line 56 at r1 (raw file):
return;
See my comment about the magic number 5000 above, why return here? You want to load the model and then do the prediction, even when the it's the first time, right?
deployment-examples/browser-plugin/src/background.js, line 64 at r1 (raw file):
!predictions)
Why might this happen? Would it be more appropriate to use try-catch?
deployment-examples/browser-plugin/src/background.js, line 81 at r1 (raw file):
resolve
This should use reject
, instead of resolve
, so that an Error can be thrown properly. I.e., new Promise((resolve, reject) => { ...
.
deployment-examples/browser-plugin/src/background.js, line 93 at r1 (raw file):
img.src = src;
What is this line for? Is src
even defined?
deployment-examples/browser-plugin/src/background.js, line 103 at r1 (raw file):
valuesAndIndices.sort
No need to do this manually. The latest version of TF.js has a tf.topk
method, see:
https://js.tensorflow.org/api/latest/#topk
deployment-examples/browser-plugin/src/content.js, line 23 at r1 (raw file):
// Produces a short text string summarizing the prediction // Input prediction should be a list of {className: string, prediction: float} // objects.
Style nit: function jsdocs should be in C style. Same elsewhere.
See: https://google.github.io/styleguide/jsguide.html#appendices-documentation-annotations
deployment-examples/browser-plugin/src/content.js, line 29 at r1 (raw file):
0.5
These magic numbers should be pulled out as file-level const
s for clarity.
deployment-examples/browser-plugin/src/content.js, line 30 at r1 (raw file):
"😄 " + predictions[0].className + "!";
All these string concatenations should use template strings, i.e., the ones with backtics. Same throughout.
deployment-examples/browser-plugin/src/content.js, line 125 at r1 (raw file):
}
style nit: need a newline character at the end of the file.
deployment-examples/browser-plugin/src/imagenet_classes.js, line 899 at r1 (raw file):
nit: indentation should be two spaces, not one.
deployment-examples/web/README.md, line 1 at r1 (raw file):
# TensorFlow.js Deployment Example : Web
Does this file belong in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi and @tafsiri)
deployment/README.md, line 1 at r2 (raw file):
# TensorFlow.js Deployment Examples
The deploy script assumes a script in each directory called build, can you make sure that works with this nested structure?
Also, is this the structure we want? How about just making a folder called chrome-extension?
https://github.com/tensorflow/tfjs-examples/blob/master/deploy.sh
deployment/browser-plugin/package.json, line 1 at r2 (raw file):
{
this is specific to chrome right? how about just calling this directory chrome-extension instead of browser-plugin?
deployment/browser-plugin/src/background.js, line 24 at r2 (raw file):
// Where to load the model from. const MOBILENET_MODEL_PATH = 'https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json';
use tfhub
deployment/browser-plugin/src/imagenet_classes.js, line 1 at r2 (raw file):
/**
why do you need this? can you just depend on the mobilenet package @tensorflow-models/mobilenet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
deployment/README.md, line 1 at r2 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
The deploy script assumes a script in each directory called build, can you make sure that works with this nested structure?
Also, is this the structure we want? How about just making a folder called chrome-extension?
https://github.com/tensorflow/tfjs-examples/blob/master/deploy.sh
Updated. I'm happy to move the chrome-extension to top level and get rid of the idea of a group of deployment-centric examples.
deployment-examples/README.md, line 1 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
# TensorFlow.js Deployment Examples
directory naming nit: how about let's just call this folder "deployment", instead of "deployment-examples", for the sake of simplicity?
changed.
deployment-examples/README.md, line 12 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
Improve readme.
done
deployment/browser-plugin/src/background.js, line 24 at r2 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
use tfhub
done.
deployment/browser-plugin/src/imagenet_classes.js, line 1 at r2 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
why do you need this? can you just depend on the mobilenet package @tensorflow-models/mobilenet?
That does not expose the actual classes. It's more of a managed solution that only offers 'load' and 'classify'
deployment-examples/browser-plugin/package.json, line 1 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
{
Take a look at the cloud build status. It's currently failing. The presubmit script, which is run by cloud build, assumes that there is a package.json file under each and every top-level folder in this repository. In this new directory organization, the script has to be modified accordingly.
Done Thanks for pointing this out.
I think the change I made to the testing script should be sufficient.
deployment-examples/browser-plugin/README.md, line 1 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
# TensorFlow.js Deployment Example : Browser Plugin
You should include instructions on how to build the Chrome Extension and how to load it in Chrome for testing.
Directory naming discussion. Strictly speaking, what you are building is called an "extension", not a "plugin". I think we should replace "plugin" with "extensions" in the file, directory names and the texts.
Done.
deployment-examples/browser-plugin/README.md, line 5 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
"copy": "cp src/content.js dist/src/ && cp src/imagenet_classes.js dist/src/",
Improve readme. Add build & installation instructions.
done
deployment-examples/browser-plugin/src/background.js, line 1 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
mport 'babel-polyfill';
nit: Need license header just like all other .js files in tfjs-examples.
Done.
deployment-examples/browser-plugin/src/background.js, line 1 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
Needs license
Done.
deployment-examples/browser-plugin/src/background.js, line 3 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
nit: The style we've been using in tfjs-examples doesn't include these spaces in import statements.
Done.
deployment-examples/browser-plugin/src/background.js, line 6 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
mobilenet_v1_
Why not MobileNetV2? It's smaller and more accuracy.
If it's not there, it'll be easy to create one, e.g., by doing in pythonimport tensorflow as tf mport tensorflowjs as tfjs model = tf.keras.applications.MobileNetV2() tfjs.converters.save_keras_model(model, 'mobilenet_v2_1.00_224/model.json'
Done.
deployment-examples/browser-plugin/src/background.js, line 10 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
Fn(
nit: Google style generally prefers more descriptive and longer names over shorthands like
Fn
. Maybe call thisclickMenuCallback
.See https://google.github.io/styleguide/jsguide.html#naming-rules-common-to-all-identifiers
Done.
deployment-examples/browser-plugin/src/background.js, line 18 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
[
nit: missing a space before
[
. Please check your JS style throughout, possibly by imitating the eslint in intent-classifier.
Done. (needed to re-install and setup clang-format)
deployment-examples/browser-plugin/src/background.js, line 39 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
this.model.predict(tf.zeros([1, IMAGE_SIZE, IMAGE_SIZE, 3])).dispose();
- Add a comment to say this is for warming up the model.
- Note that even though you use
dispose()
, this still leaks a tenor (i.e., the one created withtf.zeros()
). To prevent leakage, do:tf.tidy(() => { this.model.predict(...); });
Done.
deployment-examples/browser-plugin/src/background.js, line 42 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
ms
nit: add a space before
ms
.
Done.
deployment-examples/browser-plugin/src/background.js, line 50 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
log(
Error conditions like this should use
console.error()
, instead ofconsole.log()
. Same below.
Done.
deployment-examples/browser-plugin/src/background.js, line 55 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
5000)
This magic number looks dangerous.
Done.
deployment-examples/browser-plugin/src/background.js, line 55 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
The style looks weird. Break it into a separate line.
Done.
deployment-examples/browser-plugin/src/background.js, line 56 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
return;
See my comment about the magic number 5000 above, why return here? You want to load the model and then do the prediction, even when the it's the first time, right?
The function uses async recursion here to handle the case that the model isn't loaded. While it can't load the model it keeps trying every 5 seconds.
deployment-examples/browser-plugin/src/background.js, line 64 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
!predictions)
Why might this happen? Would it be more appropriate to use try-catch?
I don't think it can happen. Removed.
deployment-examples/browser-plugin/src/background.js, line 81 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
resolve
This should use
reject
, instead ofresolve
, so that an Error can be thrown properly. I.e.,new Promise((resolve, reject) => { ...
.
good catch. Updated error handling here.
deployment-examples/browser-plugin/src/background.js, line 93 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
img.src = src;
What is this line for? Is
src
even defined?
src is an input argument. This line sets the src parameter of the image element
deployment-examples/browser-plugin/src/content.js, line 23 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
// Produces a short text string summarizing the prediction // Input prediction should be a list of {className: string, prediction: float} // objects.
Style nit: function jsdocs should be in C style. Same elsewhere.
See: https://google.github.io/styleguide/jsguide.html#appendices-documentation-annotations
Done.
deployment-examples/browser-plugin/src/content.js, line 29 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
0.5
These magic numbers should be pulled out as file-level
const
s for clarity.
Great idea. done.
deployment-examples/browser-plugin/src/content.js, line 30 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
"😄 " + predictions[0].className + "!";
All these string concatenations should use template strings, i.e., the ones with backtics. Same throughout.
done.
deployment-examples/browser-plugin/src/content.js, line 125 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
}
style nit: need a newline character at the end of the file.
Done.
deployment-examples/browser-plugin/src/imagenet_classes.js, line 899 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
nit: indentation should be two spaces, not one.
Done.
deployment-examples/web/README.md, line 1 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
# TensorFlow.js Deployment Example : Web
Does this file belong in this PR?
Removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
deployment/README.md, line 1 at r2 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
Updated. I'm happy to move the chrome-extension to top level and get rid of the idea of a group of deployment-centric examples.
updated 2: Got rid of the subdir structure
deployment/browser-plugin/package.json, line 1 at r2 (raw file):
Previously, nsthorat (Nikhil Thorat) wrote…
this is specific to chrome right? how about just calling this directory chrome-extension instead of browser-plugin?
Removed the nested substructure. If we end up wanting to add organizational structure to the examples we can do it later.
deployment-examples/README.md, line 1 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
changed.
removed.
deployment-examples/browser-plugin/README.md, line 1 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
Done.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status:
complete! 1 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
a discussion (no related file):
Previously, bileschi (Stanley Bileschi) wrote…
Appears that the manifest is missing.
Great work! Thanks!
chrome-extension/README.md, line 1 at r3 (raw file):
Plugin
-> Extension
chrome-extension/README.md, line 5 at r3 (raw file):
mobilenet
-> MobileNetV2
chrome-extension/src/background.js, line 25 at r3 (raw file):
/ 'https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/
Remove cruft.
chrome-extension/src/background.js, line 193 at r3 (raw file):
const logits1001 = this.model.predict(batched);
To be more robust against future changes, you can do:
const output = this.model.predict(batched);
if (output.shape[output.shape.length - 1] === 1001) {
return output.slice([0, 1], [-1, 1000]);
} else if (output.shape[output.shape.length - 1] === 100) {
return output;
} else {
throw new Error('Unexpected shape...');
}
chrome-extension/src/background.js, line 203 at r3 (raw file):
Math.floor(totalTime1)}
You can also do something like ${totalTime1.toFixed(1)}
.
chrome-extension/src/content.js, line 22 at r3 (raw file):
HIGH_CONFIDENCE =
Naming nit: --> HIGH_CONFIDENCE_THRESHOLD to be more threshold. Same below.
deployment-examples/browser-plugin/package.json, line 1 at r1 (raw file):
Previously, bileschi (Stanley Bileschi) wrote…
Done Thanks for pointing this out.
I think the change I made to the testing script should be sufficient.
OK. The flat structure works, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
chrome-extension/src/background.js, line 158 at r3 (raw file):
values.dataSync()
To illustrate best practice, use await value.data()
here. Same below.
data()
doesn't block the main thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
chrome-extension/src/background.js, line 25 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
/ 'https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/
Remove cruft.
Done.
chrome-extension/src/background.js, line 158 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
values.dataSync()
To illustrate best practice, use
await value.data()
here. Same below.
data()
doesn't block the main thread.
Done.
chrome-extension/src/background.js, line 193 at r3 (raw file):
if (output.shape[output.shape.length - 1] === 1001) {
return output.slice([0, 1], [-1, 1000]);
} else if (output.shape[output.shape.length - 1] === 100) {
return output;
} else {
throw new Error('Unexpected shape...');
}
Good idea. Done.
chrome-extension/src/background.js, line 203 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
Math.floor(totalTime1)}
You can also do something like
${totalTime1.toFixed(1)}
.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 1 change requests, 0 of 1 approvals obtained (waiting on @caisq, @nsthorat, and @tafsiri)
a discussion (no related file):
Previously, caisq (Shanqing Cai) wrote…
:lgtm_strong:
Great work! Thanks!
Thanks for the reviews! @nsthorat too
chrome-extension/README.md, line 1 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
Plugin
-> Extension
Done.
chrome-extension/README.md, line 5 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
mobilenet
-> MobileNetV2
Done.
chrome-extension/src/content.js, line 22 at r3 (raw file):
Previously, caisq (Shanqing Cai) wrote…
HIGH_CONFIDENCE =
Naming nit: --> HIGH_CONFIDENCE_THRESHOLD to be more threshold. Same below.
Done.
deployment-examples/browser-plugin/src/background.js, line 103 at r1 (raw file):
Previously, caisq (Shanqing Cai) wrote…
valuesAndIndices.sort
No need to do this manually. The latest version of TF.js has a
tf.topk
method, see:
https://js.tensorflow.org/api/latest/#topk
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies I had one last comment about dist/ which I think I added right after you merged
Reviewable status:
complete! 1 of 1 approvals obtained (waiting on @bileschi, @caisq, @nsthorat, and @tafsiri)
chrome-extension/README.md, line 15 at r4 (raw file):
To install the unpacked extension in chrome, follow the instructions here. Briefly, navigate to
chrome://extensions
, make sure that theDeveloper mode
switch is turned on in the upper right, and clickLoad Unpacked
. Then select the appropriate directory (thedist
directory containingmanifest.json
);
usually we don't check in dist/, this is generated. can you put images outside that dist directory? I think it will also get clobbered
Is the idea to move images & manifest.json to src, and then copy them?
…On Tue, Jul 2, 2019 at 10:59 AM Nikhil Thorat ***@***.***> wrote:
***@***.**** commented on this pull request.
Apologies I had one last comment about dist/ which I think I added right
after you merged
*Reviewable
<https://reviewable.io/reviews/tensorflow/tfjs-examples/285#-:-LinBXcE9HvQQLt26Xrb:b-rk834f>*
status: [image:
![]() --
Stan Bileschi Ph.D. | SWE | [email protected] | 617-230-8081
|
This PR creates a subdirectory within examples for examples meant to exhibit how to deploy tfjs. It creates two examples. One for deploying to browser (indicating to the reader just to use the mobilenet example in the parent dir above), and one for deploying to a browser plugin.
The browser plugin allows the user to right-click on images in a webpage, and apply mobilenet to the image. The resulting prediction is written on top of the image.
This change is