Star

Created With

linkImage Kernels

linkBackground

El kernel de una imagen es una pequeña matriz cuadrada de tamaño impar que, por medio de la convolución entre el kernel y la imagen, se utiliza para aplicar distintos efectos en la imagen. La convolución es el proceso en el cual se suma cada píxel de la imagen con sus vecinos locales, teniendo en cuenta los pesos indicados por el kernel. De esta forma, si tenemos la matriz de píxeles y el kernel

p=[149191190164195200150185194]k=[010151010]p=\begin{bmatrix}149 & 191 & 190 \\164 & 195 & 200 \\150 & 185 & 194 \end{bmatrix} k=\begin{bmatrix}0 & -1 & 0 \\-1 & 5 & -1 \\0 & -1 & 0 \end{bmatrix}1

y deseamos obtener la convolución del píxel central (195), obtenemos el resultado:

(1911)+(1641)+(1955)+(2001)+(1851)=235(191\ast -1) + (164\ast -1) + (195\ast 5) + (200\ast -1) + (185\ast -1) = 2351

Así, para aplicar el filtro deseado, se toma cada uno de los píxeles de la imagen original y se reemplazan por el píxel obtenido al realizar su respectiva convolución con el kernel.

linkCode & Results

linkFilters

A continuación se realiza la descripción de 4 kernels y se muestra el resultado de su convolución con una imagen.

Filtro que da la ilusión de profundidad y enfatiza la diferencia entre pixeles.

[210111012]\begin{bmatrix}-2 & -1 & 0 \\-1 & 1 & 1 \\0 & 1 & 2 \end{bmatrix}1

Filtro que desenfatiza las diferencias entre los pixeles, logrando un efecto borroso en la imagen.

[0.110.110.110.110.110.110.110.110.11]\begin{bmatrix}0.11 & 0.11 & 0.11 \\0.11 & 0.11 & 0.11 \\0.11 & 0.11 & 0.11 \end{bmatrix}1

Filtro que resalta diferencias de intensidad importantes entre los pixeles. De esta forma, un píxel cuyos píxeles vecinos tengan una intensidad similar, se verá negro al aplicar el filtro; mientras que un un píxel cuyos vecinos tengan una intensidad bastante diferente, se verá blanco.

[111181111]\begin{bmatrix}-1 & -1 & -1 \\-1 & 8 & -1 \\-1 & -1 & -1 \end{bmatrix}1

Filtro que enfatiza las diferencias entre los píxeles adyacentes. Con esto, se obtiene una imagen más vívida.

[010151010]\begin{bmatrix}0 & -1 & 0 \\-1 & 5 & -1 \\0 & -1 & 0 \end{bmatrix}1
convolution.js
1linklet img;

2linklet v = 1.0 / 9.0;

3link

4linklet emboss = [

5link [-2, -1, 0],

6link [-1, 1, 1],

7link [0, 1, 2]

8link];

9link

10linklet blurM = [

11link [v, v, v],

12link [v, v, v],

13link [v, v, v]

14link];

15link

16linklet outline = [

17link [-1, -1, -1],

18link [-1, 8, -1],

19link [-1, -1, -1]

20link];

21link

22linklet sharpen = [

23link [0, -1, 0],

24link [-1, 5, -1],

25link [0, -1, 0]

26link];

27link

28linkfunction preload() {

29link img = loadImage("/vc/docs/sketches/workshops/imaging/BabyYoda.jpg");

30link}

31link

32linkfunction setup() {

33link createCanvas(800, 550);

34link img.resize(400, 275);

35link noLoop();

36link}

37link

