Image edge detection with simple JavaScript

In this article we will discuss how to implement simple image edge detection in pure Java Script. The result of this source code is a gradient gray-scale image.

How it works?

We use the HTML5 canvas element to manipulate our source image. Then we apply a simple two-dimensional convolution with two 3×3 masks e.g.: Sobel operator or Prewitt detector.

The algorithm implements two helper functions conv3x and conv3y to deal with horizontal and vertical image edges.

The great deal about this family of boundary detectors is that they can produce strong and thin edges using Canny’s algorithm.

Example output

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

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

Source code

/**
* @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);
}

Conclusion

In this post we reveal how to do a simple edge detector in pure Java Script without dependencies and additional components. Although this algorithm is pretty fast it may not work so well for big pictures. For this reason, we recommend to take a look at fast edge detector by WebGL.


Gradient detection demo app

WEB APPLET

See how it works in the browser!


Related articles