Star

Created With

linkMosaic - Images

Previamente se realizó la implementación de un mosaico usando las herramientas de p5.js, si bien a nivel visual los resultados fueron bastantes sorprendentes, a nivel de eficiencia fueron bastantes deficientes, uno de los principales problemas fue el cambio de resolución lo cual resulto ineficiente y molesto para el usuario. Además, la implementación que usó un video fue realmente decepcionante y se decidió eliminar ya que afectaba el desempeño del proyecto en general.


En este punto se tienen tres retos principales, primero la implementación del mosaico usando el concepto de Shaders, segundo una mejora en la eficiencia del programa, y tercero la implementación del video. Los resultados de estos retos fueron los siguientes:

linkCode

A continuacion se muestran algunos fragmentos de código que permitirán comprender los detalles de la solucion planteada.

El siguiente fragmento de código permite obtener la distancia delta entre 2 colores, maneja el mismo concepto implemento anteriormente en JS

photomosaic.frag
1linkfloat calculateDeltaE(float r1, float g1, float b1,

2link float r2, float g2, float b2) {

3link float delta = (((r2-r1)*(r2-r1)) + ((g2-g1)*(g2-g1)) + ((b2-b1)*(b2-b1)));

4link return delta;

5link}

El codigo de P5.JS es el siguiente:

photomosaic.frag
1linklet image;

2linklet video;

3linklet om;

4linklet mosaic;

5linklet resolution;

6linklet video_on;

7linklet om_on;

8link

9linkfunction preload() {

10link

11link image = loadImage('mosaic/duck.png');

12link video = createVideo(['mosaic/duck.webm']);

13link om = loadImage('mosaic/html_colors.png');

14link mosaic = loadShader('mosaic/shader.vert','photomosaic.frag');

15link video.hide();

16link}

17link

18linkfunction setup() {

19link console.time("Mosaic: Hardware")

20link createCanvas(900, 506, WEBGL);

21link textureMode(NORMAL);

22link noStroke();

23link shader(mosaic);

24link

25link mosaic.setUniform('om', om);

26link

27link

28link om_on = createCheckbox('Mosaico', false);

29link om_on.changed(() => mosaic.setUniform('om_on', om_on.checked()));

30link om_on.position(10, 10);

31link

32link video_on = createCheckbox('Video', false);

33link video_on.changed(() => {

34link if (video_on.checked()) {

35link mosaic.setUniform('img', video);

36link video.loop();

37link } else {

38link mosaic.setUniform('img', image);

39link }

40link });

41link video_on.position(10, 30);

42link

43link

44link mosaic.setUniform('img', image);

45link resolution = createSlider(1, 200, 30, 1);

46link resolution.position(10, 50);

47link resolution.style('width', '80px');

48link resolution.input(()

49link => mosaic.setUniform('resolution', resolution.value()));

50link mosaic.setUniform('resolution', resolution.value());

51link

52link console.log({ resolution })

53link console.timeEnd("Mosaic: Hardware")

54link}

55link

56link

57link

58linkfunction draw() {

59link

60link background(33);

61link cover(true);

62link

63link}

64link

65link

66link

67linkfunction cover(texture = false) {

68link beginShape();

69link if (texture) {

70link vertex(-width / 2, -height / 2, 0, 0, 0);

71link vertex(width / 2, -height / 2, 0, 1, 0);

72link vertex(width / 2, height / 2, 0, 1, 1);

73link vertex(-width / 2, height / 2, 0, 0, 1);

74link }

75link else {

76link vertex(-width / 2, -height / 2, 0);

77link vertex(width / 2, -height / 2, 0);

78link vertex(width / 2, height / 2, 0);

79link vertex(-width / 2, height / 2, 0);

80link }

81link endShape(CLOSE);

82link}

83link

El siguiente fragmento de código es el fragment diseñado para la implementacion del mosaico

photomosaic.frag
1linkprecision mediump float;

2link

3link

4link uniform sampler2D img;

5link

6link uniform sampler2D om;

7link

8link

9link

10link uniform bool om_on;

