Data un'immagine in bianco e nero in qualsiasi formato senza perdita ragionevole come input, genera un'arte ASCII che sia il più vicino possibile all'immagine di input.
Regole
- È possibile utilizzare solo linefeed e byte ASCII 32-127.
- L'immagine in ingresso verrà ritagliata in modo che non vi siano spazi esterni estranei che circondano l'immagine.
- Gli invii devono essere in grado di completare l'intero corpus di punteggio in meno di 5 minuti.
- È accettabile solo testo non elaborato; nessun formato RTF.
- Il carattere utilizzato nel punteggio è Libertine Linux a 20 punti .
- Il file di testo di output, quando convertito in un'immagine come descritto di seguito, deve avere le stesse dimensioni dell'immagine di input, entro 30 pixel in entrambe le dimensioni.
punteggio
Queste immagini verranno utilizzate per il punteggio:
Puoi scaricare un file zip delle immagini qui .
I contributi non dovrebbero essere ottimizzati per questo corpus; piuttosto, dovrebbero funzionare per qualsiasi 8 immagini in bianco e nero di dimensioni simili. Mi riservo il diritto di modificare le immagini nel corpus se sospetto che gli invii vengano ottimizzati per queste immagini specifiche.
Il punteggio verrà eseguito tramite questo script:
#!/usr/bin/env python
from __future__ import print_function
from __future__ import division
# modified from http://stackoverflow.com/a/29775654/2508324
# requires Linux Libertine fonts - get them at https://sourceforge.net/projects/linuxlibertine/files/linuxlibertine/5.3.0/
# requires dssim - get it at https://github.com/pornel/dssim
import PIL
import PIL.Image
import PIL.ImageFont
import PIL.ImageOps
import PIL.ImageDraw
import pathlib
import os
import subprocess
import sys
PIXEL_ON = 0 # PIL color to use for "on"
PIXEL_OFF = 255 # PIL color to use for "off"
def dssim_score(src_path, image_path):
out = subprocess.check_output(['dssim', src_path, image_path])
return float(out.split()[0])
def text_image(text_path):
"""Convert text file to a grayscale image with black characters on a white background.
arguments:
text_path - the content of this file will be converted to an image
"""
grayscale = 'L'
# parse the file into lines
with open(str(text_path)) as text_file: # can throw FileNotFoundError
lines = tuple(l.rstrip() for l in text_file.readlines())
# choose a font (you can see more detail in my library on github)
large_font = 20 # get better resolution with larger size
if os.name == 'posix':
font_path = '/usr/share/fonts/linux-libertine/LinLibertineO.otf'
else:
font_path = 'LinLibertine_DRah.ttf'
try:
font = PIL.ImageFont.truetype(font_path, size=large_font)
except IOError:
print('Could not use Libertine font, exiting...')
exit()
# make the background image based on the combination of font and lines
pt2px = lambda pt: int(round(pt * 96.0 / 72)) # convert points to pixels
max_width_line = max(lines, key=lambda s: font.getsize(s)[0])
# max height is adjusted down because it's too large visually for spacing
test_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
max_height = pt2px(font.getsize(test_string)[1])
max_width = pt2px(font.getsize(max_width_line)[0])
height = max_height * len(lines) # perfect or a little oversized
width = int(round(max_width + 40)) # a little oversized
image = PIL.Image.new(grayscale, (width, height), color=PIXEL_OFF)
draw = PIL.ImageDraw.Draw(image)
# draw each line of text
vertical_position = 5
horizontal_position = 5
line_spacing = int(round(max_height * 0.8)) # reduced spacing seems better
for line in lines:
draw.text((horizontal_position, vertical_position),
line, fill=PIXEL_ON, font=font)
vertical_position += line_spacing
# crop the text
c_box = PIL.ImageOps.invert(image).getbbox()
image = image.crop(c_box)
return image
if __name__ == '__main__':
compare_dir = pathlib.PurePath(sys.argv[1])
corpus_dir = pathlib.PurePath(sys.argv[2])
images = []
scores = []
for txtfile in os.listdir(str(compare_dir)):
fname = pathlib.PurePath(sys.argv[1]).joinpath(txtfile)
if fname.suffix != '.txt':
continue
imgpath = fname.with_suffix('.png')
corpname = corpus_dir.joinpath(imgpath.name)
img = text_image(str(fname))
corpimg = PIL.Image.open(str(corpname))
img = img.resize(corpimg.size, PIL.Image.LANCZOS)
corpimg.close()
img.save(str(imgpath), 'png')
img.close()
images.append(str(imgpath))
score = dssim_score(str(corpname), str(imgpath))
print('{}: {}'.format(corpname, score))
scores.append(score)
print('Score: {}'.format(sum(scores)/len(scores)))
Il processo di punteggio:
- Esegui l'invio per ogni immagine corpus, inviando i risultati a
.txt
file con lo stesso gambo del file corpus (fatto manualmente). - Converti ogni file di testo in un'immagine PNG, usando un carattere a 20 punti, ritagliando uno spazio bianco.
- Ridimensiona l'immagine risultante alle dimensioni dell'immagine originale usando il ricampionamento di Lanczos.
- Confronta ogni immagine di testo con l'immagine originale usando
dssim
. - Emette il punteggio dssim per ciascun file di testo.
- Emette il punteggio medio.
La similarità strutturale (la metrica con cui dssim
calcola i punteggi) è una metrica basata sulla visione umana e sull'identificazione degli oggetti nelle immagini. Per dirla chiaramente: se due immagini sembrano simili agli umani, avranno (probabilmente) un punteggio basso da dssim
.
La proposta vincente sarà quella con il punteggio medio più basso.
.txt
file"? Il programma dovrebbe generare il testo che verrà reindirizzato a un file o dovremmo produrre direttamente un file?