Produziere die Nummer 2014 aus einem Bild

11

Bei der Herausforderung 2014 schlägt Michael Stern vor, OCR zum Parsen ein Bild der Nummer 2014auf 2014 zu verwenden. Ich möchte diese Herausforderung in eine andere Richtung lenken. Entwerfen Sie mit der integrierten OCR aus der Sprach- / Standardbibliothek Ihrer Wahl das kleinste Bild (in Byte), das in der ASCII-Zeichenfolge "2014" analysiert wird.

Sterns Originalbild ist 7357 Bytes groß, kann aber mit ein wenig Aufwand verlustfrei auf 980 Bytes komprimiert werden. Zweifellos funktioniert die Schwarzweißversion (181 Bytes) auch mit demselben Code.

Regeln: Jede Antwort sollte das Bild, seine Größe in Bytes und den Code enthalten, der zur Verarbeitung benötigt wird. Aus offensichtlichen Gründen ist keine benutzerdefinierte OCR zulässig ...! Alle angemessenen Sprachen und Bildformate sind zulässig.

Bearbeiten: Als Antwort auf Kommentare werde ich dies erweitern, um bereits vorhandene Bibliotheken oder sogar http://www.free-ocr.com/ für diejenigen Sprachen einzuschließen, für die keine OCR verfügbar ist.

Charles
quelle
9
In wie vielen Sprachen oder Standardbibliotheken ist OCR integriert? Oder wollen Sie hier unter "Standardbibliothek" "jede Bibliothek, die nicht speziell für diese Herausforderung erstellt wurde" verstehen?
Peter Taylor
3
Hat eine andere Entwicklungsplattform als Mathematica OCR eingebaut?
Michael Stern
Sie sollten standardisieren, sagen Sie etwas wie "use free-ocr.com " oder ein anderes leicht zugängliches ocr.
Justin

Antworten:

10

Shell (ImageMagick, Tesseract), 18 Bytes

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

Das Bild ist 18 Bytes groß und kann folgendermaßen reproduziert werden:

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

Es sieht so aus (dies ist eine PNG-Kopie, nicht das Original):

2014

Nach der Verarbeitung mit ImageMagick sieht es folgendermaßen aus:

2014 groß

Verwenden von ImageMagick Version 6.6.9-7, Tesseract Version 3.02. Das PBM-Bild wurde in Gimp erstellt und mit einem Hex-Editor bearbeitet.


Diese Version erfordert 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

Es gibt ungefähr so ​​aus:

    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     
user13957
quelle
Sehr sehr beeindruckend. 3 Bytes für den Header, 5 Bytes für die Abmessungen des Bildes, 10 Bytes für die Bitmap. Das Format wird hier beschrieben: netpbm.sourceforge.net/doc/pbm.html
Charles
5

Java + Tesseract, 53 Bytes

Da ich Mathematica nicht habe, habe ich beschlossen, die Regeln ein wenig zu verbiegen und verwenden Tesseract OCR zu tun. Ich habe ein Programm geschrieben, das "2014" mit verschiedenen Schriftarten, Größen und Stilen in ein Bild umwandelt und das kleinste Bild findet, das als "2014" erkannt wird. Die Ergebnisse hängen von den verfügbaren Schriftarten ab.

Hier ist der Gewinner auf meinem Computer - 53 Byte mit der Schriftart "URW Gothic L": 2014

Code:

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);
                    }
                }
            }
        }
    }
}
Aditsu beenden, weil SE böse ist
quelle
Ich habe die Regeln geändert, um diese und ähnliche Einträge zuzulassen. Beeindruckende Dateigröße.
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]]]

Mein bisher bester Fall:

f[24, "PBM"]

Effizienz

DavidC
quelle
1

Mathematica, 78 Bytes

Der Trick, um dies in Mathematica zu gewinnen, wird wahrscheinlich die Verwendung der ImageResize [] -Funktion wie unten sein.

Zuerst habe ich den Text "2014" erstellt und in einer GIF-Datei gespeichert, um einen fairen Vergleich mit der Lösung von David Carraher zu ermöglichen. Der Text sieht aus wie 2014. Dies ist in keiner Weise optimiert; Es ist nur Genf in einer kleinen Schriftgröße. Andere Schriftarten und kleinere Größen sind möglicherweise möglich. Straight TextRecognize [] würde fehlschlagen, aber TextRecognize [ImageResize []]] hat kein Problem

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

Ergebnisse

Wenn Sie sich mit der Schriftart, der Schriftgröße, dem Skalierungsgrad usw. beschäftigen, werden wahrscheinlich noch kleinere Dateien funktionieren.

Michael Stern
quelle
Sehr beeindruckende Dateigröße.
DavidC
Sie können das Bild von den weißen Rändern zuschneiden, um die Abstände zwischen den Ziffern zu verkleinern und zu verkürzen. Zeichnen Sie sie möglicherweise neu, um sie kompakter zu machen.
Swish
@swish in der Tat, das Trimmen des weißen Randes bringt es auf 78 Byes.
Michael Stern