11link uniform float resolution;

12link

13link

14link varying vec4 vVertexColor;

15link varying vec2 vTexCoord;

16link

17link float calculateDeltaE(float r1, float g1, float b1,

18link float r2, float g2, float b2);

19link

20link void main() {

21link

22link vec2 omCoord = vTexCoord * resolution;

23link vec2 texCoord = floor(omCoord);

24link

25link omCoord = omCoord - texCoord;

26link texCoord = texCoord * (vec2(1.0) / vec2(resolution));

27link

28link

29link vec4 imgTexel = texture2D(img, texCoord);

30link

31link if(om_on) {

32link vec2 coords = vec2(texCoord.x, texCoord.y);

33link vec4 actualPixel = texture2D(img, coords);

34link float r = actualPixel.r;

35link float g = actualPixel.g;

36link float b = actualPixel.b;

37link

38link float min = calculateDeltaE(0.0,0.0,0.0,r,g,b);

39link vec4 omTexel = texture2D(om,

40link (omCoord*(vec2(0.04, 0.1666)))+ vec2(0.0, 0.0) );

41link

42link if(min > calculateDeltaE( 0.0, 0.0, 0.0, r, g, b)){

43link min = calculateDeltaE( 0.0, 0.0, 0.0, r, g, b);

44link omTexel = texture2D(om,

45link (omCoord*(vec2(0.04, 0.16666))) + vec2( 0.0, 0) );

46link }

47link

48link

49link if(min > calculateDeltaE( 0.0, 0.0, 0.5019607843137255, r, g, b)){

50link min = calculateDeltaE( 0.0, 0.0, 0.5019607843137255, r, g, b);

51link omTexel = texture2D(om,

52link (omCoord*(vec2(0.04, 0.16666))) + vec2( 0.04, 0) );

53link }

54link

55link

56link if(min > calculateDeltaE( 0.0, 0.0, 0.5450980392156862, r, g, b)){

57link min = calculateDeltaE( 0.0, 0.0, 0.5450980392156862, r, g, b);

58link omTexel = texture2D(om,

59link (omCoord*(vec2(0.04, 0.16666))) + vec2( 0.08, 0) );

60link }

61link

62link

63link ...

64link ...

65link ...

66link ...

67link ...

68link

69link

70link if(min > calculateDeltaE( 1.0, 1.0, 0.9411764705882353, r, g, b)){

71link min = calculateDeltaE( 1.0, 1.0, 0.9411764705882353, r, g, b);

72link omTexel = texture2D(om,

73link (omCoord*(vec2(0.04, 0.16666))) + vec2( 0.44, 0.8333) );

74link }

75link

76link

77link if(min > calculateDeltaE( 1.0, 1.0, 1.0, r, g, b)){

78link min = calculateDeltaE( 1.0, 1.0, 1.0, r, g, b);

79link omTexel = texture2D(om,

80link (omCoord*(vec2(0.04, 0.16666))) + vec2( 0.48, 0.8333) );

81link }

82link

83link

84link

85link gl_FragColor = omTexel;

86link

87link

88link }

89link else {

90link gl_FragColor = imgTexel;

91link }

92link }

93link

94link

95link float calculateDeltaE(float r1, float g1, float b1,

96link float r2, float g2, float b2) {

97link float delta = (((r2-r1)*(r2-r1)) + ((g2-g1)*(g2-g1)) + ((b2-b1)*(b2-b1)));

98link return delta;

99link }

100link}

El banco de imagenes que permitio realizar el mosaico es el siguiente:

Por fines practicos el banco de imagenes fue unido en una simple imagen, la cual fue usada como textura.



linkResult

El resultado de todo el proceso es el siguiente

linkReferencia

Herramienta usada para creacion del sprite LINK

Mosaic - ImagesCodeResultReferencia

Home

Workshopschevron_right
Imaging & Videochevron_right
Softwarechevron_right
Hardwarechevron_right
Renderingchevron_right
GLobal illuminationchevron_right

Rasterisation

P5 Code Snippetschevron_right
Memberschevron_right