38linkfunction draw() {

39link

40link

41link img.loadPixels();

42link

43link eImg = createImage(img.width, img.height);

44link bImg = createImage(img.width, img.height);

45link oImg = createImage(img.width, img.height);

46link sImg = createImage(img.width, img.height);

47link

48link eImg.loadPixels();

49link for (let x = 1; x < img.width; x++) {

50link for (let y = 1; y < img.height; y++) {

51link let c = convolution(x, y, emboss);

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

53link

54link eImg.pixels[index] = red(c);

55link eImg.pixels[index + 1] = green(c);

56link eImg.pixels[index + 2] = blue(c);

57link eImg.pixels[index + 3] = alpha(c);

58link }

59link }

60link eImg.updatePixels();

61link image(eImg, 0, 0);

62link

63link bImg.loadPixels();

64link for (let x = 1; x < img.width; x++) {

65link for (let y = 1; y < img.height; y++) {

66link let c = convolution(x, y, blurM);

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

68link

69link bImg.pixels[index] = red(c);

70link bImg.pixels[index + 1] = green(c);

71link bImg.pixels[index + 2] = blue(c);

72link bImg.pixels[index + 3] = alpha(c);

73link }

74link }

75link bImg.updatePixels();

76link image(bImg, 400, 0);

77link

78link

79link oImg.loadPixels();

80link for (let x = 1; x < img.width; x++) {

81link for (let y = 1; y < img.height; y++) {

82link let c = convolution(x, y, outline);

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

84link

85link oImg.pixels[index] = red(c);

86link oImg.pixels[index + 1] = green(c);

87link oImg.pixels[index + 2] = blue(c);

88link oImg.pixels[index + 3] = alpha(c);

89link }

90link }

91link oImg.updatePixels();

92link image(oImg, 0, 275);

93link

94link sImg.loadPixels();

95link for (let x = 1; x < img.width; x++) {

96link for (let y = 1; y < img.height; y++) {

97link let c = convolution(x, y, sharpen);

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

99link

100link sImg.pixels[index] = red(c);

101link sImg.pixels[index + 1] = green(c);

102link sImg.pixels[index + 2] = blue(c);

103link sImg.pixels[index + 3] = alpha(c);

104link }

105link }

106link sImg.updatePixels();

107link image(sImg, 400, 275);

108link

109link fill(255, 255, 255);

110link textSize(32);

111link text('Emboss', 270, 30);

112link text('Outline', 280, 310);

113link text('Blur', 730, 30);

114link text('Sharpen', 665, 310);

115link

116link}

117link

118linkfunction convolution(x, y, matrix) {

119link let rtotal = 0;

120link let gtotal = 0;

121link let btotal = 0;

122link

123link for (kx = -1; kx <= 1; kx++) {

124link for (ky = -1; ky <= 1; ky++) {

125link let xpos = x + kx;

126link let ypos = y + ky;

127link let r = 0;

128link let g = 0;

129link let b = 0;

130link

131link if ((xpos >= 0 && xpos < img.width) && (ypos >= 0 || ypos < img.height)) {

132link let index = 4 * (xpos + img.width * ypos);

133link r = img.pixels[index];

134link g = img.pixels[index + 1];

135link b = img.pixels[index + 2];

136link }

137link

138link rtotal += matrix[kx + 1][ky + 1] * r;

139link gtotal += matrix[kx + 1][ky + 1] * g;

140link btotal += matrix[kx + 1][ky + 1] * b;

141link }

142link }

143link

144link rtotal = constrain(rtotal, 0, 255);

145link gtotal = constrain(gtotal, 0, 255);

146link btotal = constrain(btotal, 0, 255);

147link

148link return color(rtotal, gtotal, btotal);

149link}

linkSobels

La aplicación de filtros no es el único uso que se le da a los kernels, pues estos también se utilizan para la "Extracción de características" de una imagen. Sobel, por ejemplo, es un tipo de kernel que se utiliza en el procesamiento de imágenes, especialmente en algoritmos de detección de bordes. En total existen 4 tipos de sobel, que se describen y se muestran a continuación.

Se utiliza para mostrar únicamente las diferencias entre un píxel con los pixeles superiores adyacentes.

[121000121]\begin{bmatrix}1 & 2 & 1 \\0 & 0 & 0 \\-1 & -2 & -1 \end{bmatrix}1

Se utiliza para mostrar únicamente las diferencias entre un píxel con los pixeles posteriores adyacentes.

[101202101]\begin{bmatrix}-1 & 0 & 1 \\-2 & 0 & 2 \\-1 & 0 & 1 \end{bmatrix}1

Se utiliza para mostrar únicamente las diferencias entre un píxel con los pixeles inferiores adyacentes.

[121000121]\begin{bmatrix}-1 & -2 & -1 \\0 & 0 & 0 \\1 & 2 & 1 \end{bmatrix}1

Se utiliza para mostrar únicamente las diferencias entre un píxel con los pixeles anteriores adyacentes.

[101202101]\begin{bmatrix}1 & 0 & -1 \\2 & 0 & -2 \\1 & 0 & -1 \end{bmatrix}1
sobels.js
1linklet img;

2link

3linklet topS = [

4link [1, 2, 1],

5link [0, 0, 0],

6link [-1, -2, -1]

7link];

8link

9linklet rigthS = [

10link [-1, 0, 1],

11link [-2, 0, 2],

12link [-1, 0, 1]

13link];

14link

15linklet bottomS = [

16link [-1, -2, -1],

17link [0, 0, 0],

18link [1, 2, 1]

19link];

20link

