Star

Created With

linkEdge detection filters

This filters has the purpose of detect edges on the images, and are widely used on machine learning applications, because they help to extract important features of the images. Here we are going to test three different kernels in order to compare them.

For this and the following sections of kernel filters we are going to use the following image (By Michael Plotke - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=24301122)

linkBasic edge detection matrix

w=(101000101)w = \begin{pmatrix} 1 & 0 & -1 \\ 0 & 0 & 0 \\ -1 & 0 & 1 \end{pmatrix}1

Here you can see the filter applied to an image, and check how the edge detection extract only the shapes that could be related to edges on the image.

The markdown of the above sketch looks like:

1link> :P5 sketch=/docs/sketches/first_convolution.js, width=256, height=256

And the p5 sketch that applies the convolution on the image is the following:

first_convolution.js
1linklet w = [[1, 0, -1], [0, 0, 0], [-1, 0, 1]];

2linklet img;

3linklet copy;

4link

5linkfunction preload() {

6link copy = loadImage('/vc/docs/sketches/lenna.png');

7link}

8link

9linkfunction setup() {

10link createCanvas(256, 256);

11link img = createImage(copy.width, copy.height);

12link}

13link

14linkfunction convolution(image, x, y, kernel, size, width, height, d) {

15link let rConv = 0;

16link let gConv = 0;

17link let bConv = 0;

18link let offset = floor(size / 2);

19link for (let i = 0; i < size; i++) {

20link for (let j = 0; j < size; j++) {

21link

22link let xpos = x + j - offset;

23link let ypos = y + i - offset;

24link

25link let index = (xpos + image.width * ypos * d) * 4;

26link

27link if (!(width <= xpos || height <= ypos || xpos < 0 || ypos < 0)) {

28link rConv += image.pixels[index + 0] * kernel[i][j];

29link gConv += image.pixels[index + 1] * kernel[i][j];

30link bConv += image.pixels[index + 2] * kernel[i][j];

31link }

32link

33link }

34link }

35link return [rConv, gConv, bConv];

36link}

37link

38linkfunction draw() {

39link image(img, 0, 0, 256, 256);

40link img.loadPixels();

41link copy.loadPixels();

42link let d = pixelDensity();

43link

44link for (let y = 0; y < img.height*d; y++) {

45link for (let x = 0; x < img.width*d; x++) {

46link let result = convolution(copy, x, y, w, 3, img.width*d, img.height*d, d);

47link let index = (x + y * img.width*d) * 4;

48link img.pixels[index + 0] = result[0];

49link img.pixels[index + 1] = result[1];

50link img.pixels[index + 2] = result[2];

51link img.pixels[index + 3] = 255;

52link }

53link }

54link img.updatePixels();

55link

56link}

On the code we create a copy of the image, in order to take it as the base image and create an empty image that will act as the filtered image, then we iterate over the base image and create the convolution pixel by pixel.

And here the filter applied to a video.

The markdown of the above sketch looks like:

1link> :P5 sketch=/docs/sketches/first_convolution_video.js, width=256, height=256

And the p5 sketch that applies the convolution on the video is the following:

first_convolution_video.js
1linklet w = [[1, 0, -1], [0, 0, 0], [-1, 0, 1]];

2linklet video;

3linklet copy;

4link

5linkfunction preload() {

6link video = createVideo(['/vc/docs/sketches/fingers.mov', '/vc/docs/sketches/fingers.webm']);

7link video.hide();

8link}

9link

10linkfunction setup() {

11link createCanvas(256, 256);

12link video.loop();

13link}

14link

15linkfunction convolution(image, x, y, kernel, size, width, height, d) {

16link let rConv = 0;

17link let gConv = 0;

18link let bConv = 0;

19link let offset = floor(size / 2);

20link for (let i = 0; i < size; i++) {

21link for (let j = 0; j < size; j++) {

22link

23link let xpos = x + j - offset;

24link let ypos = y + i - offset;

25link

26link let index = (xpos + image.width * ypos * d) * 4;

27link

28link if (!(width <= xpos || height <= ypos || xpos < 0 || ypos < 0)) {

29link rConv += image.pixels[index + 0] * kernel[i][j];

30link gConv += image.pixels[index + 1] * kernel[i][j];

31link bConv += image.pixels[index + 2] * kernel[i][j];

32link }

33link

34link }

35link }

36link return [rConv, gConv, bConv];

37link}

38link

39linkfunction draw() {

40link image(video, 0, 0, 256, 256);

41link let copy = createImage(video.width, video.height);

42link video.loadPixels();

43link let d = pixelDensity();

44link for (let i = 0; i < video.pixels.length; i++) {

45link copy.pixels[i] = video.pixels[i];

46link }

47link

48link for (let y = 0; y < video.height*d; y++) {

49link for (let x = 0; x < video.width*d; x++) {

50link let result = convolution(copy, x, y, w, 3, video.width*d, video.height*d, d);

51link let index = (x + y * video.width*d) * 4;

52link video.pixels[index + 0] = result[0];

53link video.pixels[index + 1] = result[1];

54link video.pixels[index + 2] = result[2];

55link video.pixels[index + 3] = 255;

56link }

57link }

58link video.updatePixels();

59link

60link}

On the code we load the video and create a copy of the actual frame each time that the draw function is called, then with that copy as ground of truth we alter the current frame of the video with the convolution of the copy and the filter.

With this matrix we can see a soft edge detection that works fine for images but not so well for videos because the movements start to appear fuzzy.

linkFist Laplacian matrix

Laplacian matrices has been used a lot for edge detection because of their incredible properties and results on these tasks.

w=(010141010)w = \begin{pmatrix} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \end{pmatrix}1

The result of the filter on an image is the following.

The result of the filter on a video is the following.

As we can see the edge detection has improved a lot with this matrix on the image, but it stills a bit fuzzy on the video.

linkSecond Laplace matrix

w=(111181111)w = \begin{pmatrix} -1 & -1 & -1 \\ -1 & 8 & -1 \\ -1 & -1 & -1 \end{pmatrix}1

The result of the filter on an image is the following.

The result of the filter on a video is the following.

This laplacian matrix has the best performance on the video, but on the image it takes many details of the textures as edges, which could affect the detection.

Edge detection filtersBasic edge detection matrixFist Laplacian matrixSecond Laplace matrix

Home

Workshopschevron_right
Software Image & Video Processingchevron_right

Problem Statement and Background Image and Video filters Image Photographic-Mosaic Ascii art

Kernel (Image processing)chevron_right

Conclusions and References

Hardware Image & Video Processingchevron_right

Problem Statement and Background Image and Video filters Ascii art Photo Mosaic

Kernel (Image processing)chevron_right

Conclusions and References

Renderingchevron_right

Computer Graphics HCI

P5 Code Snippetschevron_right
Peoplechevron_right