এএসসিআইআই আর্ট জেনারেট করুন


14

ইনপুট হিসাবে যে কোনও যুক্তিসঙ্গত ক্ষতিহীন বিন্যাসে একটি কালো-সাদা চিত্র দেওয়া হয়েছে , আউটপুট ASCII আর্ট যা সম্ভব ইনপুট চিত্রের কাছাকাছি।

বিধি

  • কেবল লাইনফিড এবং এএসসিআইআই বাইট 32-127 ব্যবহার করা যেতে পারে।
  • ইনপুট চিত্রটি ক্রপ করা হবে যাতে চিত্রের চারপাশে কোনও বহিরাগত সাদা স্থান না থাকে।
  • জমাগুলি অবশ্যই 5 মিনিটের নিচে পুরো স্কোরিং কর্পসটি সম্পূর্ণ করতে সক্ষম হবে।
  • শুধুমাত্র কাঁচা পাঠ্য গ্রহণযোগ্য; সমৃদ্ধ পাঠ্য বিন্যাস নেই।
  • স্কোরিংয়ে ব্যবহৃত হরফটি হ'ল 20-pt লিনাক্স লিবের্টিন
  • আউটপুট পাঠ্য ফাইলটি যখন নীচে বর্ণিত হিসাবে কোনও চিত্রে রূপান্তরিত হবে তখন অবশ্যই উভয় মাত্রায় 30 পিক্সেলের মধ্যে ইনপুট চিত্রের মতো একই মাত্রা হওয়া উচিত।

স্কোরিং

এই চিত্রগুলি স্কোর করার জন্য ব্যবহৃত হবে:

আপনি এখানে চিত্রগুলির একটি জিপ ফাইল ডাউনলোড করতে পারেন ।

দাখিলগুলি এই কর্পাসের জন্য অনুকূলিত করা উচিত নয়; বরং তাদের অনুরূপ মাত্রার 8 টি কালো-সাদা চিত্রের জন্য কাজ করা উচিত। আমি যদি সন্দেহ করি যে জমাগুলি এই নির্দিষ্ট চিত্রগুলির জন্য অনুকূলিত করা হচ্ছে তবে কর্পাসে চিত্রগুলি পরিবর্তন করার অধিকার আমি সংরক্ষণ করি।

স্কোরিংটি এই স্ক্রিপ্টের মাধ্যমে সম্পাদন করা হবে:

#!/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)))

স্কোরিং প্রক্রিয়া:

  1. প্রতিটি কর্পাস চিত্রের জন্য জমা দিন, .txtকর্পস ফাইলের মতো একই স্টেমের সাথে ফাইলগুলিতে ফলাফল আউটপুট করে (ম্যানুয়ালি করা)।
  2. 20-পয়েন্ট ফন্ট ব্যবহার করে প্রতিটি স্পেস ফাইলকে পিএনজি চিত্রে রূপান্তর করুন, শ্বেত স্পেস ক্রপ করুন।
  3. ল্যানকোস রিস্যাম্পলিং ব্যবহার করে ফলাফলের চিত্রটিকে মূল চিত্রের আকারের আকার দিন।
  4. প্রতিটি টেক্সট চিত্র ব্যবহার করে মূল চিত্রের সাথে তুলনা করুন dssim
  5. প্রতিটি পাঠ্য ফাইলের জন্য dssim স্কোর আউটপুট।
  6. গড় স্কোর আউটপুট।

স্ট্রাকচারাল সাদৃশ্য (মেট্রিক যার মাধ্যমে dssimস্কোর গণনা করে) হ'ল একটি মেট্রিক যা মানুষের দৃষ্টিভঙ্গি এবং চিত্রগুলিতে অবজেক্ট সনাক্তকরণের উপর ভিত্তি করে। এটিকে স্পষ্টভাবে বলতে গেলে: দুটি চিত্র যদি মানুষের মতো হয় তবে তাদের (সম্ভবত) কম স্কোর থাকবে dssim

বিজয়ী জমাটি সর্বনিম্ন গড় স্কোর সহ জমা হবে।

সংশ্লিষ্ট


6
"কালো এবং সাদা" "শূন্য / এক" হিসাবে বা কত ধূসর স্তর?
লুইস মেন্ডো

2
@ ডোনমুসলি 0 এবং 1
মেগো

" .txtফাইলগুলিতে ফলাফল আউটপুট করে" আপনি কী বোঝাতে চেয়েছেন তা কি আপনি পরিষ্কার করতে পারেন ? প্রোগ্রাম আউটপুট পাঠ্য যা একটি ফাইলে পাইপ করা উচিত বা আমাদের সরাসরি কোনও ফাইল আউটপুট করা উচিত?
ড্যান

@DanTheMan হয় হয় গ্রহণযোগ্য। আপনি যদি STDOUT এ আউটপুট দেন তবে স্কোর করার উদ্দেশ্যে আউটপুটটিকে কোনও ফাইলে পুনঃনির্দেশ করা দরকার।
মেগো

আপনার কি রেজোলিউশন সীমাবদ্ধতা নির্দিষ্ট করা উচিত নয়? অন্যথায়, আমরা 10000 বাই 10000 চরিত্রের চিত্র তৈরি করতে পারি, যা যখন ছোট করে দেওয়া হয়, তখন মূল চিত্রগুলি খুব ঘনিষ্ঠভাবে মেলে এবং পৃথক অক্ষরগুলি অযোগ্য বিন্দু হতে পারে। ফন্টের আকারটি আউটপুট চিত্রটি বিশাল কিনা তা বিবেচনা করে না।
ডেভিডসি

উত্তর:


6

জাভা, স্কোর 0.57058675

এটি চিত্রের ম্যানিপুলেশনটি আসলে আমার প্রথমবার তাই এটি একরকম বিশ্রীজনক তবে আমি মনে করি এটি ঠিক আছে।

আমি আমার মেশিনে কাজ করতে dssim পেতে পারি না, তবে আমি পিআইএল ব্যবহার করে ছবি তৈরি করতে সক্ষম হয়েছি।

মজার বিষয় হচ্ছে, ফন্টটি জাভাতে আমাকে বলেছে যে আমি ব্যবহার করছি প্রতিটি অক্ষরই প্রস্থ 6। আপনি দেখতে পারেন আমার প্রোগ্রামে যে FontMetrics::charWidthহয় 6সমস্ত অক্ষর যে আমি ব্যবহার করেছি জন্য। {}লোগোটি একটি মোনোস্পেস ফন্টে সুন্দর শালীন দেখায়। তবে কিছু কারণে লাইনগুলি সম্পূর্ণ টেক্সট ফাইলে লাইন আপ করে না। আমি ligatures দোষারোপ। (এবং হ্যাঁ, আমার করা উচিত) সঠিক ফন্টটি ব্যবহার করা ))

মনসপ্যাসে ফন্টে:

                                                                                      .
                         .,:ff:,                                                   ,:fff::,.
                ,ff .fIIIIIf,                                                         .:fIIIIIf.:f:.
            .,:III: ,ff::                       ..,,            ,,..                      ,:fff, IIII.,
          :IIf,f:,:fff:,                  .:fIIIIIII.          .IIIIIIIf:.                 .,:fff:,ff IIf,
       ,.fIIIf,:ffff,                   ,IIIIIII:,,.            .,,:IIIIIII.                  .:ffff:,IIII,:.
     ,III.::.,,,,,.                     IIIIII:                      ,IIIIII                     ,,,,,.,:,:IIf
     IIIII :ffIIf,                      IIIIII,                      .IIIIII                      :IIIf:,.IIIIf.
  ,II,fIf.:::,..                        IIIIII,                      .IIIIII                       ..,:::,,If::II
  IIIIf.  ,:fII:                       .IIIIII,                      .IIIIII.                       IIff:.  :IIII:
 ::IIIIf:IIIf: .                  ,::fIIIIIII,                        ,fIIIIIIf::,                   ,ffIII,IIIIf,,
