从一篇帖子说起

十一月末的时候,我在论坛里看到一篇帖子,标题是:总是担心忘了她17岁的样子,常从梦中惊醒。
楼主在帖子里写道:

从16岁开始的互相喜欢,至今已15年了。
……
可最近常想起点点滴滴往事,竟忘掉好多……
人的一生很长,记忆有限,我想记住她一生的各个时刻,一颦一笑,直至终了。
有什么好的方式,像打开时间盒子一样,可尽情随意翻看……

我不由得替未来的我感到一丝担忧,担忧漫长的岁月将会风化记忆,在一个悠闲的下午,录音机突然在某一段卡带,那张无法再播放的磁带,就是我人生中的一段空白。

我甚至开始担忧有些实物将会因为意外变故而消失,以我的人生体验来看,以普通人的条件,想要长长久久地保存实物是很难的。有些东西在丢失的时候未必会有所触动,可是在某一天忽然想起来的时候,能体会的心情也许只有惆怅了。老了以后,我也许没办法告诉世界来过,但是至少应该可以告诉自己“我来过”。

高中毕业后,我清理了很多物件,有些现在看来很珍贵的东西在当时被我一狠心扔了。后来我才明白,很多东西和时间一样是一去不复返的。

在看到那篇帖子后,我决定把保存下来的纸质物品电子化。

这些纸质文件大多是高中时的,也有一些是大学时留下的,甚至还包括我写的小说和应付语文老师写的日记。20年初我就对自己写过的东西做过一次整理,不过主要是对自己写的诗和随笔,而且这些文字大都有电子档,只需要整合到一起即可。但是大量的纸质文件电子化却十分麻烦,我花了一晚上才把高中时写的日记搬到博客上,要用人力搬运高中三年留下的文件的内容,简直有如愚公移山。

为了能够把大量的纸质文件电子化,必须找到一种高效的处理方式。我先后想到了这些办法:

  1. 扫描仪把纸质文件转图像
    • 优点:高效,准确。
    • 缺点:无法把内容转成可处理的文字;在文印店无法保护文件中的个人隐私;最大的缺点,我没钱。
  2. 市面上的文档扫描软件
    • 优点:基础功能不要钱,0成本。
    • 缺点:低效,不适用于处理大量文件。
  3. 自行编写高效的文字识别程序
    • 优点:可以根据需求自由定制,图像转文字方便。
    • 缺点:数不清的BUG和跳不完的坑。

最后我选了方案3。如果我不差钱的话,用扫描仪获得图像,再把图像内容转文字的方法大概是最优的,因为扫描仪获得的图像是没有畸变的,这一点会在之后涉及到。

由于不想花钱买摄像头,因此图像采集由旧手机完成,而在发现轻量的离线OCR对手写体的识别非常糟糕后,我选择使用大厂提供的简单省心的图像识别API。

编写了一个简单的demo并验证了识别效果后,我开始着手编写完整的程序。

第一版程序很简单,按下ESC以外的任意按键,电脑实时读取手机摄像头拍摄的一张照片,然后进行图像识别,把得到的识别结果填入电子文档中,同时保存拍摄的照片以供对比和检错。

第二版程序加入了可以实时预览的视频窗口,这样我就不用再盯着手机屏幕了,同时优化了手机摄像头的对焦,改为按键触发对焦,不再在每次拍照前自动对焦,避免因为大面积空白而导致无法对焦。

第三版程序主要调整了摄像头的实时预览,由单线程改为多线程,在图像识别时,也可以保持视频的实时预览。但是带来了新的问题,预览视频的延时非常严重,在我尝试做纸张检测的时候,超高的延时让视频变成了幻灯片,这是由于Python的多线程并不适用于处理视频流这种IO密集型的情况,同时也和OpenCV读取视频流的特性有一点关系。

第四版程序由多线程改为多进程,并且利用列表模拟数据栈来从视频流中获取最新的视频帧,而非上一次获得的帧,解决了延时的问题,除去网络传输视频的延时,已经基本没有额外的延时了。

第四版程序在优化的基础上,进一步加入了纸张检测功能,能够检测到纸张并绘制边框,然后裁剪。

o0RSv4.md.jpg

这其实是为了之后的功能铺路:对我来说仅仅提取出文字是不够的,实际上文件里可能还会包含文字以外的信息,而且我总觉得,有一天这些文件都会因为意外或非意外而遗失,我必须尽可能地把这些文件的全貌保存下来。

下一步,我会把所有裁剪下的纸张图像,结合文字识别给出的坐标,把这些文件转为真正可读的PDF电子书。

为了把图像转成PDF,并且是包含文字的,需要在PDF中写入一层文字,再写入一层图像,并且文字和图像里的文字位置要对应,这样才有比较好的阅读体验。

不过目前还是遇到了一些问题:

  1. 纸张检测带来的一些畸变,导致图像的文字出现了歪斜;
  2. 很难把文字精确绘制到图像的对应位置;
  3. 图像识别给出了文字块的四个锚点坐标,仅凭锚点坐标很难设定字体的大小;
    此外还有很多细节需要处理……

不过总的来说,我很期待敲完最后一行代码的那一天,还有一个月就要回家了,我甚至开始想象,那些锁在抽屉里的信件,再一次重见光日,按张按行地变成电子书,呈现在手机上的样子。