Đưa ra một hình ảnh đen trắng ở bất kỳ định dạng lossless hợp lý nào làm đầu vào, nghệ thuật ASCII đầu ra càng gần với hình ảnh đầu vào càng tốt.
Quy tắc
- Chỉ các nguồn cấp dữ liệu và các byte ASCII 32-127 có thể được sử dụng.
- Hình ảnh đầu vào sẽ được cắt để không có khoảng trắng bên ngoài xung quanh hình ảnh.
- Đệ trình phải có thể hoàn thành toàn bộ kho điểm trong vòng dưới 5 phút.
- Chỉ văn bản thô được chấp nhận; không có định dạng văn bản phong phú.
- Phông chữ được sử dụng trong tính điểm là Linux Libertine 20 pt .
- Tệp văn bản đầu ra, khi được chuyển đổi thành hình ảnh như được mô tả bên dưới, phải có cùng kích thước với hình ảnh đầu vào, trong phạm vi 30 pixel ở cả hai chiều.
Chấm điểm
Những hình ảnh này sẽ được sử dụng để chấm điểm:
Bạn có thể tải về một zipfile của hình ảnh ở đây .
Đệ trình không nên được tối ưu hóa cho kho văn bản này; thay vào đó, chúng nên hoạt động cho bất kỳ 8 hình ảnh đen trắng có kích thước tương tự. Tôi bảo lưu quyền thay đổi hình ảnh trong kho văn bản nếu tôi nghi ngờ việc gửi đang được tối ưu hóa cho những hình ảnh cụ thể này.
Việc chấm điểm sẽ được thực hiện thông qua kịch bản này:
#!/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)))
Quy trình chấm điểm:
- Chạy đệ trình cho mỗi hình ảnh kho văn bản, xuất kết quả cho
.txt
các tệp có cùng gốc với tệp kho văn bản (được thực hiện thủ công). - Chuyển đổi từng tệp văn bản thành hình ảnh PNG, sử dụng phông chữ 20 điểm, cắt xén khoảng trắng.
- Thay đổi kích thước hình ảnh kết quả theo kích thước của hình ảnh gốc bằng cách sử dụng mô hình lại Lanczos.
- So sánh từng hình ảnh văn bản với hình ảnh gốc bằng cách sử dụng
dssim
. - Xuất điểm dssim cho mỗi tệp văn bản.
- Xuất điểm trung bình.
Độ tương tự về cấu trúc (số liệu dssim
tính toán điểm số) là một số liệu dựa trên tầm nhìn của con người và nhận dạng đối tượng trong hình ảnh. Nói một cách dễ hiểu: nếu hai hình ảnh trông giống con người, chúng sẽ (có thể) có điểm thấp dssim
.
Bài dự thi sẽ là bài nộp có điểm trung bình thấp nhất.
.txt
tệp" không? Văn bản đầu ra của chương trình sẽ được dẫn đến một tập tin hay chúng ta nên xuất một tập tin trực tiếp?