:IIf:::    .,fI:                  IIIIIIIII:                            :IIIIIIIIf                  If:,    .::fIIf
 IIIIII, :IIIIf                     .,:IIIIIIf                        fIIIIII:,.                    ,IIIII. fIIIII:
 ,:IIIII ff:,   f,                      IIIIII,                      .IIIIII                      f.  .::f::IIIIf,.
 fIf::,,     ,fIII                      IIIIII,                      .IIIIII                     :III:      ,,:fII.
  fIIIIIIf, :IIIIf   ,                  IIIIII,                      .IIIIII                 .,  ,IIIII. :fIIIIII,
   .:IIIIIII,ff,    :II:                IIIIIIf                      fIIIIII               .fII.   .:ff:IIIIIIf,
     :fffff:,      IIIIIf   ,            :IIIIIIIfff            fffIIIIIII:           ..   IIIII:      ::fffff,
      .fIIIIIIIf:, fIIII,   ,IIf,           ,:ffIIII.          .IIIIff:,          .:fII    fIIII,.:ffIIIIIII:
         ,fIIIIIIIIIf:,     ,IIIII:  .,::,                               .,::,  .IIIIII      ::fIIIIIIIIf:.
             :fffffff,      .fIIIII,   .IIIIIf:                     ,:fIIII:    IIIIII:       :fffffff,
              .:fIIIIIIIIIIIIffffI:      IIIIIIII.                :IIIIIII:     .fIffffIIIIIIIIIIII:,
                   ,:fIIIIIIIIIIIf,       .:fIIIII               ,IIIIIf,        :IIIIIIIIIIIff,.
                         .:ffffffffIIIIIIIIIIIfff:.              ,ffffIIIIIIIIIIIfffffff:,
                             .,:ffIIIIIIIIIIIIIIIIf,   .,,,,.  .:fIIIIIIIIIIIIIIIIff:,.
                                       ....... .,,:fffff:.,:fffff:,.  .......
                                    ..,,:fffIIIIf:,.            .,:fIIIIff::,,..
                                   .IIIIIf:,.                          .,:fIIIII
                                     f,                                      ,f

এটি চিত্র সরঞ্জামের মাধ্যমে চালানোর পরে:

।} লোগো

যাইহোক, এখানে আসল কোড।

//package cad97;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;

public final class AsciiArt {

    private static final Font LINUX_LIBERTINE = new Font("LinLibertine_DRah", Font.PLAIN, 20);
    private static final FontMetrics LL_METRICS = Toolkit.getDefaultToolkit().getFontMetrics(LINUX_LIBERTINE);
    // Toolkit::getFontMetrics is deprecated, but that's the only way to get FontMetrics without an explicit Graphics environment.
    // If there's a better way to get the widths of characters, please tell me.

    public static void main(String[] args) throws IOException {
        File jar = new java.io.File(AsciiArt.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        if (args.length != 1) {
            String jarName = jar.getName();
            System.out.println("Usage: java -jar " + jarName + " file");
        } else {
            File image = new File(args[0]);
            try (InputStream input = new FileInputStream(image)) {
                String art = createAsciiArt(ImageIO.read(input), LINUX_LIBERTINE, LL_METRICS);
                System.out.print(art); // If you want to save as a file, change this.
            } catch (FileNotFoundException fnfe) {
                System.out.println("Unable to find file " + image + ".");
                System.out.println("Please note that you need to pass the full file path.");
            }
        }
    }

    private static String createAsciiArt(BufferedImage image, Font font, FontMetrics metrics) {
        final int height = metrics.getHeight();
        final Map<Character,Integer> width = new HashMap<>();
        for (char c=32; c<127; c++) { width.put(c, metrics.charWidth(c)); }

        StringBuilder art = new StringBuilder();

        for (int i=0; i<=image.getHeight(); i+=height) {
            final int tempHeight = Math.min(height, image.getHeight()-i);
            art.append(createAsciiLine(image.getSubimage(0, i, image.getWidth(), tempHeight), width));
        }

        return art.toString();
    }

    private static String createAsciiLine(BufferedImage image, Map<Character,Integer> charWidth) {
        if (image.getWidth()<6) return "\n";
        /*
        I'm passing in the charWidth Map because I could use it, and probably a later revision if I
        come back to this will actually use non-6-pixel-wide characters. As is, I'm only using the
        6-pixel-wide characters for simplicity. They are those in this set: { !,./:;I[\]ft|}
        */
        assert charWidth.get(' ') == 6; assert charWidth.get('!') == 6;
        assert charWidth.get(',') == 6; assert charWidth.get('.') == 6;
        assert charWidth.get('/') == 6; assert charWidth.get(':') == 6;
        assert charWidth.get(';') == 6; assert charWidth.get('I') == 6;
        assert charWidth.get('[') == 6; assert charWidth.get('\\') == 6;
        assert charWidth.get(']') == 6; assert charWidth.get('f') == 6;
        assert charWidth.get('t') == 6; assert charWidth.get('|') == 6;

        // Measure whiteness of 6-pixel-wide sample
        Raster sample = image.getData(new Rectangle(6, image.getHeight()));
        int whiteCount = 0;
        for (int x=sample.getMinX(); x<sample.getMinX()+sample.getWidth(); x++) {
            for (int y=sample.getMinY(); y<sample.getMinY()+sample.getHeight(); y++) {
                int pixel = sample.getPixel(x, y, new int[1])[0];
                whiteCount += pixel==1?0:1;
            }
        }

        char next;

        int area = sample.getWidth()*sample.getHeight();

        if (whiteCount > area*0.9) {
            next = ' ';
        } else if (whiteCount > area*0.8) {
            next = '.';
        } else if (whiteCount > area*0.65) {
            next = ',';
        } else if (whiteCount > area*0.5) {
            next = ':';
        } else if (whiteCount > area*0.3) {
            next = 'f';
        } else {
            next = 'I';
        }

        return next + createAsciiLine(image.getSubimage(charWidth.get(','), 0, image.getWidth()-sample.getWidth(), image.getHeight()), charWidth);
    }

}

কম্পাইল:

