* Async loads a mobilenet on construction. Subsequently handles * requests to classify images through the .analyzeImage API. * Successful requests will post a chrome message with * 'IMAGE_CLICK_PROCESSED' action, which the content.js can * hear and use to manipulate the DOM.
| 67 | * hear and use to manipulate the DOM. |
| 68 | */ |
| 69 | class ImageClassifier { |
| 70 | constructor() { |
| 71 | this.loadModel(); |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Loads mobilenet from URL and keeps a reference to it in the object. |
| 76 | */ |
| 77 | async loadModel() { |
| 78 | console.log('Loading model...'); |
| 79 | const startTime = performance.now(); |
| 80 | try { |
| 81 | this.model = await mobilenet.load({ version: 2, alpha: 1.00 }); |
| 82 | // Warms up the model by causing intermediate tensor values |
| 83 | // to be built and pushed to GPU. |
| 84 | tf.tidy(() => { |
| 85 | this.model.classify(tf.zeros([1, IMAGE_SIZE, IMAGE_SIZE, 3])); |
| 86 | }); |
| 87 | const totalTime = Math.floor(performance.now() - startTime); |
| 88 | console.log(`Model loaded and initialized in ${totalTime} ms...`); |
| 89 | } catch (e) { |
| 90 | console.error('Unable to load model', e); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | /** |
| 95 | * Triggers the model to make a prediction on the image referenced by the |
| 96 | * image data. After a successful prediction a IMAGE_CLICK_PROCESSED message |
| 97 | * when complete, for the content.js script to hear and update the DOM with |
| 98 | * the results of the prediction. |
| 99 | * |
| 100 | * @param {ImageData} imageData ImageData of the image to analyze. |
| 101 | * @param {string} url url of image to analyze. |
| 102 | * @param {number} tabId which tab the request comes from. |
| 103 | */ |
| 104 | async analyzeImage(imageData, url, tabId) { |
| 105 | if (!tabId) { |
| 106 | console.error('No tab. No prediction.'); |
| 107 | return; |
| 108 | } |
| 109 | if (!this.model) { |
| 110 | console.log('Waiting for model to load...'); |
| 111 | setTimeout( |
| 112 | () => { this.analyzeImage(imageData, url, tabId) }, FIVE_SECONDS_IN_MS); |
| 113 | return; |
| 114 | } |
| 115 | console.log('Predicting...'); |
| 116 | const startTime = performance.now(); |
| 117 | const predictions = await this.model.classify(imageData, TOPK_PREDICTIONS); |
| 118 | const totalTime = performance.now() - startTime; |
| 119 | console.log(`Done in ${totalTime.toFixed(1)} ms `); |
| 120 | const message = { action: 'IMAGE_CLICK_PROCESSED', url, predictions }; |
| 121 | chrome.tabs.sendMessage(tabId, message); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | const imageClassifier = new ImageClassifier(); |
nothing calls this directly
no outgoing calls
no test coverage detected