21linklet leftS = [

22link [1, 0, -1],

23link [2, 0, -2],

24link [1, 0, -1]

25link];

26link

27linkfunction preload() {

28link img = loadImage("/vc/docs/sketches/workshops/imaging/BabyYoda.jpg");

29link}

30link

31linkfunction setup() {

32link createCanvas(800, 550);

33link img.resize(400, 275);

34link noLoop();

35link}

36link

37linkfunction draw() {

38link

39link img.loadPixels();

40link

41link tImg = createImage(img.width, img.height);

42link rImg = createImage(img.width, img.height);

43link bImg = createImage(img.width, img.height);

44link lImg = createImage(img.width, img.height);

45link

46link tImg.loadPixels();

47link for (let x = 1; x < img.width; x++) {

48link for (let y = 1; y < img.height; y++) {

49link let c = convolution(x, y, topS);

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

51link

52link tImg.pixels[index] = red(c);

53link tImg.pixels[index + 1] = green(c);

54link tImg.pixels[index + 2] = blue(c);

55link tImg.pixels[index + 3] = alpha(c);

56link }

57link }

58link tImg.updatePixels();

59link image(tImg, 0, 0);

60link

61link rImg.loadPixels();

62link for (let x = 1; x < img.width; x++) {

63link for (let y = 1; y < img.height; y++) {

64link let c = convolution(x, y, rigthS);

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

66link

67link rImg.pixels[index] = red(c);

68link rImg.pixels[index + 1] = green(c);

69link rImg.pixels[index + 2] = blue(c);

70link rImg.pixels[index + 3] = alpha(c);

71link }

72link }

73link rImg.updatePixels();

74link image(rImg, 400, 0);

75link

76link

77link bImg.loadPixels();

78link for (let x = 1; x < img.width; x++) {

79link for (let y = 1; y < img.height; y++) {

80link let c = convolution(x, y, bottomS);

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

82link

83link bImg.pixels[index] = red(c);

84link bImg.pixels[index + 1] = green(c);

85link bImg.pixels[index + 2] = blue(c);

86link bImg.pixels[index + 3] = alpha(c);

87link }

88link }

89link bImg.updatePixels();

90link image(bImg, 0, 275);

91link

92link lImg.loadPixels();

93link for (let x = 1; x < img.width; x++) {

94link for (let y = 1; y < img.height; y++) {

95link let c = convolution(x, y, leftS);

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

97link

98link lImg.pixels[index] = red(c);

99link lImg.pixels[index + 1] = green(c);

100link lImg.pixels[index + 2] = blue(c);

101link lImg.pixels[index + 3] = alpha(c);

102link }

103link }

104link lImg.updatePixels();

105link image(lImg, 400, 275);

106link

107link fill(255, 255, 255);

108link textSize(32);

109link text('Top', 330, 30);

110link text('Bottom', 280, 310);

111link text('Right', 710, 30);

112link text('Left', 730, 310);

113link

114link}

115link

116linkfunction convolution(x, y, matrix) {

117link let rtotal = 0;

118link let gtotal = 0;

119link let btotal = 0;

120link

121link for (kx = -1; kx <= 1; kx++) {

122link for (ky = -1; ky <= 1; ky++) {

123link let xpos = x + kx;

124link let ypos = y + ky;

125link let r = 0;

126link let g = 0;

127link let b = 0;

128link

129link if ((xpos >= 0 && xpos < img.width) && (ypos >= 0 || ypos < img.height)) {

130link let index = 4 * (xpos + img.width * ypos);

131link r = img.pixels[index];

132link g = img.pixels[index + 1];

133link b = img.pixels[index + 2];

134link }

135link

136link rtotal += matrix[kx + 1][ky + 1] * r;

137link gtotal += matrix[kx + 1][ky + 1] * g;

138link btotal += matrix[kx + 1][ky + 1] * b;

139link }

140link }

141link

142link rtotal = constrain(rtotal, 0, 255);

143link gtotal = constrain(gtotal, 0, 255);

144link btotal = constrain(btotal, 0, 255);

145link

146link return color(rtotal, gtotal, btotal);

147link}

linkKernels on Videos

Adicionalmente, estos kernel pueden ser utilizados en el procesamiento de videos.

videos.js
1linklet fingers;

2link

3linklet outline = [

4link [-1, -1, -1],

5link [-1, 8, -1],

6link [-1, -1, -1]

7link];

8link

9linklet topSobel = [

10link [1, 2, 1],

11link [0, 0, 0],

12link [-1, -2, -1]

13link];

14link

15linklet emboss = [

16link [-2, -1, 0],

17link [-1, 1, 1],

18link [0, 1, 2]

19link];