  • আপনার জেডিকে আছে তা নিশ্চিত করুন ইনস্টল
  • নিশ্চিত করুন যে জেডিকে বিন আপনার পথে রয়েছে (এটি আমার জন্য C:\Program Files\Java\jdk1.8.0_91\bin )
  • ফাইল হিসাবে সংরক্ষণ করুন AsciiArt.java
  • javac AsciiArt.java
  • jar cvfe WhateverNameYouWant.jar AsciiArt AsciiArt.class

ব্যবহার: java -jar WhateverNameYouWant.jar C:\full\file\path.png :, প্রিন্ট করুন STDOUT

1-বিট গভীরতা এবং একটি সাদা পিক্সেলের জন্য নমুনা সহ উত্স ফাইলটি সংরক্ষণ করা প্রয়োজন 1

স্কোরিং আউটপুট:

corp/board.png: 0.6384
corp/Doppelspalt.png: 0.605746
corp/down.png: 1.012326
corp/img2.png: 0.528794
corp/pcgm.png: 0.243618
corp/peng.png: 0.440982
corp/phi.png: 0.929552
corp/text2image.png: 0.165276
Score: 0.57058675

1
দৃ -eaenable়তা সক্ষম করতে চালান । এটি আচরণটি পরিবর্তন করবে না (কেবলমাত্র এটি অল্প পরিমাণে কমিয়ে দেওয়া ব্যতীত) কারণ যখন প্রোগ্রামগুলি ব্যর্থ করে মূল্যায়ন করে falseএবং এই সমস্ত দাবিগুলি পাস হয় তখনই দাবিগুলি কাজ করে ।
CAD97

আহ, আমি মিস করেছি যে আপনি প্যাকেজ ঘোষণা সরিয়ে দিয়েছেন। এটা এখন কাজ করে. আমি আজ কয়েক মিনিট পেলে এটি স্কোর করব।
মেগো

জন্য আউটপুট board.png কিছু কারণে মাত্র 4 লাইন দীর্ঘ: gist.github.com/Mego/75eccefe555a81bde6022d7eade1424f । আসলে, পিপিসিজি লোগো ব্যতীত আমি যখন এটি চালনা করি তখন আউটপুটগুলির সমস্তগুলি অকাল থেকেই ছাঁটাই হয়ে যায়।
মেগো

@ মেগো আমি মনে করি এটি হ'ল ফন্টের উচ্চতা (ফন্টমেট্রিক্স প্রতিবেদনের 24 পিক্সেল) এর সাথে করতে হবে। আমি লাইন লুপটি পরিবর্তন করেছি যাতে এটি খুব অল্প সংখ্যক লাইনের পরিবর্তে একাধিক লাইনের পাশে ভুল হয় এবং এটি এখন কাজ করা উচিত। (বোর্ড 5 লাইন হয়)
CAD97

ঠিক যেমন একটি নিয়ম হিসাবে এই অ্যালগরিদমটি ছোট চিত্রগুলির সাথে লড়াই করে, যেহেতু (এটি মনে হয়) সমস্ত অক্ষর 6px প্রশস্ত এবং 24px লম্বা, এবং এটির যা দেখায় তা হ'ল সেই সুপার-পিক্সেলটিতে কত পিক্সেল চালু আছে।
CAD97
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.