Please bookmark this page to avoid losing your image tool!

Image Edge Detection Filter Overlayer

(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, filterType = 'sobel', threshold = 128, overlayColor = 'rgba(255, 0, 0, 0.7)', blurRadius = 1) {

    // 1. Canvas Setup
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Draw original image on the canvas which will serve as the background
    ctx.drawImage(originalImg, 0, 0);

    // Get the image data to work with
    const imageData = ctx.getImageData(0, 0, width, height);
    const data = imageData.data;

    // 2. Grayscale Conversion
    // We create both a raw array for convolution and an ImageData object for blurring.
    const grayDataForConv = new Uint8ClampedArray(width * height);
    const grayImageDataForBlur = ctx.createImageData(width, height);
    const grayDataForBlur = grayImageDataForBlur.data;

    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        
        const index = i / 4;
        grayDataForConv[index] = gray;
        
        // Populate the ImageData for canvas-based blurring
        grayDataForBlur[i] = gray;
        grayDataForBlur[i + 1] = gray;
        grayDataForBlur[i + 2] = gray;
        grayDataForBlur[i + 3] = 255;
    }

    // 3. Optional Pre-processing Blur
    // Applying a blur helps reduce noise and leads to cleaner edge detection.
    let sourceData = grayDataForConv;
    if (blurRadius > 0) {
        const offscreenCanvas = document.createElement('canvas');
        offscreenCanvas.width = width;
        offscreenCanvas.height = height;
        const offscreenCtx = offscreenCanvas.getContext('2d');
        
        offscreenCtx.putImageData(grayImageDataForBlur, 0, 0);
        offscreenCtx.filter = `blur(${blurRadius}px)`;
        // Drawing onto itself is required to apply the filter
        offscreenCtx.drawImage(offscreenCanvas, 0, 0);

        const blurredImageData = offscreenCtx.getImageData(0, 0, width, height);
        const blurredData = blurredImageData.data;
        
        // Extract the blurred grayscale values back into a simple array
        const blurredGrayData = new Uint8ClampedArray(width * height);
        for(let i = 0; i < blurredData.length; i += 4) {
            blurredGrayData[i/4] = blurredData[i];
        }
        sourceData = blurredGrayData;
    }

    // 4. Edge Detection (Convolution)
    const kernels = {
        sobel: {
            x: [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]],
            y: [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]
        },
        prewitt: {
            x: [[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]],
            y: [[-1, -1, -1], [0, 0, 0], [1, 1, 1]]
        },
        laplacian: {
            // Laplacian uses a single kernel
            single: [[0, 1, 0], [1, -4, 1], [0, 1, 0]]
        }
    };

    const selectedKernel = kernels[filterType.toLowerCase()] || kernels.sobel;
    const gradientData = new Float32Array(width * height);
    
    // Iterate over each pixel (excluding borders)
    for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
            let magnitude = 0;

            if (selectedKernel.single) {
                // Handle single-kernel filters like Laplacian
                let convValue = 0;
                 for (let ky = -1; ky <= 1; ky++) {
                    for (let kx = -1; kx <= 1; kx++) {
                        const val = sourceData[(y + ky) * width + (x + kx)];
                        convValue += val * selectedKernel.single[ky + 1][kx + 1];
                    }
                }
                magnitude = Math.abs(convValue);
            } else {
                // Handle dual-kernel filters like Sobel and Prewitt
                let gx = 0;
                let gy = 0;
                for (let ky = -1; ky <= 1; ky++) {
                    for (let kx = -1; kx <= 1; kx++) {
                        const val = sourceData[(y + ky) * width + (x + kx)];
                        gx += val * selectedKernel.x[ky + 1][kx + 1];
                        gy += val * selectedKernel.y[ky + 1][kx + 1];
                    }
                }
                magnitude = Math.sqrt(gx * gx + gy * gy);
            }
            
            const index = y * width + x;
            gradientData[index] = magnitude;
        }
    }

    // 5. Create Overlay based on Threshold
    // First, parse the overlayColor string into RGBA components
    let r = 255, g = 0, b = 0, a = 178; // Default: semi-transparent red
    try {
        const colorParserCanvas = document.createElement('canvas');
        colorParserCanvas.width = 1;
        colorParserCanvas.height = 1;
        const cpcCtx = colorParserCanvas.getContext('2d');
        cpcCtx.fillStyle = overlayColor;
        cpcCtx.fillRect(0, 0, 1, 1);
        [r, g, b, a] = cpcCtx.getImageData(0, 0, 1, 1).data;
    } catch(e) {
        console.error("Invalid overlayColor provided:", overlayColor);
    }

    const overlayImageData = ctx.createImageData(width, height);
    const overlayData = overlayImageData.data;

    for (let i = 0; i < gradientData.length; i++) {
        if (gradientData[i] > threshold) {
            overlayData[i * 4] = r;
            overlayData[i * 4 + 1] = g;
            overlayData[i * 4 + 2] = b;
            overlayData[i * 4 + 3] = a;
        }
    }

    // 6. Composite the final image
    // Put the overlay data onto a temporary canvas, then draw it over the main one.
    const overlayCanvas = document.createElement('canvas');
    overlayCanvas.width = width;
    overlayCanvas.height = height;
    overlayCanvas.getContext('2d').putImageData(overlayImageData, 0, 0);
    ctx.drawImage(overlayCanvas, 0, 0);

    // 7. Return the final canvas
    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 Edge Detection Filter Overlayer is a web tool that applies various edge detection filters to images, enhancing their features by highlighting edges. Users can select from different filter types, such as Sobel or Prewitt, and customize parameters like threshold and overlay color. This tool can be useful in fields such as graphic design, image processing, and computer vision, where extracting outlines and contours from images is essential for tasks such as automated object detection, artistic effects, or data analysis. The feature to apply a blur before edge detection helps reduce noise for cleaner results.

Leave a Reply

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