东京大学招生海报上的那些事(下)

我也跟着搞了搞,下面把感受和过程贴下。

我选了妹子打伞的那一张,首先就是OCR识别01,在linux下用的tesseract-ocr,具体使用方法在这篇帖子里提到了,很详细,不过稍微有些旧,具体配置过程参见里面提到的官方文档。

提前说一下,偶用tesseract-ocr识别的并不足够准确==!(看STAGE1里面人家用的是汉王搞的,我后来就没有再试,直接用的人家搞下来的01继续了下一步。。)我是这么做的。

首先在google code上下载了tesseract-ocr源码,按文档解决好依赖,然后配置安装。接着下载语言包,在列表里可以看到一个Math/Equation的,不是因为要识别数字就下载这个包,我们只要eng的就可以。然后解压到tessdata下,如果你有自己的安装目录,要export一下tessdata的副文件夹(如果找不到训练集,tesseract也会提示你设一下),不然的话就放在/user/local/share/tessdata下。最新的tesseract已经支持不少图片格式了,因此没必要在convert格式。

执行tesseract 1.png 1.out -l eng。结果只有一点点乱七八糟的东西,一点意义也没有。。为了提高识别准确度,可以把每一行截个图,逐行处理。甚至可以用PS,总之提高图片里数字的对比度跟清晰度,然后再给tesseract识别。

这回好多了,不过发现结果里面有好多字母,我们明明只需要数字的,没必要让它把字母也包进来,况且还是错的。。可以给tesseract加个配置项digits,这样它就只会识别数字了,执行tesseract 1.png 1.out -l eng digits,结果里有一些94.。。再缩小范围,让tesseract只识别01. 不过默认文件没有这个配置项,我们可以手工写一个。

在/usr/local/share/tessdata/configs里,sudo cp digits binarys,然后修改一下binarys,使其只识别01. binarys最终内容如下:tessedit_char_whitelist 01

现在执行tesseract 1.png 1.out -l eng binarys,结果已经好很多了。不过苦B之处在于,这个结果总归是不可信的,你还得一个一个去比对tesseract是不是识别对了。

总结,OCR识别有意义的文字,对准确度要求并不高。但是识别二进制码要求就相当高了,错一个都没的进行下一步==!


接下来就是把识别的文本的二进制码转化成一些有意义的东西。在(上)中,可以看到作者对每行几个,一共几行,总数是不是8的倍数等都统计了一遍,要想出这些二进制码到底是什么感觉是最最难的一步,得有足够的想象力。妹子打伞的这个还好说,直接写成二进制文件就是下一步的结果,红衣端庄全身照的那个,作者最后说搞出来一段二进制码是重复的,并且最后一次重复还有点噪声,然后作者就直接扣出那一段分析,不管其它的了,总觉得不够完美啊,恩。。果然还是这一步最难了。

下面把文本二进制码写成二进制文件的代码贴下,需要说明的是,这段代码不通用,因为我默认的二进制码总数是8的倍数(太烂了,好久不写cpp)。

#include<fstream>
#include<iostream>
using namespace std;
int main(){
    ifstream infile;
    infile.open("binary");
    if(infile){
        cout<<"open success!"<<endl;
        ofstream outfile;
        outfile.open("binaryout",ofstream::out);
        if(!outfile){
            cout<<"open write file failure"<<endl;
            return 0;
        }else{
            cout<<"open outfile success!"<<endl;
        }
        char in,out,tmp;
        int count=0;
        int totalInterator = 0;
        out=0;
        while(true){
            cout<<"totalInterator:"<<totalInterator<<endl;
            totalInterator++;
            in = infile.get();
            if(!infile.good()){
                break;
            }
            if(in==10){
                continue;
            }
            tmp = ((in-'0')<<(7-count));
            out = out | tmp;
            count++;
            if(count==8){
                count=0;
                outfile.put(out);
                outfile.flush();
                out=0;
            }
        }
        outfile.flush();
        outfile.close();
        infile.close();
        cout<<"done"<<endl;

    }else{
        cout<<"open error!"<<endl;
    }
    return 0;
}

