Star

Created With

linkConversión de la imagen a un foto-mosaico utilizando shaders.

linkProblem statement

Creación de un foto-mosaico de una imagen determinada a partir de una lista de imagenes definida mediante la utilización de shaders

linkBackground

En el campo de las imágenes y la fotografía, un fotomosaico es una imagen usualmente una fotografía que ha sido dividida en secciones rectangulares (usualmente del mismo tamaño), tal como es compuesto un mosaico tradicional, con la característica de que cada elemento del mosaico es reemplazado por otra fotografía con colores promedios apropiados al elemento de la imagen original. Cuando es vista en detalle, los píxeles individuales se ven como la imagen principal, sin embargo al verla como un todo, es posible apreciar que la imagen está compuesta por cientos de miles o incluso millones de imágenes.

Para la realizacion de este algoritmo de computacion visual se hizo uso de shaders desarrollados en GLSL el cual es un lenguaje de alto nivel de shader con una sintaxis basada en el lenguaje de programación C y diseñado específicamente para su uso dentro del entorno de OpenGL.

El algoritmo parte de un dataset de imagenes concatenadas de manera horizontal en un solo archivo .JPG ordenadas por su nivel de brillo percibido el cual fue calculado utilizando la libreria pillow en python.

1linkfrom PIL import Image

2linkfrom PIL import ImageStat

3linkimport math

4link

5linkdef brightness( im_file ):

6link im = Image.open(im_file)

7link stat = ImageStat.Stat(im)

8link r,g,b = stat.rms

9link return math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2))

Posteriormente la imagen original se recrea apartir de texturas 2D cuadradas de un color plano dependiendo del valor de la resolucion, el cual puede ser modificado interactivamente (ej. si la resolucion tiene un valor de 50 la imagen se divide en filas de 50 texturas 2D cuadradas).

Luego, se realiza el calculo del brillo de dichas texturas 2D y se encuentra la posicion aproximada dentro del dataset concatenado de las imagenes que conformarán el mosaico correspondiendo con dicho nivel de brillo para extraer la imagen especifica que ira ubicada en esa seccion del mosaico. Este proceso se repite con todos los cuadrados generados previamente hasta construir la imagen completa.

linkCode (solution) & results

*NOTA: la resolucion de la imagen, que se refiere al numero de imagenes por fila que conforman el mosaico, puede ser modificada con el selector en la esquina superior izquierda

1linklet mosaico;

2linklet mosaicDatasetImg;

3linklet originalImage;

4linklet showMosaico;

5linklet imagesMainPath = "/vc/docs/sketches/assets/image_mosaic/";

6linklet imgsPerRow = 100;

7linkconst numImagenes = 70;

8link

9linkfunction preload() {

10link originalImage = loadImage(imagesMainPath + "art-shaders.jpg");

11link mosaicDatasetImg = loadImage(imagesMainPath + "mosaicDataset.jpg");

12link mosaico = loadShader(

13link "/vc/docs/sketches/scripts/hardware/shader.vert",

14link "/vc/docs/sketches/scripts/hardware/photomosaic.frag"

15link );

16link}

17link

18linkfunction setup() {

19link setupSelect();

20link setupMosaic();

21link}

22link

23linkfunction setupSelect(){

24link sel = createSelect();

25link sel.position(15, 15);

26link sel.option(10);

27link sel.option(50);

28link sel.option(100);

29link sel.option(150);

30link sel.option(200);

31link sel.option(500);

32link sel.option(2000);

33link sel.option(10000);

34link sel.option(100000);

35link sel.option(1000000);

36link sel.option(10000000);

37link sel.option(100000000);

38link sel.selected(imgsPerRow);

39link sel.changed(mySelectEvent);

40link}

41link

42linkfunction mySelectEvent() {

43link imgsPerRow = sel.value();

44link mosaico.setUniform("imgsPerRow", imgsPerRow);

45link}

46link

47linkfunction setupMosaic() {

48link createCanvas(718, 900, WEBGL);

49link textureMode(NORMAL);

50link noStroke();

51link shader(mosaico);

52link mosaico.setUniform("originalImage", originalImage);

53link mosaico.setUniform("imgsPerRow", imgsPerRow);

54link mosaico.setUniform("numImagenes", numImagenes);

55link showMosaico = true;

56link mosaico.setUniform("showMosaico", showMosaico);

57link mosaico.setUniform("mosaicDatasetImg", mosaicDatasetImg);

58link}

59link

60linkfunction draw() {

61link background(33);

62link cover();

63link}

64link

65linkfunction cover() {

66link beginShape();

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

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

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

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

71link endShape(CLOSE);

72link}

73link

74linkfunction keyPressed() {

75link if (key === "1") {

76link showMosaico = !showMosaico;

77link mosaico.setUniform("showMosaico", showMosaico);

78link

79link if (showMosaico) {

80link setupSelect();

81link } else {

82link sel.remove();

83link }

84link }

85link}

1linkprecision mediump float;

2linkuniform sampler2D originalImage;

3linkuniform sampler2D mosaicDatasetImg;

4linkuniform bool showMosaico;

5linkuniform float imgsPerRow;

6linkuniform float numImagenes;

7link

8link// interpolated texcoord (same name and type as in vertex shader)

9linkvarying vec2 vTexCoord;

10linkvarying vec4 vVertexColor;

11link

12linkvoid main() {

13link vec2 mosaicDatasetImgCoord = vTexCoord*imgsPerRow;

14link vec2 originalImageCoord = floor(mosaicDatasetImgCoord);

15link mosaicDatasetImgCoord = mosaicDatasetImgCoord-originalImageCoord;

16link originalImageCoord = originalImageCoord*vec2(1.0)/vec2(imgsPerRow);

17link vec4 col = texture2D(originalImage,originalImageCoord);

18link float brightnessValue = dot(col.xyz, vec3(0.35, 0.35, 0.35));

19link

20link float temp = brightnessValue*(numImagenes);

21link float level = floor(temp);

22link

23link float scalingfactor = 1.0/numImagenes;

24link

25link float y0 = 0.0;

26link float x0 = (level-(numImagenes*(floor(level/numImagenes))))*scalingfactor;

27link

28link vec2 finalCord = (mosaicDatasetImgCoord*vec2(1.0)/vec2(numImagenes,1))+vec2(x0,y0);

29link vec4 finalColor = texture2D(mosaicDatasetImg,finalCord);

30link

31link gl_FragColor = showMosaico?finalColor:col;

32link}

linkConclusions & Future Work

Conversión de la imagen a un foto-mosaico utilizando shaders.Problem statementBackgroundCode (solution) & resultsConclusions & Future Work

Home

Workshopschevron_right
Imaging & Videochevron_right
Softwarechevron_right
Hardwarechevron_right
Renderingchevron_right
Algovischevron_right
Computer Graphicschevron_right
HCIchevron_right
P5 Code Snippetschevron_right
Memberschevron_right