Produire le numéro 2014 à partir d'une image


11

Dans le défi de 2014 , Michael Stern suggère d'utiliser l'OCR pour analyser une image du numéro 20142014. J'aimerais prendre ce défi dans une direction différente. À l'aide de l'OCR intégré de la bibliothèque de langues / standard de votre choix, concevez la plus petite image (en octets) qui est analysée dans la chaîne ASCII "2014".

L'image originale de Stern est de 7357 octets, mais avec un peu d'effort, elle peut être compressée sans perte à 980 octets. Nul doute que la version noir et blanc (181 octets) fonctionne aussi bien avec le même code.

Règles: Chaque réponse doit donner l'image, sa taille en octets et le code nécessaire pour la traiter. Aucun OCR personnalisé n'est autorisé, pour des raisons évidentes ...! Toutes les langues et tous les formats d'image raisonnables sont autorisés.

Edit: En réponse aux commentaires, j'élargirai ceci pour inclure n'importe quelle bibliothèque préexistante, ou même http://www.free-ocr.com/ pour les langues où aucun OCR n'est disponible.


9
Combien de langues ou de bibliothèques standard ont une OCR intégrée? Ou entendez-vous ici "bibliothèque standard" signifier "toute bibliothèque qui n'a pas été créée spécifiquement pour ce défi"?
Peter Taylor

3
Y a-t-il une OCR intégrée à une plate-forme de développement autre que Mathematica?
Michael Stern

Vous devriez standardiser, dire quelque chose comme "use free-ocr.com " ou un autre ocr facilement accessible.
Justin

Réponses:


10

Shell (ImageMagick, Tesseract), 18 octets

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

L'image est de 18 octets et peut être reproduite comme ceci:

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

Cela ressemble à ceci (c'est une copie PNG, pas l'original):

2014

Après le traitement avec ImageMagick, cela ressemble à ceci:

2014 grand

En utilisant ImageMagick version 6.6.9-7, Tesseract version 3.02. L'image PBM a été créée dans Gimp et modifiée avec un éditeur hexadécimal.


Cette version nécessite 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

Il produit quelque chose comme ceci:

    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     

Très, très impressionnant. 3 octets pour l'en-tête, 5 octets pour les dimensions de l'image, 10 octets pour le bitmap. Le format est décrit ici: netpbm.sourceforge.net/doc/pbm.html
Charles

5

Java + Tesseract, 53 octets

Comme je n'ai pas Mathematica, j'ai décidé de plier un peu les règles et d' utiliser Tesseract pour faire l'OCR. J'ai écrit un programme qui rend "2014" en une image, en utilisant différentes polices, tailles et styles, et trouve la plus petite image reconnue comme "2014". Les résultats dépendent des polices disponibles.

Voici le gagnant sur mon ordinateur - 53 octets, utilisant la police "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);
                    }
                }
            }
        }
    }
}

J'ai changé les règles pour autoriser cela et des entrées similaires. Taille de fichier impressionnante.
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]]]

Mon meilleur cas jusqu'à présent:

f[24, "PBM"]

Efficacité


1

Mathematica, 78 octets

L'astuce pour gagner cela dans Mathematica sera probablement d'utiliser la fonction ImageResize [] comme ci-dessous.

Tout d'abord, j'ai créé le texte "2014" et l'ai enregistré dans un fichier GIF, pour une comparaison équitable avec la solution de David Carraher. Le texte ressemble 2014. Ce n'est pas optimisé en aucune façon; c'est juste Genève dans une petite taille de police; d'autres polices et tailles plus petites peuvent être possibles. Straight TextRecognize [] échouerait, mais TextRecognize [ImageResize []]] n'a aucun problème

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

résultats

S'occuper de la police, de la taille de la police, du degré de mise à l'échelle, etc., entraînera probablement des fichiers encore plus petits qui fonctionnent.


Taille de fichier très impressionnante.
DavidC

Vous pouvez recadrer l'image des bordures blanches pour la rendre plus petite et plus courte les espaces entre les chiffres, peut-être redessiner pour les rendre plus compacts.
swish

@swish en effet, rogner la bordure blanche la porte à 78 byes.
Michael Stern
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.