Star

Created With

linkAscii in Hardware

linkProblem Statement

Image conversion to ascii art.

linkBackground

linkProcessing the dataset

This implementation uses the list given by Paul Bourke in Character representation of grey scale images. The "Standard" character ramp for grey scale pictures, black -> white.

"$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. "

An image of 64x64 is created for each character. Then, the images are concatenated and passed to the shaders. The shaders have the logic to select the part of this new large image to choose the proper character. The creation of the characters images was developed in Python, code below:

1linkimport cv2

2linkfrom glob import glob

3linkfrom PIL import Image,ImageStat, ImageDraw,>>ImageFont

4linkimport math

5link

6linkdef brightness( img_file ):

7link im = Image.open(img_file)

8link stat = ImageStat.Stat(im)

9link r,g,b = stat.rms

10link bright= math.sqrt(0.241*(r**2) + 0.691*(g**2) >>+ 0.068*(b**2))

11link return { 'brightness': bright, 'filename': >>img_file }

12link

13linkdef orderByBrightness(files):

14link dataset= []

15link for f in files:

16link img_brightness = brightness(f)

17link dataset.append(img_brightness)

18link return sorted(dataset, key = lambda i: i>>['brightness'])

19link

20linkdef createCharFromImage(char):

21link W, H = (64,64)

22link img = Image.new('RGB', (W, H), color = (255, >>255, 255))

23link d = ImageDraw.Draw(img)

24link w, h = d.textsize(char)

25link fnt = ImageFont.truetype("./font2.otf", 70)

26link d.text(((W-w)/2,0), char, font=fnt, fill=(0,0,>>0))

27link img.save('characters/_{}_.jpg'.format(char))

28link

29linkcharacters = "$@B%8&>>WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft()1{}[]?-_>>+~<>i!lI;:,\"^`'. "

30link

31linkfor char in characters:

32link createCharFromImage(char)

33link

34linkimg_w = None

35linkfor i, char in enumerate(characters):

36link file = 'characters/_{}_.jpg'.format(char)

37link if i==0:

38link img_w = cv2.imread(file)

39link continue

40link img = cv2.imread(file)

41link img_w = cv2.hconcat([img_w, img])

42link

43linkcv2.imwrite('Characters.jpg', img_w)

linkFinal Results

linkImage

ascii.js
1linklet mosaic;

2linklet symbol1;

3linklet myImage;

4linklet debug;

5linklet slider;

6linklet slider2;

7linkconst WIDTH_PIXEL = 64;

8linkconst HEIGHT_PIXEL = 64;

9linkconst NUM_IMAGES = 70;

10link

11link

12linkfunction preload() {

13link myImage = loadImage("/vc/docs/sketches/images/mandrill.png");

14link symbol1 = loadImage("/vc/docs/sketches/images/Characters.jpg");

15link mosaic = loadShader(

16link "/vc/docs/sketches/shaders/shader.vert",

17link "/vc/docs/sketches/shaders/hardwarePhotomosaic.frag"

18link );

19link}

20link

21linkfunction setup() {

22link slider = createSlider(1, 9, 1,1);

23link slider.position(10, 30);

24link slider.style('width', '100px');

25link slider2 = createSlider(0,5,3,1);

26link slider2.position(10,10);

27link slider2.style('width', '100px');

28link createCanvas(600, 600, WEBGL);

29link textureMode(NORMAL);

30link noStroke();

31link shader(mosaic);

32link mosaic.setUniform("image", myImage);

33link mosaic.setUniform("WIDTH_PIXEL", WIDTH_PIXEL);

34link mosaic.setUniform("NUM_IMAGES", NUM_IMAGES);

35link mosaic.setUniform("HEIGHT_PIXEL", HEIGHT_PIXEL);

36link debug = true;

37link mosaic.setUniform("debug", debug);

38link let img = symbol1;

39link mosaic.setUniform("symbol1", img);

40link}

41link

42linkfunction draw() {

43link const pow = Math.pow(10,slider2.value())

44link mosaic.setUniform("resolution", pow*slider.value());

45link background(33);

46link cover(true);

47link}

48link

49linkfunction cover(texture = false) {

50link beginShape();

51link if (texture) {

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

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

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

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

56link } else {

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

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

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

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

61link }

62link endShape(CLOSE);

63link}

64link

65linkfunction keyPressed() {

66link if (key === "d") {

67link debug = !debug;

68link mosaic.setUniform("debug", debug);

69link }

70link}

shader.vert
1linkprecision highp float;

2linkattribute vec3 aPosition;

3linkattribute vec2 aTexCoord;

4linkattribute vec4 aVertexColor;

5linkuniform mat4 uProjectionMatrix;

6linkuniform mat4 uModelViewMatrix;

7linkvarying vec4 vVertexColor;

8linkvarying vec2 vTexCoord;

9link

10linkvoid main() {

11link vVertexColor = aVertexColor;

12link vTexCoord = aTexCoord;

13link gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0);

14link}

hardwareAscii.vert
1linkprecision mediump float;

2linkuniform sampler2D image;

3linkuniform sampler2D symbol1;

4linkuniform bool debug;

5linkuniform float resolution;

6linkuniform float NUM_IMAGES;

7linkuniform float WIDTH_PIXEL;

8linkuniform float HEIGHT_PIXEL;

9linkvarying vec2 vTexCoord;

10linkvarying vec4 vVertexColor;

11link

12linkfloat module( float x , float y ){

13link float flt_res = x-(y*(floor(x/y)));

14link return flt_res;

15link}

16link

