Tạo số 2014 từ một hình ảnh


11

Trong thử thách năm 2014 , Michael Stern đề nghị sử dụng OCR để phân tích một hình ảnh của số 2014đến năm 2014. Tôi muốn thực hiện thử thách này theo một hướng khác. Sử dụng OCR tích hợp từ thư viện ngôn ngữ / tiêu chuẩn bạn chọn, thiết kế hình ảnh nhỏ nhất (tính bằng byte) được phân tách thành chuỗi ASCII "2014".

Hình ảnh gốc của Stern là 7357 byte, nhưng với một chút nỗ lực, nó có thể được nén một cách dễ dàng đến 980 byte. Không còn nghi ngờ gì nữa, phiên bản đen trắng (181 byte) cũng hoạt động với cùng một mã.

Quy tắc: Mỗi câu trả lời sẽ cung cấp cho hình ảnh, kích thước của nó theo byte và mã cần thiết để xử lý nó. Không cho phép OCR tùy chỉnh, vì lý do rõ ràng ...! Bất kỳ ngôn ngữ hợp lý và định dạng hình ảnh được cho phép.

Chỉnh sửa: Để phản hồi các bình luận, tôi sẽ mở rộng điều này để bao gồm bất kỳ thư viện có sẵn nào, hoặc thậm chí http: //www.free-oc.com/ cho những ngôn ngữ không có OCR.


9
Có bao nhiêu ngôn ngữ hoặc thư viện chuẩn đã tích hợp sẵn OCR? Hay bạn có ý định "thư viện chuẩn" ở đây có nghĩa là "bất kỳ thư viện nào chưa được tạo riêng cho thử thách này"?
Peter Taylor

3
Có nền tảng phát triển nào khác ngoài Mathicala có OCR được tích hợp không?
Michael Stern

Bạn nên chuẩn hóa, nói một cái gì đó như "sử dụng free-nob.com " hoặc một số ocr dễ truy cập khác.
Justin

Câu trả lời:


10

Shell (ImageMagick, Tesseract), 18 byte

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

Hình ảnh là 18 byte và có thể được sao chép như thế này:

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

Nó trông như thế này (đây là bản sao PNG, không phải bản gốc):

2014

Sau khi xử lý với ImageMagick, nó trông như thế này:

2014 lớn

Sử dụng ImageMagick phiên bản 6.6.9-7, Tesseract phiên bản 3.02. Hình ảnh PBM được tạo trong Gimp và được chỉnh sửa bằng trình chỉnh sửa hex.


Phiên bản này yêu cầu 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

Nó xuất ra một cái gì đó như thế này:

    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     

Rất, rất ấn tượng. 3 byte cho tiêu đề, 5 byte cho kích thước của hình ảnh, 10 byte cho bitmap. Định dạng được mô tả ở đây: netpbm.sourceforge.net/doc/pbm.html
Charles

5

Java + Tesseract, 53 byte

Vì tôi không có Mathicala, tôi quyết định bẻ cong các quy tắc một chút và sử dụng Tesseract để thực hiện OCR. Tôi đã viết một chương trình biến "2014" thành một hình ảnh, sử dụng nhiều phông chữ, kích cỡ và kiểu khác nhau và tìm thấy hình ảnh nhỏ nhất được công nhận là "2014". Kết quả phụ thuộc vào các phông chữ có sẵn.

Đây là người chiến thắng trên máy tính của tôi - 53 byte, sử dụng phông chữ "URW Gothic L": 2014

Mã số:

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);
                    }
                }
            }
        }
    }
}

Tôi đã thay đổi các quy tắc để cho phép điều này và các mục tương tự. Kích thước tập tin ấn tượng.
Charles

1

Toán học 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]]]

Trường hợp tốt nhất của tôi cho đến nay:

f[24, "PBM"]

hiệu quả


1

Toán học, 78 byte

Thủ thuật để giành được điều này trong Mathematica có thể sẽ là sử dụng hàm ImageResize [] như dưới đây.

Đầu tiên, tôi đã tạo văn bản "2014" và lưu nó vào tệp GIF, để so sánh công bằng với giải pháp của David Carraher. Các văn bản trông như thế nào 2014. Điều này không được tối ưu hóa theo bất kỳ cách nào; đó chỉ là Geneva với kích thước phông chữ nhỏ; phông chữ khác và kích thước nhỏ hơn có thể có thể. TextRecognize [] sẽ không thành công, nhưng TextRecognize [ImageResize []]] không có vấn đề gì

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

các kết quả

Làm phiền với kiểu chữ, kích thước phông chữ, mức độ chia tỷ lệ, v.v., có thể sẽ dẫn đến các tệp thậm chí nhỏ hơn hoạt động.


Kích thước tập tin rất ấn tượng.
DavidC

Bạn có thể cắt hình ảnh ra khỏi viền trắng để làm cho nó nhỏ hơn và ngắn hơn khoảng cách giữa các chữ số, có thể vẽ lại để làm cho chúng nhỏ gọn hơn.
swish

@swish thực sự, cắt viền trắng đưa nó lên 78 byes.
Michael Stern
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.