Wyprodukuj liczbę 2014 na podstawie obrazu


11

W wyzwaniu z 2014 roku Michael Stern sugeruje użycie OCR do parsowania obraz liczby 2014do 2014 roku. Chciałbym podjąć to wyzwanie w innym kierunku. Korzystając z wbudowanego OCR z wybranej biblioteki języka / standardu, zaprojektuj najmniejszy obraz (w bajtach), który zostanie przetworzony na ciąg ASCII „2014”.

Oryginalny obraz Sterna ma 7357 bajtów, ale przy odrobinie wysiłku można go bezstratnie skompresować do 980 bajtów. Bez wątpienia czarno-biała wersja (181 bajtów) działa również z tym samym kodem.

Reguły: Każda odpowiedź powinna zawierać obraz, jego rozmiar w bajtach i kod potrzebny do jego przetworzenia. Nie jest dozwolone niestandardowe rozpoznawanie znaków z oczywistych powodów ...! Dozwolone są wszelkie rozsądne języki i formaty obrazów.

Edycja: W odpowiedzi na komentarze rozszerzę to, aby uwzględnić dowolną istniejącą bibliotekę, a nawet http://www.free-ocr.com/ dla tych języków, w których nie jest dostępny OCR.


9
Ile języków lub bibliotek standardowych ma wbudowane OCR? Czy może zamierzasz tutaj oznaczać „bibliotekę standardową” jako „bibliotekę, która nie została stworzona specjalnie dla tego wyzwania”?
Peter Taylor

3
Czy jakaś platforma programistyczna inna niż Mathematica ma wbudowane OCR?
Michael Stern

Powinieneś ustandaryzować, powiedzieć coś takiego jak „use free-ocr.com ” lub inny łatwo dostępny ocr.
Justin

Odpowiedzi:


10

Shell (ImageMagick, Tesseract), 18 bajtów

file=golf_2014
echo -n UDQKMTMgNQruqCqo6riKiO6I | base64 -d > $file.pbm
convert -border 2x2 -bordercolor white -resize 300% -sharpen 0 -monochrome $file.pbm $file.png
tesseract $file.png $file digits
cat $file.txt
rm $file.pbm $file.png $file.txt

Obraz ma 18 bajtów i można go odtworzyć w następujący sposób:

echo -n UDQKMTMgNQruqCqo6riKiO6I | base64 -d > 2014.pbm

Wygląda to tak (jest to kopia PNG, a nie oryginał):

2014

Po przetworzeniu za pomocą ImageMagick wygląda to tak:

2014 duży

Korzystanie z ImageMagick w wersji 6.6.9-7, Tesseract w wersji 3.02. Obraz PBM został utworzony w Gimp i edytowany za pomocą edytora szesnastkowego.


Ta wersja wymaga jp2a.

file=golf_2014
echo -n UDQKMTMgNQruqCqo6riKiO6I | base64 -d > $file.pbm
convert -border 2x2 -bordercolor white -resize 300% -sharpen 0 -monochrome $file.pbm $file.png
tesseract $file.png $file digits
cat $file.txt
convert -background black -fill white -border 2x2 -bordercolor black -pointsize 100 label:$(cat $file.txt) $file.jpg
jp2a --chars=" $(cat $file.txt) " $file.jpg
rm $file.pbm $file.png $file.txt $file.jpg

Wyprowadza coś takiego:

    2014444444102         01144444102              214441                 214441     
   1             1      24           1            04    4                0     4     
  1    410201     0    0    410004    1       2014      4              21      4     
 24   42     0    4    4    0     1    0    24          4             04       4     
  22222      1    1   0    42     0    4    2   4100    4            1   41    4     
            1    42   0    4      2     2   2412   0    4          24   420    4     
          04    42    0    1      2     2          0    4         0   40  0    4     
       204    42      0    1      2     2          0    4       24   42   0    4     
     21     12        0    4      0    42          0    4      2     411114     1112 
    04   412          24    0     1    0           0    4      0                   0 
  24     1111111110    1    42  21    4            0    4      200011111001    40002 
  4               4     04    44     42            0    4                 0    4     
 0                4      214       10              0    4                 0    4     
  22222222222222222         222222                  22222                  22222     

Bardzo, bardzo imponujące. 3 bajty na nagłówek, 5 bajtów na wymiary obrazu, 10 bajtów na mapę bitową. Format jest opisany tutaj: netpbm.sourceforge.net/doc/pbm.html
Charles

5

Java + Tesseract, 53 bajty

Ponieważ nie mam Mathematica, postanowiłem nieco nagiąć reguły i użyć Tesseract do wykonania OCR. Napisałem program, który przekształca „2014” w obraz, używając różnych czcionek, rozmiarów i stylów, i znajduje najmniejszy obraz, który zostanie rozpoznany jako „2014”. Wyniki zależą od dostępnych czcionek.

Oto zwycięzca na moim komputerze - 53 bajty, przy użyciu czcionki „URW Gothic L”: 2014

