You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, minConfidence = 0.5, boxColor = '#00FF00', textColor = '#000000') {
// Determine confidence threshold properly (fallback if parsed as string)
const threshold = parseFloat(minConfidence) || 0.5;
// Create a canvas to return synchronously
const canvas = document.createElement('canvas');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
// Draw the initial image on the canvas
ctx.drawImage(originalImg, 0, 0);
// Draw a loading indicator natively on the canvas while scripts download & run
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
ctx.fillRect(0, 0, canvas.width, 50);
ctx.fillStyle = '#ffffff';
ctx.font = '20px sans-serif';
ctx.textBaseline = 'middle';
ctx.fillText('Loading object detection model...', 15, 25);
// Asynchronous processing function
(async function detectObjects() {
const loadScript = (src, globalVar) => {
return new Promise((resolve, reject) => {
// If library is already available globally
if (window[globalVar]) return resolve();
// If the script is already embedded but not finished loading
let script = document.querySelector(`script[src="${src}"]`);
if (script) {
const checkInterval = setInterval(() => {
if (window[globalVar]) {
clearInterval(checkInterval);
resolve();
}
}, 50);
return;
}
// Inject otherwise
script = document.createElement('script');
script.src = src;
script.crossOrigin = 'anonymous';
script.onload = resolve;
script.onerror = () => reject(new Error(`Failed to load ${src}`));
document.head.appendChild(script);
});
};
try {
// Dynamically load TensorFlow.js and COCO-SSD model
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs', 'tf');
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd', 'cocoSsd');
// Load the model
const model = await window.cocoSsd.load();
// Re-draw the image to clear the overlay text before detecting
ctx.drawImage(originalImg, 0, 0);
// Process the image
const predictions = await model.detect(canvas);
// Draw bounding boxes and labels for predictions meeting the threshold
predictions.forEach(prediction => {
if (prediction.score >= threshold) {
const [x, y, width, height] = prediction.bbox;
// Draw bounding box
ctx.strokeStyle = boxColor;
ctx.lineWidth = Math.max(2, Math.floor(canvas.width / 300));
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.stroke();
// Format text label (Class + Confidence Score)
const label = `${prediction.class} (${Math.round(prediction.score * 100)}%)`;
// Responsive font size calculation
const fontSize = Math.max(14, Math.floor(canvas.width / 50));
ctx.font = `bold ${fontSize}px sans-serif`;
ctx.textBaseline = 'top';
// Measure text to draw background box
const textWidth = ctx.measureText(label).width;
const textHeight = fontSize;
// Ensure label text remains inside the picture bounds
const textY = y > textHeight + 8 ? y - textHeight - 8 : y;
// Draw Label Background
ctx.fillStyle = boxColor;
ctx.fillRect(x, textY, textWidth + 8, textHeight + 8);
// Draw Label Text
ctx.fillStyle = textColor;
ctx.fillText(label, x + 4, textY + 4);
}
});
// If no predictions found, just leave original image
if (predictions.length === 0) {
ctx.drawImage(originalImg, 0, 0);
}
} catch (err) {
console.error("Image Object Detection encountered an error:", err);
// Draw an error indicator
ctx.drawImage(originalImg, 0, 0);
ctx.fillStyle = 'rgba(255, 0, 0, 0.6)';
ctx.fillRect(0, 0, canvas.width, 50);
ctx.fillStyle = '#ffffff';
ctx.font = '20px sans-serif';
ctx.textBaseline = 'middle';
ctx.fillText('Error loading detection model.', 15, 25);
}
})();
// Immediately return canvas. It will visually update when promises resolve.
return canvas;
}
Apply Changes