Please bookmark this page to avoid losing your image tool!

Website Interface Image Identifier

(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.
function processImage(originalImg, blockSizeStr = "12", varianceThresholdStr = "80", mergeRadiusStr = "2") {
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height;
    const ctx = canvas.getContext('2d');
    
    // Draw original image to canvas
    ctx.drawImage(originalImg, 0, 0);

    const bSize = parseInt(blockSizeStr, 10) || 12;
    const thresh = parseFloat(varianceThresholdStr) || 80;
    const mRad = parseInt(mergeRadiusStr, 10) || 2;

    const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imgData.data;

    const cols = Math.ceil(canvas.width / bSize);
    const rows = Math.ceil(canvas.height / bSize);
    const blocks = new Uint8Array(cols * rows);

    // Step 1: Detect active blocks based on color variance
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            let sum = 0;
            let sqSum = 0;
            let count = 0;
            let maxGray = 0;
            let minGray = 255;
            for(let y = r * bSize; y < (r+1) * bSize && y < canvas.height; y++) {
                for(let x = c * bSize; x < (c+1) * bSize && x < canvas.width; x++) {
                    let i = (y * canvas.width + x) * 4;
                    // Calculate grayscale luminosity
                    let gray = 0.299 * data[i] + 0.587 * data[i+1] + 0.114 * data[i+2];
                    sum += gray;
                    sqSum += gray * gray;
                    count++;
                }
            }
            if (count > 0) {
                let mean = sum / count;
                let variance = (sqSum / count) - (mean * mean);
                // Flag blocks with significant variance (edges, text, boundaries)
                if (variance > thresh) {
                    blocks[r * cols + c] = 1;
                }
            }
        }
    }

    // Step 2: Connected Component Labeling via DFS
    const labels = new Int32Array(cols * rows);
    let nextLabel = 1;

    function dfs(startR, startC, label) {
        const stack = [[startR, startC]];
        labels[startR * cols + startC] = label;
        
        while(stack.length > 0) {
            const [currR, currC] = stack.pop();
            
            // Search in a window based on mergeRadius to cluster sparse elements (e.g., text)
            for (let dr = -mRad; dr <= mRad; dr++) {
                for (let dc = -mRad; dc <= mRad; dc++) {
                    let nr = currR + dr;
                    let nc = currC + dc;
                    if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) {
                        let nIdx = nr * cols + nc;
                        if (blocks[nIdx] === 1 && labels[nIdx] === 0) {
                            labels[nIdx] = label;
                            stack.push([nr, nc]);
                        }
                    }
                }
            }
        }
    }

    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            let idx = r * cols + c;
            if (blocks[idx] === 1 && labels[idx] === 0) {
                dfs(r, c, nextLabel++);
            }
        }
    }

    // Step 3: Find bounding boxes for each labeled component
    const bboxes = {};
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            let label = labels[r * cols + c];
            if (label > 0) {
                if (!bboxes[label]) {
                    bboxes[label] = { minR: r, maxR: r, minC: c, maxC: c, count: 0 };
                }
                bboxes[label].minR = Math.min(bboxes[label].minR, r);
                bboxes[label].maxR = Math.max(bboxes[label].maxR, r);
                bboxes[label].minC = Math.min(bboxes[label].minC, c);
                bboxes[label].maxC = Math.max(bboxes[label].maxC, c);
                bboxes[label].count++;
            }
        }
    }

    // Step 4: Analyze and render identified UI elements
    ctx.lineWidth = 2;
    const colors = ['#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231', '#911eb4', '#46f0f0', '#f032e6', '#bcf60c', '#fabebe', '#008080', '#e6beff', '#9a6324', '#fffac8'];
    let elCount = 0;

    for (let label in bboxes) {
        const box = bboxes[label];
        
        let x = box.minC * bSize;
        let y = box.minR * bSize;
        let w = (box.maxC - box.minC + 1) * bSize;
        let h = (box.maxR - box.minR + 1) * bSize;
        
        // Add aesthetic padding around elements
        let px = Math.max(0, x - bSize/2);
        let py = Math.max(0, y - bSize/2);
        let pw = Math.min(canvas.width - px, w + bSize);
        let ph = Math.min(canvas.height - py, h + bSize);
        
        // Skip bounding boxes that cover almost the entire page (like background images)
        if (pw >= canvas.width * 0.95 && ph >= canvas.height * 0.95) {
            continue;
        }

        // Infer UI element type based on dimensions & proportions
        let type = "Container";
        let ratio = pw / ph;
        
        if (pw >= canvas.width * 0.8 && ph <= 120) {
            type = "Navbar / Header";
        } else if (pw >= canvas.width * 0.7 && ph >= canvas.height * 0.6) {
            type = "Main Content Segment";
        } else if (ratio > 10 && ph <= 30) {
            type = "Divider / Line";
        } else if (ratio > 3.5 && ph <= 60) {
            type = "Text / Input";
        } else if (ratio < 1.5 && ratio > 0.6) {
            if (pw <= 65 && ph <= 65) type = "Icon / Avatar";
            else if (pw >= 120 && ph >= 120) type = "Image";
            else type = "Card";
        } else if (ratio >= 1.5 && ratio <= 4) {
            if (ph <= 55) type = "Button / Tab";
            else type = "Container / Panel";
        } else {
            type = "UI Element";
        }

        const color = colors[elCount % colors.length];
        
        // Draw main bounding box
        ctx.strokeStyle = color;
        ctx.strokeRect(px, py, pw, ph);
        
        // Draw crosshair-style corners for a "scanner" / "identifier" visual theme
        ctx.beginPath();
        let cLen = Math.min(10, pw/4, ph/4);
        ctx.moveTo(px, py + cLen); ctx.lineTo(px, py); ctx.lineTo(px + cLen, py);
        ctx.moveTo(px + pw - cLen, py); ctx.lineTo(px + pw, py); ctx.lineTo(px + pw, py + cLen);
        ctx.moveTo(px, py + ph - cLen); ctx.lineTo(px, py + ph); ctx.lineTo(px + cLen, py + ph);
        ctx.moveTo(px + pw - cLen, py + ph); ctx.lineTo(px + pw, py + ph); ctx.lineTo(px + pw, py + ph - cLen);
        ctx.stroke();

        ctx.fillStyle = color;
        ctx.globalAlpha = 0.15;
        ctx.fillRect(px, py, pw, ph);
        ctx.globalAlpha = 1.0;
        
        // Calculate appropriate font size for label
        let fontSize = Math.max(12, Math.floor(Math.min(pw, ph) * 0.15));
        fontSize = Math.min(fontSize, 16); 
        ctx.font = `bold ${fontSize}px Arial, sans-serif`;
        
        // Draw label background pill
        let textMetrics = ctx.measureText(type);
        let ty = py - fontSize - 6;
        if (ty < 0) ty = py; // Flow downwards if hitting top boundary
        
        ctx.fillStyle = color;
        ctx.fillRect(px - 1, ty, textMetrics.width + 12, fontSize + 8);
        
        // Draw label text
        ctx.fillStyle = '#111111'; // High contrast text over pastel colors
        ctx.fillText(type, px + 5, ty + fontSize + 2);

        elCount++;
    }

    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 Website Interface Image Identifier is a tool designed to analyze screenshots of websites and automatically detect various user interface (UI) components. By analyzing color variance and spatial relationships, the tool identifies and labels elements such as navigation bars, buttons, text inputs, icons, cards, and main content segments. This tool is useful for web designers, UX researchers, and developers who want to visually audit page layouts, study component distribution, or perform rapid structural analysis of web interfaces.

Leave a Reply

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