Home » Blog » Image Processing » Image edge detection with simple JavaScript
source-code-edge-detection-java-script

Image edge detection with simple JavaScript

In this article we will discuss how to implement simple image edge detection in pure Java Script. The post reveals several techniques that are suitable for use in a web browser to solve edge detection tasks.

First, let’s start with direct pixel manipulation using the 2D rendering API of the HTML5 Canvas element.

Pure JavaScript and 2D Canvas Context

The source code below shows how to implement an edge detection algorithm using image gradient approximation in pure Java Script and CanvasRenderingContext2D.

How it works?

After putting image data into an HTML5 canvas element, we can retrieve the pixels from it using getImageData. This gives us access to the underlying image data and so we can apply various image processing algorithms on it.

The proposed source code extracts the image outlines using gradients approximation. The most popular algorithms from this family of edge detectors are Sobel operator and Prewitt.

The following sample code implements two helper functions, conv3x and conv3y, which extract horizontal and vertical image edges through a simple two-dimensional convolution.

/**
* @param data - input pixels data
* @param idx - the index of the central pixel
* @param w - image width (width*4 in case of RGBA)
* @param m - the gradient mask (for Sobel=[1, 2, 1])
*/
function conv3x(data, idx, w, m){
  return (m[0]*data[idx - w - 4] + m[1]*data[idx - 4] + m[2]*data[idx + w - 4]
      -m[0]*data[idx - w + 4] - m[1]*data[idx + 4] - m[2]*data[idx + 4 + 4]);
}

function conv3y(data, idx, w, m){
  return (m[0]*data[idx - w - 4] + m[1]*data[idx - w] + m[2]*data[idx - w + 4]
      -(m[0]*data[idx + w - 4] + m[1]*data[idx + w] + m[2]*data[idx + w + 4]));
}


/**
* @param pixels - Object of image parameters
* @param mask - gradient operator e.g. Prewitt, Sobel, Scharr, etc. 
*/
function gradient_internal(pixels, mask)
{
  var data = pixels.data;
  var w = pixels.width*4;
  var l = data.length - w - 4;
  var buff = new data.constructor(new ArrayBuffer(data.length));
  
  for (var i = w + 4; i < l; i+=4){
    var dx = conv3x(data, i, w, mask);
    var dy = conv3y(data, i, w, mask);
    buff[i] = buff[i + 1] = buff[i + 2] = Math.sqrt(dx*dx + dy*dy);
    buff[i + 3] = 255;
  }
  pixels.data.set(buff);
}

/**
* @param canvas - HTML5 Canvas elementFromPoint
*/
function gradient(canvas){
  var context = canvas.getContext('2d');
  var pixels = context.getImageData(0, 0, canvas.width,canvas.height);
  gradient_internal(pixels, [1, 2, 1]); // Apply Sobel operator
  context.putImageData(pixels, 0, 0);
}

The output of this source code is a gradient gray-scale image and it can easily apply different kind of edge detection mask (aka kernels). A nice feature of this family of boundary detectors is that they can produce strong and thin edges using Canny’s algorithm.

Example output

The picture below shows an example output of the Prewitt edge detector.

prewitt-gradient-detection-example
Example output of Prewitt operator

Edge Detection by Canvas Filter API

The Canvas Filter API is a relatively new addition to the web standard. Although this new feature is not mature it is currently supported by major web browsers like Google Chrome and Microsoft Edge.

Important Update: Since the initial publication of this article, it has come to light that the CanvasFilterAPI is no longer actively being developed by web browsers. While there may have been initial interest in this API, it appears to have been deprecated and there is no guarantee of future support for this API.

Essentially, this API is analogous to SVG filters, so they provide the convenience of using them as pure JavaScript code.

The following source snippet shows how we can use the Canvas Filters to implement edge detection through a simple 2D convolution.

function drawFrame(source){
  const canvas = document.querySelector("canvas");
  const context = canvas.getContext("2d");
  canvas.width = source.naturalWidth || source.videoWidth;
  canvas.height = source.naturalHeight || source.videoHeight;
  ctx.filter = new CanvasFilter([
      {
        filter: "convolveMatrix",
        kernelMatrix: [[0, 1, 0], [1, -4, 1], [0, 1, 0]],
         bias: 0,
         divisor: 1,
         preserveAlpha: "true",
      }
   ]);
  context.drawImage(source, 0, 0);
}

The output of the code snippet yields a contour image extracted using discrete approximations to the Laplace filter.

Example output

The following picture shows an example result of the algorithm.

Laplacian edge detector by SVG filters
Example result of Laplacian via Canvas Filter API

Other Resources

The following additional resources may interest you:

Conclusion

Image edge detection is a common task in the fields of image processing and computer graphics. In this post we reveal how to do a simple edge detector in pure Java Script without dependencies and additional components. Although these algorithms are quite fast, they may not work as well for large images. For this reason, you may take a look at fast edge detector by WebGL.

WEB APPLET

See how it works in the browser!

Gradient detection demo app

Transform Your Images: Explore Our Must-Have Tools!