17linkvoid main() {

18link vec2 symbolCoord=vTexCoord*resolution;

19link vec2 imageCoord=floor(symbolCoord);

20link symbolCoord=symbolCoord-imageCoord;

21link imageCoord=imageCoord*vec2(1.0)/vec2(resolution);

22link vec4 col=texture2D(image,imageCoord);

23link float brightness = dot(col.xyz, vec3(0.2126, 0.7152, 0.0722));

24link float temp=brightness*(NUM_IMAGES);

25link float level=floor(temp);

26link float scalingfactor = 1.0/NUM_IMAGES;

27link float y0=0.0;

28link float x0= module(level,NUM_IMAGES)*scalingfactor;

29link vec2 myCoord=(symbolCoord*vec2(1.0)/vec2(NUM_IMAGES,1))+vec2(x0,y0);

30link vec4 finalColor=texture2D(symbol1,myCoord);

31link gl_FragColor = debug?finalColor:col;

32link}

linkVideo

There are two sliders that allow configuring the resolution. The First Slider decide the pow(1,100,1.000,10.000,100.000).The Second Slider is a number from 1 to 10. This configuration lets the users visualize multiple resolutions that generate a variety of results

asciiCamara.js
1linklet mosaic;

2linklet symbol1;

3linklet myImage;

4linklet debug;

5linklet slider;

6linklet slider2;

7linkconst WIDTH_PIXEL = 64;

8linkconst HEIGHT_PIXEL = 64;

9linkconst NUM_IMAGES = 70;

10link

11link

12linkfunction preload() {

13link myImage = createCapture(VIDEO);

14link myImage.hide();

15link symbol1 = loadImage("/vc/docs/sketches/images/Characters.jpg");

16link mosaic = loadShader(

17link "/vc/docs/sketches/shaders/shader.vert",

18link "/vc/docs/sketches/shaders/hardwarePhotomosaic.frag"

19link );

20link}

21link

22linkfunction setup() {

23link slider = createSlider(1, 9, 1,1);

24link slider.position(10, 30);

25link slider.style('width', '100px');

26link slider2 = createSlider(0,5,3,1);

27link slider2.position(10,10);

28link slider2.style('width', '100px');

29link createCanvas(600, 600, WEBGL);

30link textureMode(NORMAL);

31link noStroke();

32link shader(mosaic);

33link mosaic.setUniform("image", myImage);

34link mosaic.setUniform("WIDTH_PIXEL", WIDTH_PIXEL);

35link mosaic.setUniform("NUM_IMAGES", NUM_IMAGES);

36link mosaic.setUniform("HEIGHT_PIXEL", HEIGHT_PIXEL);

37link debug = true;

38link mosaic.setUniform("debug", debug);

39link let img = symbol1;

40link mosaic.setUniform("symbol1", img);

41link}

42link

43linkfunction draw() {

44link const pow = Math.pow(10,slider2.value())

45link mosaic.setUniform("resolution", pow*slider.value());

46link background(33);

47link cover(true);

48link}

49link

50linkfunction cover(texture = false) {

51link beginShape();

52link if (texture) {

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

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

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

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

57link } else {

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

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

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

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

62link }

63link endShape(CLOSE);

64link}

65link

66linkfunction keyPressed() {

67link if (key === "d") {

68link debug = !debug;

69link mosaic.setUniform("debug", debug);

70link }

71link}

shader.vert
1linkprecision highp float;

2linkattribute vec3 aPosition;

3linkattribute vec2 aTexCoord;

4linkattribute vec4 aVertexColor;

5linkuniform mat4 uProjectionMatrix;

6linkuniform mat4 uModelViewMatrix;

7linkvarying vec4 vVertexColor;

8linkvarying vec2 vTexCoord;

9link

10linkvoid main() {

11link vVertexColor = aVertexColor;

12link vTexCoord = aTexCoord;

13link gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition, 1.0);

14link}

hardwareAscii.vert
1linkprecision mediump float;

2linkuniform sampler2D image;

3linkuniform sampler2D symbol1;

4linkuniform bool debug;

5linkuniform float resolution;

6linkuniform float NUM_IMAGES;

7linkuniform float WIDTH_PIXEL;

8linkuniform float HEIGHT_PIXEL;

9linkvarying vec2 vTexCoord;

10linkvarying vec4 vVertexColor;

11link

12linkfloat module( float x , float y ){

13link float flt_res = x-(y*(floor(x/y)));

14link return flt_res;

15link}

16link

17linkvoid main() {

18link vec2 symbolCoord=vTexCoord*resolution;

19link vec2 imageCoord=floor(symbolCoord);

20link symbolCoord=symbolCoord-imageCoord;

21link imageCoord=imageCoord*vec2(1.0)/vec2(resolution);

22link vec4 col=texture2D(image,imageCoord);

23link float brightness = dot(col.xyz, vec3(0.2126, 0.7152, 0.0722));

24link float temp=brightness*(NUM_IMAGES);

25link float level=floor(temp);

26link float scalingfactor = 1.0/NUM_IMAGES;

27link float y0=0.0;

28link float x0= module(level,NUM_IMAGES)*scalingfactor;

29link vec2 myCoord=(symbolCoord*vec2(1.0)/vec2(NUM_IMAGES,1))+vec2(x0,y0);

30link vec4 finalColor=texture2D(symbol1,myCoord);

31link gl_FragColor = debug?finalColor:col;

32link}

linkReferences

Ascii in HardwareProblem StatementBackgroundProcessing the datasetFinal ResultsImageVideoReferences

Home

Workshopschevron_right
Imaging & Videochevron_right
Sofwarechevron_right
Hardwarechevron_right

Benchmark

Renderingchevron_right
Algovischevron_right
Computer Graphicschevron_right
HCIchevron_right
P5 Code Snippetschevron_right
Memberschevron_right