在(上)中,作者反复提到了big-endian,little-endian,但是这里其实是用不到这个概念的==!不信你看他最后结论是不是都是big-endian正确?big-endian,little-endian分别是一个数存储的时候以高位地址结尾和以低位地址结尾, 但是单位是字节,因此又称作高字节序和低字节序。一个ASCII码本来就是一个字节,因此也无所谓高字节序,低字节序了。作者的意思可能是一个字节正着存还是反着存,这个我觉得除非是解人家加密的密码,否则没有这个考虑的必要。

写出来的二进制文件,要分析它的属性,就需要看文件的头几个字节,类型一般是前三字节。我从网上搜来一点类型,展示一下。

      SWF (swf):"435753"或者“465753"
      JPEG (jpg):"FFD8FF"
      PNG (png):"89504E47"
      GIF (gif):"47494638"
      TIFF (tif):"49492A00"
      Bitmap (bmp):"424D"
      CAD (dwg):"41433130"
      XML (xml):"3C3F786D6C"
      HTML (html):"68746D6C3E"));
      Word/Excel (xls.or.doc):"D0CF11E0"
      Access (mdb):"5374616E64617264204A"
      ZIP Archive (zip):"504B0304"
      RAR Archive (rar):"52617221"
      Wave (wav):"57415645"
      AVI (avi):"41564920"
      Real Media (rm):"2E524D46"
      MPEG (mpg):"000001BA"或者"000001B3"
      Quicktime (mov):"6D6F6F76"
      Windows Media (asf):"3026B2758E66CF11"
由于linux不是靠扩展名识别文件类型的,所以gnome一下就认出了这是gz,不然我们就自己搜然后用对应的软件打开好了。

给二进制文件(我的叫binaryout)加上扩展名gz,命令行解压下:gunzip binaryout.gz。或者保留着源压缩包,gunzip -c binaryout.gz > binaryout

不加扩展名,gunzip默认是不给你解压的,除非加上参数-f。

然后华丽的class文件就出来了~cafe babe有木有~

你可以这么看二进制文件:vim binaryout -b以二进制方式察看,然后在vim里面转换成十六进制,看的方便点: %!xxd .有一篇文章讲的就是这个。

直接运行找不到类是正常的,因为Java 要求文件的类名要和程序里的类名统一的,即主程序类名是A,那么这个编译后的class文件命名为A.class。我们搞成这种形式就能运行了。在(上)中,java抛出的错误直接提示了类名是i。我的并没有这个提示,只说找不到类。其实都到这步了,哪用管这么多,直接jd反编译,看结果。不贴代码了,(中)里面62楼有写的,那就是完整代码。

然后或者你把binaryout改名成i.class,或者你干脆把代码copy到你的eclipse里运行一下,URL结果就出来了。

其实这段java代码也挺好玩,这段杂乱的字符串是怎么组织起来成为URL的?

我们通过以下代码来看每次访问的index

#include<stdio.h>
int main(){
    int arr[42];
    int x,i;
    for(i=0;i<42;i++){
        arr[i]=0;
    }
    for(i=0;i<50;i++){
        x = i * 6 % 41;
        printf("%d",x);
        if(arr[x]==0){
            arr[x]=1;
        }else{
            printf("collision!");
        }
        printf("\n");
    }
    return 0;
}
输出结果发现,前41个根本没有冲突,接下来才会发生冲突。而 www.i.u-tokyo.ac.jp/fun/hikari-loveletter,这段URL长度正好是41!因此只要对URL每个字符换到新的位置,就是w-aurlwtcniewo./-t.kjhltiypioe.o/kvru.fae这段混乱的字符了。

东京大学这么用心,给跪了。。情报,和服,妹子,诗跟音乐,这海报牛大了。


你可能感兴趣的:(东京大学招生海报上的那些事(下))