Wenn Sie ein Schwarzweißbild in einem vernünftigen verlustfreien Format als Eingabe verwenden, geben Sie ASCII-Grafiken aus, die dem Eingabebild so nahe wie möglich kommen.
Regeln
- Es dürfen nur Linefeeds und ASCII-Bytes 32-127 verwendet werden.
- Das Eingabebild wird so beschnitten, dass das Bild nicht von einem Leerzeichen umgeben ist.
- Einreichungen müssen in der Lage sein, den gesamten Wertungskorpus in weniger als 5 Minuten zu vervollständigen.
- Nur roher Text ist akzeptabel. Keine Rich-Text-Formate.
- Die für die Bewertung verwendete Schriftart ist 20 pt Linux Libertine .
- Die Ausgabe-Textdatei muss, wenn sie wie unten beschrieben in ein Bild konvertiert wird, die gleichen Abmessungen wie das Eingabebild haben und darf in keiner der beiden Dimensionen 30 Pixel enthalten.
Wertung
Diese Bilder werden für die Bewertung verwendet:
Sie können eine ZIP - Datei der Bilder herunterladen hier .
Einsendungen sollten nicht für dieses Korpus optimiert werden. Sie sollten vielmehr für 8 beliebige Schwarzweißbilder mit ähnlichen Abmessungen funktionieren. Ich behalte mir das Recht vor, die Bilder im Korpus zu ändern, wenn ich vermute, dass die Einsendungen für diese spezifischen Bilder optimiert werden.
Das Scoring wird über dieses Skript durchgeführt:
#!/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)))
Der Bewertungsprozess:
- Führen Sie die Übermittlung für jedes Korpusbild aus und geben Sie die Ergebnisse in
.txt
Dateien mit demselben Stamm wie die Korpusdatei aus (manuell durchgeführt). - Konvertieren Sie jede Textdatei in ein PNG-Bild, indem Sie eine 20-Punkt-Schriftart verwenden und Leerzeichen entfernen.
- Passen Sie die Größe des Ergebnisbilds mit Lanczos-Resampling an die Abmessungen des Originalbilds an.
- Vergleichen Sie jedes Textbild mit dem Originalbild mit
dssim
. - Geben Sie die dssim-Punktzahl für jede Textdatei aus.
- Geben Sie die durchschnittliche Punktzahl aus.
Strukturelle Ähnlichkeit (die Metrik, anhand derer dssim
Punktzahlen berechnet werden) ist eine Metrik, die auf dem menschlichen Sehen und der Objektidentifikation in Bildern basiert. Um es einfach auszudrücken: Wenn zwei Bilder Menschen ähnlich sehen, werden sie (wahrscheinlich) eine niedrige Punktzahl von haben dssim
.
Die gewinnende Einsendung ist die Einsendung mit der niedrigsten Durchschnittspunktzahl.
.txt
Dateien" verstehen ? Soll das Programm Text ausgeben, der an eine Datei weitergeleitet wird, oder sollten wir eine Datei direkt ausgeben?