注:推荐先下载文末的 Workflow,照着本文边看边用,多多动手能获得更好的理解。
正值期末,一位学生读者 @Teresa想养个猫 问我讨一个「能提取照片中文字」的应用,我一笑:这不就是 OCR(Optical Character Recognition,光学字符识别) 嘛。遂推荐 TextGrabber,不过很快被吐槽「好难用,根本不知道点哪里」,又补一句「怎么把没用的页码也识别进来了」,最后补刀一下「折腾半天也不知道怎么把文字发到微信里」。 她的一连串碰壁,反映了 TextGrabber 设计不够人性化的地方。于是我做了一个 Workflow,实现这样的效果:选择图片,运行后弹出文本选择界面,选中所需的文字片段后即自动复制到剪贴板。
思路
这个 Workflow 的核心就是利用现有的 OCR 接口,把图片上传、获取文字。提供 API(Application Programming Interface,应用程序编程接口)的厂商不少,但是微软已经从申请的次月开始收费,谷歌无法正常访问,所以我转向了国内大厂。最后考虑百度的 API 使用起来相对简单,更适合用 Workflow 来交互,所以我选择了它。
选好 API,就去读读它的开发文档,我揪出了重点步骤:
对制作过程不感兴趣读者可以只读「获取 AK/SK」部分,然后直接跳到文末下载 Workflow、按照里面的提示框填入自己的 AK 和 SK。
获取 AK/SK
你可在 百度云计算 免费申请一个文字识别 API。登陆百度账号后选择「创建应用」,填一份简单的表格说明你打算干什么。 之后你会在左侧的「应用列表」里看见申请到的 API。记下里面的 AK 和 SK,它们相当于 API 的钥匙,后续会用到。保护好你的 AK 和 SK。
现在新建第一个 Workflow,拖入一个「Text」并填入 AK,后接一个「Set Variable」把 AK 设为变量,名称自己能看懂就行。设置 SK 变量可如法炮制。
生成 access_token
为了防止 API 被滥用,光有 AK 和 SK 两把钥匙还不够,你需要找百度服务器把它们合成一把新钥匙:access_token。这是一把动态的钥匙,每 30 天会自动过期(但是可以不断重新生成),所以我们要做一个 Workflow 来生成它。
具体说,我们要把 AK 和 SK 两把钥匙做为参数上传(POST)到 https://aip.baidubce.com/oauth/2.0/token 。官方说明在 这里。落实到 Workflow 里需要「Get Contents From URL」这个动作: 上传好了还没完事,服务器会把 access_token 交给你,不过它夹杂在一串貌似乱码的 JSON 里,所以再加一步把 access_token 提取出来:
现在保存好这个 Workflow,取个名字(比如「access_token」),我们将在之后复杂 OCR 功能的 Workflow 里调用它。分成两个动作是为了降低制作难度,毕竟挤在一起太长了,另外也方便以后你拿这个 API 做别的 Workflow。
上传图片
终于要上传图片了,百度提供了多个 API,我选用的是高精度版文字识别,每天有 50 次的上限,已经足够我使用。
和获取 access_token 一样,也是用「Get Content From URL 的」动作来上传图片、获取文字,不过百度的 API 对图片有特殊要求,需在 base64 编码后进行 urlencode,你可能看得云里雾里,其实就是把图片转成一串文字,好让服务器能看懂。
我们先按照 官方文档 进行编码,Workflow 里预设了相关的动作: 由于我把这个 Workflow 当作 ShareSheet 插件用,所以图片编码的一系列动作放在了开头。如果你想拍照识别,就在一开始加个拍照的动作。
接下来调用生成 access_token 的 Workflow:
现在图片和 access_token 就到位了,让我们准备上传。需要注意,access_token 得直接放在 URL 里,需要填进 Workflow 的 URL 地址就成了这样:
https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=【这里换成你的 access_token】
另外再加上一个 Content-Type 参数,值为 application/x-www-form-urlencoded。所有所需参数在 Workflow 里的对应表达方式如下:
返回的结果看起来一团乱麻似的的东西,按层级表示出来应该是这样的:
我们真正想要的是嵌在方括号里的粉色部分。
所以第一次「Get Dictionary Value」的 key 应该是 words_result,获得一串 words: 打头的列表(粉色部分),它们按行分割了识别结果。最终需要的是 words 的值,所以再用一次「Get Dictionary Value」,key 设为 words,并且用循环挨个取出来。
现在为识别结果设一个值,我就直白一点管它叫「result」。不过还没结束,这样的一个列表非常粗糙,还要调教一下。
调教识别结果
识别结果是一个列表,里面往往夹杂着标题、页码等不需要的东西,甚至会有识别错误的部分,所以我要加一个选择的功能,只保存所需的识别部分。
所幸上一步结果是列表,我们能够直接加一个「Choose From List」动作,勾选多项、默认全选,实现选择部分识别结果的功能。选择的结果通过「Combine Text」组合起来,设置「New Lines」让每条结果之间换行,最后组成一段文本拷贝进剪贴板。
如果想要预览识别结果,也可以加一个发送通知的动作,要求高一点的话还可以用「Get Variable」动作把最开始的图片也放进通知里(右图),就能实现「原图+文字」图文并茂的通知效果了。
小结
市面上的 OCR 应用非常多,其中有特色的不少,但是兼具中文识别和极简功能的不多。这个 Workflow 就是为有着轻度中文 OCR 需求的人而准备,速度快、直接复制,还能选择自己要的那一部分识别结果。当然,如果你有非常重度的需求,还是得依靠专门的应用。
大家可以在下面下载两个 Workflow,请在「获取 access_token」中填入你自己的 AK 和 SK。