Please bookmark this page to avoid losing your image tool!

Image Face Detection Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg) {
    const FACEAPI_SCRIPT_URL = 'https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js';
    const MODEL_URL = 'https://cdn.jsdelivr.net/gh/justadudewhohacks/face-api.js/weights';

    // Validate originalImg: must be a loaded HTMLImageElement
    if (!(originalImg instanceof HTMLImageElement) || originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
        console.error("processImage: Provided originalImg is not a valid, loaded HTMLImageElement.", originalImg);
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 300; // Default error canvas size
        errorCanvas.height = 150;
        const ctx = errorCanvas.getContext('2d');
        ctx.fillStyle = '#f0f0f0';
        ctx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
        ctx.fillStyle = 'red';
        ctx.font = `bold ${Math.min(18, errorCanvas.height * 0.12)}px Arial`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('Invalid or Unloaded Image', errorCanvas.width / 2, errorCanvas.height / 2);
        return errorCanvas;
    }

    // Helper to ensure face-api.js is loaded
    const ensureFaceApiLoaded = () => {
        return new Promise((resolve, reject) => {
            // Check if faceapi is already loaded and seems initialized
            if (typeof faceapi !== 'undefined' && faceapi.nets && faceapi.nets.ssdMobilenetv1) {
                resolve();
                return;
            }

            // If loading is already in Pprogress by another call, wait for its promise
            if (window.faceApiLoadingPromise instanceof Promise) {
                // This ensures concurrent calls don't try to load the script multiple times
                return window.faceApiLoadingPromise.then(resolve).catch(reject);
            }

            // This is the first call, or a call after a previous load attempt failed and cleared the promise
            let script = document.querySelector(`script[src="${FACEAPI_SCRIPT_URL}"]`);
            if (!script) {
                script = document.createElement('script');
                script.src = FACEAPI_SCRIPT_URL;
                script.async = true; // Load asynchronously
                document.head.appendChild(script);
            }
            
            // Create a global promise to track the loading status of face-api.js
            window.faceApiLoadingPromise = new Promise((res, rej) => {
                script.onload = () => {
                    if (typeof faceapi !== 'undefined' && faceapi.nets && faceapi.nets.ssdMobilenetv1) {
                        res(); // Successfully loaded and initialized
                    } else {
                        // Script loaded, but faceapi global is not as expected
                        window.faceApiLoadingPromise = null; // Clear promise to allow a retry on next processImage call
                        rej(new Error('face-api.js loaded but `faceapi` global is incomplete or invalid.'));
                    }
                };
                script.onerror = (errEvent) => {
                    console.error("Script load error for face-api.js:", errEvent);
                    window.faceApiLoadingPromise = null; // Clear promise for retry
                    if(script && script.parentNode) { // Optional: remove failed script tag
                        script.parentNode.removeChild(script);
                    }
                    rej(new Error(`Failed to load script: ${FACEAPI_SCRIPT_URL}. Check network or CDN status.`));
                };
            });
            
            return window.faceApiLoadingPromise.then(resolve).catch(reject);
        });
    };
    
    // Helper to display errors on a canvas
    const displayErrorOnCanvas = (targetCanvas, message) => {
        const ctx = targetCanvas.getContext('2d');
        
        let barHeight = Math.min(60, targetCanvas.height * 0.25, targetCanvas.width * 0.8);
        barHeight = Math.max(30, barHeight); // Ensure minimum height
        
        ctx.fillStyle = 'rgba(200, 0, 0, 0.85)'; // Semi-transparent red bar
        ctx.fillRect(0, targetCanvas.height / 2 - barHeight / 2, targetCanvas.width, barHeight);
        
        ctx.fillStyle = 'white';
        // Responsive font size, ensuring it fits and is readable
        ctx.font = `bold ${Math.max(12, Math.min(18, barHeight * 0.35))}px Arial`; 
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(message, targetCanvas.width / 2, targetCanvas.height / 2);
    };

    // Try to load library and models
    try {
        await ensureFaceApiLoaded();
        // Load the SSD Mobilenet V1 model for face detection if not already loaded
        if (!faceapi.nets.ssdMobilenetv1.isLoaded) {
            await faceapi.nets.ssdMobilenetv1.loadFromUri(MODEL_URL);
        }
        // For other features like landmarks, expressions, age/gender, load other models:
        // if (!faceapi.nets.faceLandmark68Net.isLoaded) await faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL);
        // if (!faceapi.nets.faceExpressionNet.isLoaded) await faceapi.nets.faceExpressionNet.loadFromUri(MODEL_URL);
        // if (!faceapi.nets.ageGenderNet.isLoaded) await faceapi.nets.ageGenderNet.loadFromUri(MODEL_URL);

    } catch (error) {
        console.error("Initialization Error (library/models):", error.message);
        // Create a new canvas, draw the original image, and overlay the error message
        const initErrorCanvas = document.createElement('canvas');
        initErrorCanvas.width = originalImg.naturalWidth;
        initErrorCanvas.height = originalImg.naturalHeight;
        const initCtx = initErrorCanvas.getContext('2d');
        initCtx.drawImage(originalImg, 0, 0, initErrorCanvas.width, initErrorCanvas.height);
        
        const friendlyMessage = error.message.includes('load script') || error.message.includes('faceapi global')
            ? 'Error: AI library failed to load.'
            : 'Error: AI models failed to load.';
        displayErrorOnCanvas(initErrorCanvas, friendlyMessage);
        return initErrorCanvas;
    }

    // Create canvas for output
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;
    const ctx = canvas.getContext('2d');

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    try {
        // Perform face detection
        // SsdMobilenetv1Options can set minConfidence (default 0.5), maxResults etc.
        const detections = await faceapi.detectAllFaces(originalImg, new faceapi.SsdMobilenetv1Options()); 

        if (detections && detections.length > 0) {
            // Draw bounding boxes for detected faces
            detections.forEach(detection => {
                const box = detection.box; // { x, y, width, height }
                
                ctx.strokeStyle = 'lime'; // Bright green for visibility
                // Dynamic line width based on image size, with min/max
                ctx.lineWidth = Math.max(2, Math.round(Math.min(canvas.width, canvas.height) * 0.007));
                ctx.beginPath();
                ctx.rect(box.x, box.y, box.width, box.height);
                ctx.stroke();
            });
        } else {
            // Display a message if no faces are detected
            let barHeight = Math.min(40, canvas.height * 0.1);
            barHeight = Math.max(20, barHeight); // Min height for the message bar
            
            ctx.fillStyle = 'rgba(0, 0, 0, 0.6)'; // Semi-transparent dark bar
            ctx.fillRect(0, canvas.height - barHeight, canvas.width, barHeight); // At the bottom
            
            ctx.fillStyle = 'white';
            // Dynamic font size for the message
            ctx.font = `bold ${Math.max(12, Math.min(16, barHeight * 0.5))}px Arial`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText('No faces detected.', canvas.width / 2, canvas.height - barHeight / 2);
        }
    } catch (detectError) {
        console.error("Face Detection Error:", detectError);
        // Display detection error on the main canvas (which already has the image)
        displayErrorOnCanvas(canvas, 'Error during face detection.');
    }

    return canvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Face Detection Tool allows users to upload images and automatically detect faces present in them. Utilizing advanced face detection technology, the tool draws bounding boxes around identified faces, providing a visual representation of the detected individuals. This tool is beneficial for various applications, such as social media management for quickly identifying individuals in photos, enhancing security systems by analyzing images for faces, and assisting in image organization by allowing users to detect and categorize photos based on facial presence.

Leave a Reply

Your email address will not be published. Required fields are marked *