You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, description = '') {
/**
* Helper function to dynamically load a script and wait for it to be ready.
* Caches the promise to avoid reloading the same script.
* @param {string} url - The URL of the script to load.
* @param {string} globalVarName - The name of the global variable the script is expected to create.
* @returns {Promise<void>} - A promise that resolves when the script is loaded.
*/
const loadScript = (url, globalVarName) => {
if (!window.loadedScripts) {
window.loadedScripts = {};
}
if (!window.loadedScripts[url]) {
window.loadedScripts[url] = new Promise((resolve, reject) => {
// Check if the script's global object already exists (e.g., from a previous run)
if (window[globalVarName]) {
return resolve();
}
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = () => reject(new Error(`Script load error for ${url}`));
document.head.appendChild(script);
});
}
return window.loadedScripts[url];
};
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
// Show a loading message on the canvas while the model loads
ctx.drawImage(originalImg, 0, 0);
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height / 2 - 20, canvas.width, 40);
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.font = '20px Arial';
ctx.fillText('🔍 Analyzing image, please wait...', canvas.width / 2, canvas.height / 2 + 7);
try {
// Dynamically load TensorFlow.js and the COCO-SSD model.
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest', 'tf');
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd@latest', 'cocoSsd');
// Load the COCO-SSD model. We cache the model promise in the window object
// to avoid reloading it on subsequent calls.
if (!window.cocoSsdModelPromise) {
window.cocoSsdModelPromise = cocoSsd.load();
}
const model = await window.cocoSsdModelPromise;
const predictions = await model.detect(originalImg);
// Clear loading message and redraw the original image
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0);
// Parse the user's description string into a set for efficient lookup
const descriptionItems = new Set(
description.toLowerCase().split(',').map(s => s.trim()).filter(Boolean)
);
predictions.forEach(prediction => {
const [x, y, width, height] = prediction.bbox;
const text = `${prediction.class} (${Math.round(prediction.score * 100)}%)`;
let boxColor = '#00FFFF'; // Default color: Cyan
if (descriptionItems.size > 0) {
// If a description is provided, color-code the boxes
const isMatch = descriptionItems.has(prediction.class.toLowerCase());
boxColor = isMatch ? '#00FF00' : '#FF0000'; // Green for match, Red for mismatch
}
// Draw the bounding box
ctx.strokeStyle = boxColor;
ctx.lineWidth = Math.max(2, Math.min(canvas.width, canvas.height) / 200);
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.stroke();
// Draw the text label with a background
const fontSize = Math.max(12, Math.min(canvas.width, canvas.height) / 40);
ctx.font = `${fontSize}px Arial`;
const textMetrics = ctx.measureText(text);
const textWidth = textMetrics.width;
const textHeight = fontSize * 1.2;
ctx.fillStyle = boxColor;
ctx.fillRect(x, y - textHeight, textWidth + 8, textHeight);
ctx.fillStyle = '#000000'; // Black text for better readability
ctx.fillText(text, x + 4, y - (textHeight * 0.15));
});
// Add a legend if a description was provided
if (descriptionItems.size > 0) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(10, 10, 260, 30);
ctx.font = '16px Arial';
ctx.fillStyle = '#00FF00';
ctx.fillText('■ Matches Description', 95, 30);
ctx.fillStyle = '#FF0000';
ctx.fillText('■ Mismatch', 210, 30);
} else if (predictions.length === 0) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(0, canvas.height / 2 - 20, canvas.width, 40);
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.font = '20px Arial';
ctx.fillText('No objects detected.', canvas.width / 2, canvas.height / 2 + 7);
}
} catch (error) {
console.error("Image detection failed:", error);
// Display an error message on the canvas if something goes wrong
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ff0000';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.fillText('Error: Could not perform image detection.', canvas.width / 2, canvas.height / 2 - 10);
ctx.fillText('Please check your internet connection and try again.', canvas.width / 2, canvas.height / 2 + 10);
}
return canvas;
}
Apply Changes