20link

21linklet sharpen = [

22link [0, -1, 0],

23link [-1, 5, -1],

24link [0, -1, 0]

25link];

26link

27link

28linkfunction preload() {

29link fingers = createVideo("/vc/docs/sketches/fingers.webm");

30link}

31link

32linkfunction mousePressed() {

33link fingers.loop();

34link}

35link

36linkfunction setup() {

37link createCanvas(640, 480);

38link fingers.hide();

39link}

40link

41linkfunction draw() {

42link

43link fingers.loadPixels();

44link loadPixels();

45link

46link let count = 0;

47link

48link for (let y = 1; y < fingers.height; y++) {

49link count = count + 1;

50link for (let x = 1; x < fingers.width; x++) {

51link

52link let c = convolution(x, y, emboss);

53link let index = 4 * (x + fingers.width * (y + count));

54link

55link pixels[index] = red(c);

56link pixels[index + 1] = green(c);

57link pixels[index + 2] = blue(c);

58link pixels[index + 3] = alpha(c);

59link }

60link }

61link

62link count = 0;

63link

64link for (let y = 1; y < fingers.height; y++) {

65link count = count + 1;

66link for (let x = 1; x < fingers.width; x++) {

67link

68link let c = convolution(x, y, topSobel);

69link let index = 4 * ((x + 320) + fingers.width * (y + count));

70link

71link pixels[index] = red(c);

72link pixels[index + 1] = green(c);

73link pixels[index + 2] = blue(c);

74link pixels[index + 3] = alpha(c);

75link }

76link }

77link

78link count = 0;

79link

80link for (let y = 1; y < fingers.height; y++) {

81link count = count + 1;

82link for (let x = 1; x < fingers.width; x++) {

83link

84link let c = convolution(x, y, outline);

85link let index = 4 * (x + fingers.width * (y + 500 + count));

86link

87link pixels[index] = red(c);

88link pixels[index + 1] = green(c);

89link pixels[index + 2] = blue(c);

90link pixels[index + 3] = alpha(c);

91link }

92link }

93link

94link count = 0;

95link

96link for (let y = 1; y < fingers.height; y++) {

97link count = count + 1;

98link for (let x = 1; x < fingers.width; x++) {

99link

100link let c = convolution(x, y, sharpen);

101link let index = 4 * ((x + 320) + fingers.width * (y + 500 + count));

102link

103link pixels[index] = red(c);

104link pixels[index + 1] = green(c);

105link pixels[index + 2] = blue(c);

106link pixels[index + 3] = alpha(c);

107link }

108link }

109link updatePixels();

110link

111link fill(255, 255, 255);

112link textSize(25);

113link strokeWeight(0.1);

114link text('Emboss', 220, 40);

115link text('Outline', 230, 280);

116link text('Top Sobel', 520, 40);

117link text('Sharpen', 535, 280);

118link

119link stroke(255, 255, 255);

120link strokeWeight(11);

121link line(0, 246, 640, 246);

122link strokeWeight(5);

123link line(320, 0, 320, 480);

124link

125link}

126link

127linkfunction convolution(x, y, matrix) {

128link let rtotal = 0;

129link let gtotal = 0;

130link let btotal = 0;

131link

132link for (kx = -1; kx <= 1; kx++) {

133link for (ky = -1; ky <= 1; ky++) {

134link let xpos = x + kx;

135link let ypos = y + ky;

136link let r = 0;

137link let g = 0;

138link let b = 0;

139link

140link if ((xpos >= 0 && xpos < fingers.width) && (ypos >= 0 || ypos < fingers.height)) {

141link let index = 4 * (xpos + fingers.width * ypos);

142link r = fingers.pixels[index];

143link g = fingers.pixels[index + 1];

144link b = fingers.pixels[index + 2];

145link }

146link

147link rtotal += matrix[kx + 1][ky + 1] * r;

148link gtotal += matrix[kx + 1][ky + 1] * g;

149link btotal += matrix[kx + 1][ky + 1] * b;

150link }

151link }

152link

153link rtotal = constrain(rtotal, 0, 255);

154link gtotal = constrain(gtotal, 0, 255);

155link btotal = constrain(btotal, 0, 255);

156link

157link return color(rtotal, gtotal, btotal);

158link}

Image KernelsBackgroundCode & ResultsFiltersSobelsKernels on Videos

Home

Workshopschevron_right
Imaging & Videochevron_right
Softwarechevron_right
Hardwarechevron_right
Renderingchevron_right
GLobal illuminationchevron_right

Rasterisation

P5 Code Snippetschevron_right
Memberschevron_right