Kod:

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Ocr {
    public static boolean blankLine(final BufferedImage img, final int x1, final int y1, final int x2, final int y2) {
        final int d = x2 - x1 + y2 - y1 + 1;
        final int dx = (x2 - x1 + 1) / d;
        final int dy = (y2 - y1 + 1) / d;
        for (int i = 0, x = x1, y = y1; i < d; ++i, x += dx, y += dy) {
            if (img.getRGB(x, y) != -1) {
                return false;
            }
        }
        return true;
    }

    public static BufferedImage trim(final BufferedImage img) {
        int x1 = 0;
        int y1 = 0;
        int x2 = img.getWidth() - 1;
        int y2 = img.getHeight() - 1;
        while (x1 < x2 && blankLine(img, x1, y1, x1, y2)) x1++;
        while (x1 < x2 && blankLine(img, x2, y1, x2, y2)) x2--;
        while (y1 < y2 && blankLine(img, x1, y1, x2, y1)) y1++;
        while (y1 < y2 && blankLine(img, x1, y2, x2, y2)) y2--;
        return img.getSubimage(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
    }

    public static int render(final Font font, final int w, final String name) throws IOException {
        BufferedImage img = new BufferedImage(w, w, BufferedImage.TYPE_BYTE_BINARY);
        Graphics2D g = img.createGraphics();
        float size = font.getSize2D();
        Font f = font;
        while (true) {
            final FontMetrics fm = g.getFontMetrics(f);
            if (fm.stringWidth("2014") <= w) {
                break;
            }
            size -= 0.5f;
            f = f.deriveFont(size);
        }
        g = img.createGraphics();
        g.setFont(f);
        g.fillRect(0, 0, w, w);
        g.setColor(Color.BLACK);
        g.drawString("2014", 0, w - 1);
        g.dispose();
        img = trim(img);
        final File file = new File(name);
        ImageIO.write(img, "gif", file);
        return (int) file.length();
    }

    public static boolean ocr() throws Exception {
        Runtime.getRuntime().exec("/usr/bin/tesseract 2014.gif out -psm 8").waitFor();
        String t = "";
        final BufferedReader br = new BufferedReader(new FileReader("out.txt"));
        while (true) {
            final String s = br.readLine();
            if (s == null) break;
            t += s;
        }
        br.close();
        return t.trim().equals("2014");
    }

    public static void main(final String... args) throws Exception {
        int min = 10000;
        for (String s : GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()) {
            for (int t = 0; t < 4; ++t) {
                final Font font = new Font(s, t, 50);
                for (int w = 10; w < 25; ++w) {
                    final int size = render(font, w, "2014.gif");
                    if (size < min && ocr()) {
                        render(font, w, "2014win.gif");
                        min = size;
                        System.out.println(s + ", " + size);
                    }
                }
            }
        }
    }
}

Zmieniłem zasady, aby zezwolić na to i podobne wpisy. Imponujący rozmiar pliku.
Charles

1

Mathematica 753 100

f[n_,format_]:=
Module[{filename},
Print["raster: ",n," by ", n];
filename="2014At"<>ToString[n]<>"."<>format;
Print["filename:  ",filename];
Print["format: ",format];
Print["raster image: ",rasterImg=Rasterize[Style[2014,"OCR A Std"],
RasterSize->n,ImageSize->1n,ImageResolution->6n]];
Export[filename,rasterImg];
Print["Actual imported image: ",img=Switch[format,"PDF"|"HDF",Import[filename][[1]],
_,Import[filename]]];
Print["Identified text: ",TextRecognize[ImageResize[img,Scaled[3]]]];
Print["filesize (bytes): ",FileByteCount[filename]]]

Mój najlepszy przypadek do tej pory:

f[24, "PBM"]

wydajność


1

Mathematica, 78 bajtów

Trikiem do wygrania tego w Mathematica będzie prawdopodobnie użycie funkcji ImageResize [] jak poniżej.

Najpierw stworzyłem tekst „2014” i zapisałem go w pliku GIF, aby zapewnić rzetelne porównanie z rozwiązaniem Davida Carrahera. Tekst wygląda jak 2014. Nie jest to w żaden sposób zoptymalizowane; to tylko Genewa w małym rozmiarze czcionki; Możliwe są inne czcionki i mniejsze rozmiary. Proste TextRecognize [] nie powiedzie się, ale TextRecognize [ImageResize []]] nie ma problemu

filename = "~/Desktop/2014.gif";
Print["Actual imported image: ", img = Import[filename]]
Print["Identified text: ", 
 TextRecognize[ImageResize[img, Scaled[2]]]]
Print["filesize (bytes): ", FileByteCount[filename]]

wyniki

Problemy z krojem czcionki, rozmiarem czcionki, stopniem skalowania itp. Prawdopodobnie spowodują, że nawet mniejsze pliki będą działać.


Bardzo imponujący rozmiar pliku.
DavidC

Możesz przyciąć obraz poza białe obramowania, aby zmniejszyć i skrócić odstępy między cyframi, a być może przerysować, aby były bardziej zwarte.
świst

@ Swish rzeczywiście, przycięcie białej granicy powoduje, że jest to 78 bajtów.
Michael Stern
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.