Bir görüntüden 2014 sayısını üretin


11

In 2014 mücadeleden Michael Stern ayrıştırmak için OCR kullanarak önerir 2014 sayısının görüntüsüben farklı bir yöne bu zorluğu çekmek istiyorum 2014 için. Seçtiğiniz dil / standart kütüphaneden yerleşik OCR kullanarak, ASCII dizesi "2014" olarak ayrıştırılan en küçük resmi (bayt cinsinden) tasarlayın.

Stern'in orijinal görüntüsü 7357 bayt, ancak biraz çaba ile 980 bayta kayıpsız bir şekilde sıkıştırılabilir. Şüphesiz siyah beyaz versiyon (181 bayt) aynı kodla da çalışır.

Kurallar: Her cevap, görüntüyü, bayt cinsinden boyutunu ve işlemek için gereken kodu vermelidir. Belirgin nedenlerle özel OCR'ye izin verilmez ...! Makul dillere ve resim biçimlerine izin verilir.

Düzenleme: Yorumlara yanıt olarak, önceden var olan herhangi bir kütüphaneyi ve hatta OCR bulunmayan diller için http://www.free-ocr.com/ adresini de içerecek şekilde genişleteceğim .


9
Dahili OCR'de kaç dil veya standart kitaplık var? Yoksa "standart kütüphane" yi "bu sorun için özel olarak oluşturulmamış herhangi bir kütüphane" mi kastediyorsunuz?
Peter Taylor

3
Mathematica dışında herhangi bir geliştirme platformunda OCR yerleşik olarak mevcut mu?
Michael Stern

Standartlaşmalı, " free-ocr.com'u kullan " veya başka bir kolay erişilebilir ocr gibi bir şey söylemelisiniz .
Justin

Yanıtlar:


10

Kabuk (ImageMagick, Tesseract), 18 bayt

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

Görüntü 18 bayttır ve şu şekilde çoğaltılabilir:

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

Şöyle görünüyor (bu orijinal değil, bir PNG kopyasıdır):

2014

ImageMagick ile işlendikten sonra şöyle görünür:

2014 büyük

ImageMagick sürüm 6.6.9-7, Tesseract sürüm 3.02 kullanarak. PBM görüntüsü Gimp'de oluşturuldu ve onaltılık bir editörle düzenlendi.


Bu sürüm gerektirir 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

Bunun gibi bir çıktı verir:

    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     

Çok, çok etkileyici. Başlık için 3 bayt, resmin boyutları için 5 bayt, bitmap için 10 bayt. Biçim burada açıklanmaktadır: netpbm.sourceforge.net/doc/pbm.html
Charles

5

Java + Tesseract, 53 bayt

Mathematica'ya sahip olmadığım için kuralları biraz bükmeye ve OCR yapmak için Tesseract'ı kullanmaya karar verdim . Çeşitli yazı tiplerini, boyutlarını ve stillerini kullanarak bir görüntüye "2014" oluşturan ve "2014" olarak tanınan en küçük resmi bulan bir program yazdım. Sonuçlar kullanılabilir yazı tiplerine bağlıdır.

İşte bilgisayarımdaki kazanan - 53 bayt, "URW Gothic L" yazı tipini kullanarak: 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);
                    }
                }
            }
        }
    }
}

Bu ve benzeri girişlere izin vermek için kuralları değiştirdim. Etkileyici dosya boyutu.
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]]]

Şimdiye kadarki en iyi durumum:

f[24, "PBM"]

verim


1

Mathematica, 78 bayt

Mathematica'da bunu kazanmanın hilesi muhtemelen ImageResize [] işlevini aşağıdaki gibi kullanacaktır.

İlk olarak, "2014" metnini oluşturdum ve David Carraher'ın çözümü ile adil bir karşılaştırma için bir GIF dosyasına kaydettim. Metin benziyor 2014. Bu hiçbir şekilde optimize edilmemiştir; küçük bir yazı tipi boyutunda sadece Cenevre; başka yazı tipleri ve daha küçük boyutlar da olabilir. Düz TextRecognize [] başarısız olur, ancak TextRecognize [ImageResize []]] 'da sorun yok

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

Sonuçlar

Yazı tipi, yazı tipi boyutu, ölçekleme derecesi vb. İle uğraşmak muhtemelen daha küçük dosyaların bile çalışmasına neden olur.


Çok etkileyici dosya boyutu.
DavidC

Görüntüyü daha küçük ve rakamlar arasındaki boşlukları kısaltmak için beyaz kenarlıklardan kırpabilirsiniz, belki daha kompakt hale getirmek için yeniden çizin.
homoseksüel

swish, beyaz kenarlığı düzeltmek onu 78 byes alır.
Michael Stern
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.