从 API 的素质可以看出公司的气质

2017-11-21 23:49:06 +08:00
 quietjosen

今天在改进 iText 上传前压缩大图的功能。其中,百度、腾讯、Google 等各家 OCR 服务对上传的图片尺寸都有要求、也都要求对图片进行 base64 压缩。可这要求跟要求可就不同了。

为什么实际大小与宣称大小不一致呢?

既然 base64 会带来计算上的麻烦,为什么不直接使用解压后的图片大小呢?没错,Google 就是这么干的。你无需考虑 base64 带来的尺寸增加,也无需考虑一个字符串到底占几个字节,只要原图是 4 MB 以下即可

从这一点上看,服务接口的素质(公司的节操)顺序为:

Google > 腾讯 > 百度

13150 次点击
所在节点    程序员
70 条回复
Tokin
2017-11-23 09:41:23 +08:00
google 明显更人性化啊,虽然百度和腾讯文档写的很清楚,但是明明可以做的更好的。大概这就是气质???
pathbox
2017-11-23 09:46:16 +08:00
讲真 API 文档这一类,是一家互联网科技公司的 “门面” 。大家共勉
jimrok
2017-11-23 10:23:06 +08:00
google 确实比百度好不少,接口文档就是计算机里的电路板,看过苹果的,再看其他的机器就知道差距是全面的。
XYxe
2017-11-23 10:29:58 +08:00
https://i.loli.net/2017/11/23/5a162fb434cdf.png 这是一个 2.48MB ( 5752*4824,超过要求了)的图片,base64 以后是 3.31MB。

时间有限,只测试了百度的 API。代码:

```python
import requests
import base64

rsp = requests.post('https://aip.baidubce.com/oauth/2.0/token', data={'grant_type': 'client_credentials', 'client_id': API_Key, 'client_secret': Secret_Key})
token = rsp.json()['access_token']

f = open('sbpen.png', 'rb')
d = f.read()
b64data = base64.b64encode(d)

rsp = requests.post('https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic', data={'access_token': token, 'image': b64data})
print(rsp.json()['words_result'])
```
输出:
[{'words': '为什么实际大小与宣称大小不一致呢?'}, {'words': '首先,base64 压缩后,得到的大小、会增加约 1/3'}, {'words': '·进一步,base64 是使用字符串表示的。那么
,一个字符串如\'a"占几个字节呢?看起来百度是使用 2,腾讯是使用 1'}, {'words': '综合起来,就是上面看到的缩水版大小'}, {'words': '另外,百度要求图片最大分辨率为 409
6*4096;而其他 2 家则无此要求'}, {'words': '既然 base64 会带来计算上的麻烦,为什么不直接使用解压后的图片大小呢?没错, Google 就是这么干的。你无需考虑'}, {'words':
'base64 带来的尺寸增加,也无需考虑一个字符串到底占几个字节,只要原图是 4MB 以下即可'}, {'words': '从这一点上看,服务接口的素质(公司的节操)顺序为:'}, {'words':
'Goog1e>腾讯>百度'}, {'words': '第 1 条附言·1 天前'}, {'words': '哎,我真是看不出黑百度或者腾讯对我有什么好处,只是多次试错后过来发个牢骚'}, {'words': '对,base
64 编码我写成了压缩,这点可以'}, {'words': '对,「计算方式」」是我根据测试结果逆推的,看起来是有点问题,这个可以喷;不过「实际可用大小√」是我实测的结果,'}, {'w
ords': '这个是准确的。'}, {'words': '以上,请尽情喷、吐槽、Bs;吐爽了,可以往下看;不然请继续。'}, {'words': '不过,「 base64 编码后大小是 4MB 」,请问这 4MB 如何计算
?'}, {'words': '是 4MB 「个」编码后的字符串?测试结果不是;是每个字符占 2 个字符吗?百度的测试结果是(虽然这并没太多道'}, {'words': '理)。还请行家指个点,这个 4MB 到
底怎么比较?最好解释清楚后再 BS 我,显得更专业'}, {'words': '听以,我最想吐槽的是这一点:为什么不直接使用原图来判定、而要用 base64 的这个说不清楚的大小?平白给开发
者带'}, {'words': '来这样的麻烦?只是为了服务器减少一次解码的开销?我只能这么想。'}]



不知道你的 1.5MB 是怎么得出来的。

另外,计算一个字符串占用空间很难吗?
quietjosen
2017-11-23 11:04:16 +08:00
@XYxe 首先,谢谢你这么有技术含量的回复。

1. 我试了你的代码和图片,可以上传、识别,没有问题。
2. 我试了你的图片和我的代码,依然提示图片大小不正确。

为什么呢?

我检查了下,因为你用的是普通的识别:
https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic

我用的是高精度识别:
https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic

如果,

- 你的代码改用高精度识别,失败,提示图片大小不正确。你可以试试。
- 我的代码改用普通识别,成功

依然是几个事实:

- 百度的文档( https://cloud.baidu.com/doc/OCR/OCR-API.html )里并没有说高精度识别的尺寸应该比较小。


- 为什么 5752*4824 明明已经超出了百度规定的「最长边最大 4096px 」,普通版依然能正确识别?

我就不推导什么结论了,看官自己心里自有判断。
XYxe
2017-11-23 11:22:40 +08:00
@quietjosen #61 这个错误提示是因为图片尺寸太大了。
https://i.loli.net/2017/11/23/5a163e6d996a8.jpg 这个 2.95 MB,4000*3356,base64 以后大概 3.9MB 。
高精度识别,你试试?
quietjosen
2017-11-23 12:18:41 +08:00
@XYxe 我用你的图片试了,高精度可以识别。

那看来上一张图说明的问题是:通用文字识别对最大分辨率的判断不准确,而高精度识别是则是准确的。

另外,百度的错误码并没有区分是图片太大,还是分辨率太大,是混在一起的,不太好:
216202 image size error 上传的图片大小错误,现阶段我们支持的图片大小为:base64 编码后小于 4M,分辨率不高于 4096*4096,请重新上传图片

到目前,我奇怪的是,我之前确实出现过分辨率正确、图片尺寸太大,也返回 216202 这个错误。这次用你的图试,就没出现。之后有时间多造些图试试。不过目前打算中文抱腾讯的大腿了,因为感觉腾讯对英文的识别比百度好。国外用户抱 Google 大腿。
Kisesy
2017-11-23 12:56:37 +08:00
@quietjosen 你就不能发个你不行的例子,让别人试一下吗
quietjosen
2017-11-23 14:32:00 +08:00
@Kisesy 你这个问题问的很好。

首先回答你的问题:我应该是无法提供这样的图了。具体请向下看:

我在试着做出这样的图时,可能发现了问题。比如,当我在压缩一张 2000*2000、大小为 5,217,759 bytes 的图时,当「压缩」为 2187*2187、大小为 2,397,638 bytes 时,我觉得,恩,图片肯定对了,base64 后大小也没问题。于是就去上传到百度,发现还是得到 216202 这个错误。我想,分辨率没有问题,自然是图片大小比较出现问题。恰好,当继续压缩后(比如文中提到的 1.5MB )时,可以上传并成功识别了。

所以,我会得出文中开头的推论:可能跟 base64 大小及编码比较有关。

但,你在让我提供这样的图时,我就把压缩过程中、存在于内存中的图片输出出来,结果一看,虽然大小确实是 2,397,638 bytes,但分辨率却是:4374*4374,超出了百度 4096*4096 的限制,所以出错了。

奇怪,明明是压缩了,为什么分辨率反而提高了?

我又用工具查看图片信息,发现 DPI 是 144:



这应该就是原因了。原图应该是 72 DPI 的,而由于我通过 NSImage 缩放、在用 NSBitmapImageRep 取 jpeg 格式的 Data 时,估计 Mac Book Pro 使用 144 来计算 pixels,也就是,把 2187*2187 乘以 2,变成了 4374*4374。



于是这些计算都在内存中,我确实没有发现;直到你让我提供这样的图,还得谢谢你的问题。

所以,我应该收回对百度的批评,并对百度可能的名誉损失道歉。

不过,我依然保留对百度此 API 保留意见:

- 如果百度返回错误区分图片大小和分辨率错误,我就可以很容易地发现问题。
- 如果百度不限制分辨率( Google 和腾讯均未限制),也就不会出现问题。
quietjosen
2017-11-23 14:35:58 +08:00
更正:上楼中的 2000*2000、大小为 5,217,759 bytes 的图,数据不正确,应该是 3000*3000、大小为 13,452,222 bytes ;多次测试过程中,数据贴错了,抱歉。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/408422

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX