emoji-net
Version:
EmojiNet is an image to emoji recognizer based on MobileNet / Google Emoji Scavenger Hunt
121 lines • 4.88 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmojiNet = exports.MOBILENET_SIZE = void 0;
/**
* @license
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================================
*/
require("isomorphic-fetch");
const tfc = __importStar(require("@tensorflow/tfjs-core"));
const tfjs_converter_1 = require("@tensorflow/tfjs-converter");
const emoji_classes_1 = require("./emoji-classes");
const canvas_utils_1 = require("./canvas-utils");
const MOBILENET_SIZE = 224;
exports.MOBILENET_SIZE = MOBILENET_SIZE;
const MODEL_FILE_URL = 'https://emojiscavengerhunt.withgoogle.com/model/tensorflowjs_model.pb';
const WEIGHT_MANIFEST_FILE_URL = 'https://emojiscavengerhunt.withgoogle.com/model/weights_manifest.json';
// const MODEL_FILE_URL = 'file:///model/tensorflowjs_model.pb'
// const WEIGHT_MANIFEST_FILE_URL = 'file:///model/weights_manifest.json'
const INPUT_NODE_NAME = 'input';
const OUTPUT_NODE_NAME = 'final_result';
const PREPROCESS_DIVISOR = tfc.scalar(255 / 2);
class EmojiNet {
async load() {
this.model = await tfjs_converter_1.loadFrozenModel(MODEL_FILE_URL, WEIGHT_MANIFEST_FILE_URL);
this.predict(tfc.zeros([
MOBILENET_SIZE,
MOBILENET_SIZE,
3,
]));
}
dispose() {
if (this.model) {
this.model.dispose();
}
}
async recognize(src) {
const image = await canvas_utils_1.loadImage(src);
const resizedImage = await canvas_utils_1.resizeImage(image, MOBILENET_SIZE, MOBILENET_SIZE);
const canvas = await canvas_utils_1.createCanvas(MOBILENET_SIZE, MOBILENET_SIZE);
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('no ctx');
}
ctx.putImageData(resizedImage, 0, 0);
const pixels = tfc.fromPixels(canvas);
const predictions = this.predict(pixels);
const top3 = this.getTopKClasses(predictions, 3);
return top3;
}
/**
* Infer through MobileNet, assumes variables have been loaded. This does
* standard ImageNet pre-processing before inferring through the model. This
* method returns named activations as well as softmax logits.
*
* @param input un-preprocessed input Array.
* @return The softmax logits.
*/
predict(input) {
const preprocessedInput = tfc.div(tfc.sub(input.asType('float32'), PREPROCESS_DIVISOR), PREPROCESS_DIVISOR);
const reshapedInput = preprocessedInput.reshape([
1,
...preprocessedInput.shape,
]);
const dict = {};
dict[INPUT_NODE_NAME] = reshapedInput;
return this.model.execute(dict, OUTPUT_NODE_NAME);
}
getTopKClasses(predictions, topK) {
const values = predictions.dataSync();
predictions.dispose();
let predictionList = [];
for (let i = 0; i < values.length; i++) {
predictionList.push({
index: i,
probobility: values[i],
});
}
predictionList = predictionList.sort((a, b) => {
return b.probobility - a.probobility;
}).slice(0, topK);
return predictionList.map(x => ({
id: x.index,
name: emoji_classes_1.EMOJI_CLASSES[x.index],
probobility: x.probobility,
}));
}
}
exports.EmojiNet = EmojiNet;
//# sourceMappingURL=emoji-net.js.map