You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, targetLanguage = 'ru') {
/**
* Dynamically loads required machine learning libraries from a CDN.
* Checks if the libraries are already in the global window object to avoid reloading.
*/
const ensureLibraries = async () => {
const scripts = [{
name: 'tf',
url: 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.11.0/dist/tf.min.js'
}, {
name: 'cocoSsd',
url: 'https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd@2.2.2/dist/coco-ssd.min.js'
}];
for (const script of scripts) {
if (!window[script.name]) {
await new Promise((resolve, reject) => {
const scriptTag = document.createElement('script');
scriptTag.src = script.url;
scriptTag.crossOrigin = 'anonymous';
scriptTag.onload = resolve;
scriptTag.onerror = () => reject(new Error(`Failed to load script: ${script.url}`));
document.head.appendChild(scriptTag);
});
}
}
};
/**
* A dictionary containing translations for COCO-SSD object classes.
* Supports: English (en), Russian (ru), Spanish (es), French (fr), German (de), Chinese (zh).
*/
const translations = {
"person": { "en": "person", "ru": "человек", "es": "persona", "fr": "personne", "de": "Person", "zh": "人" },
"bicycle": { "en": "bicycle", "ru": "велосипед", "es": "bicicleta", "fr": "vélo", "de": "Fahrrad", "zh": "自行车" },
"car": { "en": "car", "ru": "машина", "es": "coche", "fr": "voiture", "de": "Auto", "zh": "汽车" },
"motorcycle": { "en": "motorcycle", "ru": "мотоцикл", "es": "motocicleta", "fr": "moto", "de": "Motorrad", "zh": "摩托车" },
"airplane": { "en": "airplane", "ru": "самолет", "es": "avión", "fr": "avion", "de": "Flugzeug", "zh": "飞机" },
"bus": { "en": "bus", "ru": "автобус", "es": "autobús", "fr": "bus", "de": "Bus", "zh": "公共汽车" },
"train": { "en": "train", "ru": "поезд", "es": "tren", "fr": "train", "de": "Zug", "zh": "火车" },
"truck": { "en": "truck", "ru": "грузовик", "es": "camión", "fr": "camion", "de": "LKW", "zh": "卡车" },
"boat": { "en": "boat", "ru": "лодка", "es": "barco", "fr": "bateau", "de": "Boot", "zh": "船" },
"traffic light": { "en": "traffic light", "ru": "светофор", "es": "semáforo", "fr": "feu de circulation", "de": "Ampel", "zh": "红绿灯" },
"fire hydrant": { "en": "fire hydrant", "ru": "пожарный гидрант", "es": "boca de incendios", "fr": "bouche d'incendie", "de": "Hydrant", "zh": "消防栓" },
"stop sign": { "en": "stop sign", "ru": "знак стоп", "es": "señal de stop", "fr": "panneau stop", "de": "Stoppschild", "zh": "停车标志" },
"parking meter": { "en": "parking meter", "ru": "паркометр", "es": "parquímetro", "fr": "parcmètre", "de": "Parkuhr", "zh": "停车计时器" },
"bench": { "en": "bench", "ru": "скамейка", "es": "banco", "fr": "banc", "de": "Bank", "zh": "长凳" },
"bird": { "en": "bird", "ru": "птица", "es": "pájaro", "fr": "oiseau", "de": "Vogel", "zh": "鸟" },
"cat": { "en": "cat", "ru": "кошка", "es": "gato", "fr": "chat", "de": "Katze", "zh": "猫" },
"dog": { "en": "dog", "ru": "собака", "es": "perro", "fr": "chien", "de": "Hund", "zh": "狗" },
"horse": { "en": "horse", "ru": "лошадь", "es": "caballo", "fr": "cheval", "de": "Pferd", "zh": "马" },
"sheep": { "en": "sheep", "ru": "овца", "es": "oveja", "fr": "mouton", "de": "Schaf", "zh": "羊" },
"cow": { "en": "cow", "ru": "корова", "es": "vaca", "fr": "vache", "de": "Kuh", "zh": "牛" },
"elephant": { "en": "elephant", "ru": "слон", "es": "elefante", "fr": "éléphant", "de": "Elefant", "zh": "大象" },
"bear": { "en": "bear", "ru": "медведь", "es": "oso", "fr": "ours", "de": "Bär", "zh": "熊" },
"zebra": { "en": "zebra", "ru": "зебра", "es": "cebra", "fr": "zèbre", "de": "Zebra", "zh": "斑马" },
"giraffe": { "en": "giraffe", "ru": "жираф", "es": "jirafa", "fr": "girafe", "de": "Giraffe", "zh": "长颈鹿" },
"backpack": { "en": "backpack", "ru": "рюкзак", "es": "mochila", "fr": "sac à dos", "de": "Rucksack", "zh": "背包" },
"umbrella": { "en": "umbrella", "ru": "зонт", "es": "paraguas", "fr": "parapluie", "de": "Regenschirm", "zh": "雨伞" },
"handbag": { "en": "handbag", "ru": "сумка", "es": "bolso", "fr": "sac à main", "de": "Handtasche", "zh": "手提包" },
"tie": { "en": "tie", "ru": "галстук", "es": "corbata", "fr": "cravate", "de": "Krawatte", "zh": "领带" },
"suitcase": { "en": "suitcase", "ru": "чемодан", "es": "maleta", "fr": "valise", "de": "Koffer", "zh": "手提箱" },
"frisbee": { "en": "frisbee", "ru": "фрисби", "es": "frisbee", "fr": "frisbee", "de": "Frisbee", "zh": "飞盘" },
"skis": { "en": "skis", "ru": "лыжи", "es": "esquís", "fr": "skis", "de": "Ski", "zh": "滑雪板" },
"snowboard": { "en": "snowboard", "ru": "сноуборд", "es": "snowboard", "fr": "snowboard", "de": "Snowboard", "zh": "单板滑雪" },
"sports ball": { "en": "sports ball", "ru": "мяч", "es": "pelota deportiva", "fr": "ballon de sport", "de": "Sportball", "zh": "运动球" },
"kite": { "en": "kite", "ru": "воздушный змей", "es": "cometa", "fr": "cerf-volant", "de": "Drachen", "zh": "风筝" },
"baseball bat": { "en": "baseball bat", "ru": "бейсбольная бита", "es": "bate de béisbol", "fr": "batte de baseball", "de": "Baseballschläger", "zh": "棒球棒" },
"baseball glove": { "en": "baseball glove", "ru": "бейсбольная перчатка", "es": "guante de béisbol", "fr": "gant de baseball", "de": "Baseballhandschuh", "zh": "棒球手套" },
"skateboard": { "en": "skateboard", "ru": "скейтборд", "es": "patineta", "fr": "skateboard", "de": "Skateboard", "zh": "滑板" },
"surfboard": { "en": "surfboard", "ru": "доска для серфинга", "es": "tabla de surf", "fr": "planche de surf", "de": "Surfbrett", "zh": "冲浪板" },
"tennis racket": { "en": "tennis racket", "ru": "теннисная ракетка", "es": "raqueta de tenis", "fr": "raquette de tennis", "de": "Tennisschläger", "zh": "网球拍" },
"bottle": { "en": "bottle", "ru": "бутылка", "es": "botella", "fr": "bouteille", "de": "Flasche", "zh": "瓶子" },
"wine glass": { "en": "wine glass", "ru": "бокал", "es": "copa de vino", "fr": "verre à vin", "de": "Weinglas", "zh": "酒杯" },
"cup": { "en": "cup", "ru": "чашка", "es": "taza", "fr": "tasse", "de": "Tasse", "zh": "杯子" },
"fork": { "en": "fork", "ru": "вилка", "es": "tenedor", "fr": "fourchette", "de": "Gabel", "zh": "叉子" },
"knife": { "en": "knife", "ru": "нож", "es": "cuchillo", "fr": "couteau", "de": "Messer", "zh": "刀" },
"spoon": { "en": "spoon", "ru": "ложка", "es": "cuchara", "fr": "cuillère", "de": "Löffel", "zh": "勺子" },
"bowl": { "en": "bowl", "ru": "миска", "es": "cuenco", "fr": "bol", "de": "Schüssel", "zh": "碗" },
"banana": { "en": "banana", "ru": "банан", "es": "plátano", "fr": "banane", "de": "Banane", "zh": "香蕉" },
"apple": { "en": "apple", "ru": "яблоко", "es": "manzana", "fr": "pomme", "de": "Apfel", "zh": "苹果" },
"sandwich": { "en": "sandwich", "ru": "бутерброд", "es": "sándwich", "fr": "sandwich", "de": "Sandwich", "zh": "三明治" },
"orange": { "en": "orange", "ru": "апельсин", "es": "naranja", "fr": "orange", "de": "Orange", "zh": "橙子" },
"broccoli": { "en": "broccoli", "ru": "брокколи", "es": "brócoli", "fr": "brocoli", "de": "Brokkoli", "zh": "西兰花" },
"carrot": { "en": "carrot", "ru": "морковь", "es": "zanahoria", "fr": "carotte", "de": "Karotte", "zh": "胡萝卜" },
"hot dog": { "en": "hot dog", "ru": "хот-дог", "es": "perrito caliente", "fr": "hot-dog", "de": "Hotdog", "zh": "热狗" },
"pizza": { "en": "pizza", "ru": "пицца", "es": "pizza", "fr": "pizza", "de": "Pizza", "zh": "比萨" },
"donut": { "en": "donut", "ru": "пончик", "es": "dona", "fr": "beignet", "de": "Donut", "zh": "甜甜圈" },
"cake": { "en": "cake", "ru": "торт", "es": "pastel", "fr": "gâteau", "de": "Kuchen", "zh": "蛋糕" },
"chair": { "en": "chair", "ru": "стул", "es": "silla", "fr": "chaise", "de": "Stuhl", "zh": "椅子" },
"couch": { "en": "couch", "ru": "диван", "es": "sofá", "fr": "canapé", "de": "Sofa", "zh": "沙发" },
"potted plant": { "en": "potted plant", "ru": "растение в горшке", "es": "planta en maceta", "fr": "plante en pot", "de": "Topfpflanze", "zh": "盆栽" },
"bed": { "en": "bed", "ru": "кровать", "es": "cama", "fr": "lit", "de": "Bett", "zh": "床" },
"dining table": { "en": "dining table", "ru": "обеденный стол", "es": "mesa de comedor", "fr": "table à manger", "de": "Esstisch", "zh": "餐桌" },
"toilet": { "en": "toilet", "ru": "унитаз", "es": "inodoro", "fr": "toilette", "de": "Toilette", "zh": "厕所" },
"tv": { "en": "tv", "ru": "телевизор", "es": "televisión", "fr": "télévision", "de": "Fernseher", "zh": "电视" },
"laptop": { "en": "laptop", "ru": "ноутбук", "es": "portátil", "fr": "ordinateur portable", "de": "Laptop", "zh": "笔记本电脑" },
"mouse": { "en": "mouse", "ru": "мышь", "es": "ratón", "fr": "souris", "de": "Maus", "zh": "鼠标" },
"remote": { "en": "remote", "ru": "пульт", "es": "control remoto", "fr": "télécommande", "de": "Fernbedienung", "zh": "遥控器" },
"keyboard": { "en": "keyboard", "ru": "клавиатура", "es": "teclado", "fr": "clavier", "de": "Tastatur", "zh": "键盘" },
"cell phone": { "en": "cell phone", "ru": "мобильный телефон", "es": "teléfono celular", "fr": "téléphone portable", "de": "Handy", "zh": "手机" },
"microwave": { "en": "microwave", "ru": "микроволновка", "es": "microondas", "fr": "four à micro-ondes", "de": "Mikrowelle", "zh": "微波炉" },
"oven": { "en": "oven", "ru": "духовка", "es": "horno", "fr": "four", "de": "Ofen", "zh": "烤箱" },
"toaster": { "en": "toaster", "ru": "тостер", "es": "tostadora", "fr": "grille-pain", "de": "Toaster", "zh": "烤面包机" },
"sink": { "en": "sink", "ru": "раковина", "es": "fregadero", "fr": "évier", "de": "Waschbecken", "zh": "水槽" },
"refrigerator": { "en": "refrigerator", "ru": "холодильник", "es": "refrigerador", "fr": "réfrigérateur", "de": "Kühlschrank", "zh": "冰箱" },
"book": { "en": "book", "ru": "книга", "es": "libro", "fr": "livre", "de": "Buch", "zh": "书" },
"clock": { "en": "clock", "ru": "часы", "es": "reloj", "fr": "horloge", "de": "Uhr", "zh": "时钟" },
"vase": { "en": "vase", "ru": "ваза", "es": "jarrón", "fr": "vase", "de": "Vase", "zh": "花瓶" },
"scissors": { "en": "scissors", "ru": "ножницы", "es": "tijeras", "fr": "ciseaux", "de": "Schere", "zh": "剪刀" },
"teddy bear": { "en": "teddy bear", "ru": "плюшевый мишка", "es": "oso de peluche", "fr": "ours en peluche", "de": "Teddybär", "zh": "泰迪熊" },
"hair drier": { "en": "hair drier", "ru": "фен", "es": "secador de pelo", "fr": "sèche-cheveux", "de": "Fön", "zh": "吹风机" },
"toothbrush": { "en": "toothbrush", "ru": "зубная щетка", "es": "cepillo de dientes", "fr": "brosse à dents", "de": "Zahnbürste", "zh": "牙刷" },
};
// Create a canvas to draw on
const canvas = document.createElement('canvas');
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0);
// Add a status message on the canvas
const drawMessage = (message) => {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = '24px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
};
try {
drawMessage('Loading libraries...');
await ensureLibraries();
drawMessage('Loading object detection model...');
const model = await window.cocoSsd.load();
drawMessage('Identifying objects...');
const predictions = await model.detect(canvas);
// Clear the message and redraw the original image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0);
// Draw predictions
predictions.forEach(prediction => {
const [x, y, width, height] = prediction.bbox;
const originalClass = prediction.class;
const score = Math.round(prediction.score * 100);
// Translate the class name, fallback to English if not found
let translatedText = (translations[originalClass] && translations[originalClass][targetLanguage]) ?
translations[originalClass][targetLanguage] :
originalClass;
const label = `${translatedText} ${score}%`;
// Styling
const color = '#34ebc9';
ctx.strokeStyle = color;
ctx.lineWidth = 2;
ctx.font = '16px sans-serif';
ctx.textBaseline = 'top';
// Draw bounding box
ctx.strokeRect(x, y, width, height);
// Draw text background
ctx.fillStyle = color;
const textWidth = ctx.measureText(label).width;
const textHeight = 18;
ctx.fillRect(x, y, textWidth + 8, textHeight);
// Draw text
ctx.fillStyle = '#000000';
ctx.fillText(label, x + 4, y + 1);
});
if (predictions.length === 0) {
drawMessage(`No objects identified. (Lang: ${targetLanguage})`);
}
} catch (error) {
console.error("Image processing failed:", error);
drawMessage('An error occurred during processing.');
}
return canvas;
}
Apply Changes