surya,一个优秀的OCR开源项目,更专注于表格识别
写这篇文件,因为一条评论。
我写过识别计算器屏幕的文章,讲了它可以独立部署在App、小程序、树莓派等嵌入式设备上。有个老哥说,这都是应用多年的老技术了。
他说得没错,可能多少年前就有了。不过,实际上,一项技术不管应用了多少年,每年依然还有人花钱去做新的。
不知道八零、九零后是否还记得,零几年时的非智能手机,就已经有了手写识别这个功能。甚至它还给你配一个手写笔。
即便这项技术已经30年了。你现在去软件企业问问,如果他家的产品需要一个手写识别的功能,他是不是依然还得花钱买第三方的服务。
为啥?
这个问题非常好,值得思考。
首先,那时候的技术和现在不一样。在非AI时代,手写识别用的是模板匹配技术,是基于规则的。你写的字,它要拿去库里同模板做比对。就像是机器人客服,靠关键字回复一样。你问“房子”它知道,问“屋子”它说听不懂。而现在的手写识别是基于深度学习的,你问它house,它一样知道是住的地方。
其次,就算技术没变化,它的落地实践也是有壁垒的。这体现在两点。第一,给你一个开源项目,你不一定能用起来。第二,每个人的细分需求不一样,就算你能跑起来,也很难改动,个性化定制。
今天,我就讲解一个开源的OCR项目。以此论证我的观点。
我看到这个项目公布好几个月了,各类新闻也是来了一波又一波:《比xx更好的用OCR》《表格识别神器》《今年最火的十个开源项目》……
大家都在传播、转发,哎呀,这个东西好,好用。包括我做卷帘门的朋友都分享给我,说这个好用。但是,没有谁发一篇文章,说他真的用了,是如何用的,效果怎么样,它的原理是什么,它是如何训练的,它有什么优点,它有什么缺点,缺点是否能优化,该如何优化。今天,我就来填补一下。不然又会有人说,哎呀,这东西早就解决,零成本,多少年前就很成熟了。
这个项目的名字叫surya,是一个OCR识别项目,开源地址是 github.com/VikParuchuri/surya ,目前在github上拥有14K个star。它支持本地化部署,面对年收入低于500万美元的商用,可免费。
我在自己电脑上搭了一套,CPU就可以运行,GPU效率更高。稍微试验了下,给大家展示下功能。
一、功能展示
我拿这张图来进行试验,这是某报纸中的一篇新闻稿件。
它可以检测出图中有哪些类型的结构。比如,段落、图片、标题等。下面的图,就是将检测到的区域标记展示。
另外,区域检测还附赠一个阅读顺序的功能。所谓阅读顺序,就是你读这篇文档时,先读哪里后读哪里。比如按照从左到右,从上到下的顺序。有时候,阅读顺序也很重要,不然容易剧透。
既然是OCR,那么必定要将图像转为文字。想要转换文字,首先得知道哪些区域是文字。这个文本行检测,它也有。
检测到文字的位置,下一步就是识别文字了。下面是识别的结果。
最后,展示一下,它的表格识别。测试图片这样。
做一下表格检测,效果如下。
从识别到的数据信息看,它有4行,3列,12个单元格。
再来进行ocr内容识别。
二、算法集成
上面是它的功能。咱先不谈效果。下面我想问,它为什么能做到这些?回答完这个问题,才能更好地理解它的水平。
作者在最后列举了很多感谢,他说不借助这么多优秀的开源模型,他不可能完成这个项目。比如感谢CRAFT项目,这是一个超3k star的开源文本检测模型。
再比如它还采用了donut,这是一个利用无OCR理解文档的新方法。我们知道,想要理解文档,一般先要知道它上面写了什么,然后对文档进行分析,才能做出判断。而Donut结合多模态直接解析图像,极少处理文字,省去了全文分析的这个步骤。
看上面这张图。你问donut这张图的标题是什么?它可以正确地回答出来。这就是对文档的理解。
因此,从算法层面上,surya是借助了很多顶级的开源模型。而那些模型,也是站在巨人的肩膀上。可以说,它集成的算法是目前公开的一流水平。
我们再来说它的训练数据。他的训练数据,我们可以在 huggingface.co/vikp 上找到。
三、训练数据
比如文本区域类型检测,它的训练数据是这样的:
我们来看它的其中一组数据。image是一张图,bboxes是区域框,labels是区域类型,有文本类型,有表格类型。这些数据,是需要标注的,也就是在图片上画框,标注出区域类型。训练总量是1910张图片。不多。
比如表格的分析检测,它的训练数据是这样的:
image是一张表格图片,bboxes是单元格,rows是每一行的区域,cols是每一列的区域。把这些标记好的数据交给算法,让它学习什么样的特征的是行,什么样的是列。数据相对多一些,9680张图片。所以人家说它的表格识别很强。
对于文本行的检测,它的训练数据是这样的:
训练数据的结构组成:图片,图片中的某个区域,此区域对应的文本类型,另外还附加了一个文本内容。就拿上图选中的那条数据来说。这里面只标记了一条文本行区域。它告诉模型,这张图里面有一个类型为7的文本行,其区域是[88, 96, 865, 134](左、上、右、下)围成的矩形,请认真学习。
最后到了,OCR识别了。
训练数据的组成还是老一套,图片,区域框,文本内容。主要是告诉模型,我的这张图里面有几个区域,这些区域是什么文本内容,请你仔细学习。另外,这里面还有一个language字段,这表示文字的语言类型。
surya自称支持90多种语言的识别。这不是胡说,因为他的训练数据里,确实有90多种语言的标注。但是,总量太少了。一共4635张图片,如果平均的话,每种语言只有50来张训练数据。
因此,其实surya对于中文的OCR识别效果不是特别好(虽然自称并肩Tesseract)。其主要原因并不是算法不好,而是中文的训练数据太少。英文26个字母,50张纸可以覆盖。但是中文几万字,很难覆盖全。而对于手写识别,surya只能说随缘,因为根本没有训练数据,识别成啥样就是啥样。
这里面训练数据最多的是表格的识别,共9700张样本。训练数据最少的是阅读顺序的检测,才126张。因此,数据量决定了它的识别效果。对于海量的训练数据,就算对强大的商业公司来说也是一个难题。而作者能够凑足这几千张数据,已然很不容易了。
最终,我可以下一个结论。对于surya,它是一流的算法开源项目,是免费的。它对于表格的分析确实很强大。但是,它的训练数据还是太少,而且主要用于识别电子版的文档(清晰、无扭曲),手写识别基本不支持。如果你想要不做改动直接平替收费的OCR,可行性不高。就算是只用表格识别,你也得有稍微专业一些的人,进行从拍照到预处理成电子版的工作。如果收费的效果都不好,你想用免费替换它,可以打消这个念头。算法是开源的,但是训练数据和训练设备的投入,总得有人出。
如果,你想要学习并调整它,或者想自己训练,那么可以接着往下看。
四、源码运行
我不会讲官方ReadMe.md文档上明明白白写着的内容。比如你需要运行pip install streamlit
。或者它有这么几个参数,第一个--langs
是用于指定OCR的语言。
这样的话,我很像一个复读机。
另外,既然你都想要研究它了,应该不至于按照操作都跑不起来。你去看看它的源码,我只讲关键点。
首先,下载源码。你在源码中可以看到两个文件pyproject.toml
和poetry.lock
。这说明surya用的是poetry作为项目管理工具。poetry既能管理依赖包,也能管理虚拟环境。
咱们最好找一个Linux环境,再安装poetry。即便你在windows下,现在也可以很简单地安装个ubuntu虚拟机。因为linux实在是可以避免很多问题。
打开liunx命令行,进入到源码根目录。先运行pip install poetry
,安装poetry。再运行poetry install
安装依赖环境。最后运行poetry shell
进入环境,你会看到:
(surya-ocr-py3.12) root@tf:/mnt/d/surya#
这时运行surya_gui
,会启动它的web页面。正常情况下,你会看到如下的输出:
https://huggingface.co/vikp
(surya-ocr-py3.12) root@tf:/mnt/d/surya# surya_gui
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.1.109:8501
gio: http://localhost:8501: Operation not supported
Loaded detection model /mnt/d/surya/vikp/surya_det3 on device cpu with dtype torch.float32
Loaded recognition model /mnt/d/surya/vikp/surya_rec2 on device cpu with dtype torch.float32
Loaded detection model /mnt/d/surya/vikp/surya_layout3 on device cpu with dtype torch.float32
Loaded reading order model /mnt/d/surya/vikp/surya_order on device cpu with dtype torch.float32
Loaded recognition model /mnt/d/surya/vikp/surya_tablerec on device cpu with dtype torch.float32
访问localhost:8501还有这样的页面:
但实际上,极有可能不正常。因为它在自动下载权重模型访问 huggingface.co 时会访问失败。这时,需要你想办法手动下载模型,然后放到一个固定的位置。
从报错信息能看到说加载不到模型。跟着代码就找到了surya/settings.py
。
# Text detection
DETECTOR_MODEL_CHECKPOINT: str = "vikp/surya_det3"
DETECTOR_BENCH_DATASET_NAME: str = "vikp/doclaynet_bench"
# Text recognition
RECOGNITION_MODEL_CHECKPOINT: str = "vikp/surya_rec2"
RECOGNITION_BENCH_DATASET_NAME: str = "vikp/rec_bench"
# Layout
LAYOUT_MODEL_CHECKPOINT: str = "vikp/surya_layout3"
LAYOUT_BENCH_DATASET_NAME: str = "vikp/publaynet_bench"
# Ordering
ORDER_MODEL_CHECKPOINT: str = "vikp/surya_order"
ORDER_BENCH_DATASET_NAME: str = "vikp/order_bench"
# Table Rec
TABLE_REC_MODEL_CHECKPOINT: str = "vikp/surya_tablerec"
TABLE_REC_BENCH_DATASET_NAME: str = "vikp/fintabnet_bench"
……
这里面是它5大功能(检测、识别、类型、排序、表格)的权重模型以及训练数据集的路径配置。正常情况下,会自动下载并缓存读取。但现在我们要自己下载并手动配置。下载方式就是去 huggingface.co/vikp 上找对应的模型文件。
用哪个就下载哪个模型文件,即用什么功能就下载什么功能。其实,对于新手来说,这并不好区分。因为有些功能是相互依赖的。比如表格识别,往往需要先检测出表格区域,才能识别行列区域。实际上会走好几个模型。因此,不熟悉的时候,把MODEL_CHECKPOINT
全下载就行了。
DATASET_NAME
是数据集,如果你要重新训练,就下载它。不调用训练的代码,不下载也不报错。
你可以把权重文件下载到项目的根目录。然后做如下的配置:
将"vikp/surya_det3"
改为os.path.join(BASE_DIR, "vikp/surya_det3")
。因上面定义了BASE_DIR是项目根目录,所以这个路径没错。
后面再运行surya_gui
就正常了。
访问 localhost:8501 可以上传文件进行5大功能的测试。
它会展示相应的结果。
而在控制台,也会输出操作类型和时间消耗:
Detecting bboxes: 100%|███████| 1/1 [00:02<00:00, 2.61s/it]
Detecting bboxes: 100%|███████| 1/1 [00:02<00:00, 2.06s/it]
Detecting bboxes: 100%|███████| 1/1 [00:02<00:00, 2.44s/it]
Recognizing tables: 100%|███████| 1/1 [00:01<00:00, 1.19s/it]
这样,你就可以研究它的源码了。你可以改一点代码,运行一下,查看变化。具体的功能模块和代码对应,官方readMe.md上有说明。不管是暴露接口能力,还是修改内部函数,或者重新训练自己的数据,都有了着手点。
五、总结
优秀的开源项目就像一个质量很好的毛坯房,相对于商业软件,它往往不具备舒适的居住条件。但是,它的底子很好,结构合理,质量精良。它想发达,需要有人去做一个精装修。但是反过来,有些商业软件去了精装修,很可能就是豆腐渣框架。
为什么说现在是数据为王的时代。从上面的论述可以发现,在一定时空内,算法是公开的,算力投钱就可以,可能就是数据难搞。有好的、大量的数据投喂,才能产生好的AI模型。
来源:juejin.cn/post/7436713044246806578