今天在改进 iText 上传前压缩大图的功能。其中,百度、腾讯、Google 等各家 OCR 服务对上传的图片尺寸都有要求、也都要求对图片进行 base64 压缩。可这要求跟要求可就不同了。
为什么实际大小与宣称大小不一致呢?
既然 base64 会带来计算上的麻烦,为什么不直接使用解压后的图片大小呢?没错,Google 就是这么干的。你无需考虑 base64 带来的尺寸增加,也无需考虑一个字符串到底占几个字节,只要原图是 4 MB 以下即可
从这一点上看,服务接口的素质(公司的节操)顺序为:
Google
> 腾讯
> 百度
哎,我真是看不出黑百度或者腾讯对我有什么好处,只是多次试错后过来发个牢骚。
对,base64 编码我写成了压缩,这点可以喷;
对,「计算方式」是我根据测试结果逆推的,看起来是有点问题,这个可以喷;不过「实际可用大小」是我实测的结果,这个是准确的。
以上,请尽情喷、吐槽、BS;吐爽了,可以往下看;不然请继续。
不过,「base64 编码后大小是 4 MB」,请问这 4MB 如何计算?
是 4MB 「个」编码后的字符串?测试结果不是;是每个字符占 2 个字符吗?百度的测试结果是(虽然这并没太多道理)。 还请行家指个点,这个 4MB 到底怎么比较?最好解释清楚后再 BS 我,显得更专业。
所以,我最想吐槽的是这一点:为什么不直接使用原图来判定、而要用 base64 的这个说不清楚的大小?平白给开发者带来这样的麻烦?只是为了服务器减少一次解码的开销?我只能这么想。
「宣称图片大小」这个用词不对,我认。 base64 是编码不是压缩,我懂,不然我也不会说到 1/3 这个词。你要揪着用词不放,你开心就好。
百度和腾讯文档里提了 base64 编码的大小,我绝逼知道。我发贴是为吐槽那些不用图片原始大小、而非得用 base64 编码大小来比较的服务。我吐槽,是因为我花了不少时间试错,不爽,所以要吐槽。
如果你觉得我是来秀下线的、或者觉得我没有资格在 V 站吐槽我认为不爽的事情、或者是为 iText 上线前宣传造势,欢迎在 V 站 Block 我:点我的头像,右边有个 Block. 这样,可以节约你我的时间。谢谢。
最后,继续欢迎有高手能明确指出 4MB 的 base64 到底应该如何比较?最好你试试后再来;因为我试过多次,跟想当然的并不一样,谢谢。
我就问一句:多大(字节)的图片,可以上传至百度、腾讯 OCR 服务?
如果你知道,欢迎告诉我。
我知道,4MB 的图片可以上传至 Google;我自己试过 3.9MB,可以的。
1 kunluanbudang 2017-11-21 23:55:49 +08:00 还有国内公司的 REST API, 用户体验是.. |
![]() | 2 tlday 2017-11-22 00:33:32 +08:00 via Android ![]() 看不懂"一个字符如'a'占几个字节"这条。base64 不就是拿 4 个字节表示原来三个字节表示的东西,用 64 个可见字符映射了 256 个全量字符,不能被三整除的余位补等号的算法么,怎么还有'a'占几个字节这一说。这 64 个可见字符都是 ascii 标准可见字符,在 utf8 和 ascii 下编码和占用空间不也是一样的么,怎么还有百度用 2,腾讯用 1 之分? |
3 OldPanda 2017-11-22 03:41:10 +08:00 不禁想起两年前用豆瓣 API 搞了个图片同步工具,然而不久后豆瓣就把 API 关了 ┑( ̄Д  ̄)┍ |
![]() | 5 CSM 2017-11-22 08:25:30 +08:00 via Android 第一看到 base64 *压缩*这种说法... |
![]() | 6 onlyice 2017-11-22 08:42:32 +08:00 感觉这个有点为黑而黑了。 你觉得像百度 / 腾讯会在意这点大小吗?用 2M 会比 1M 增加很多成本吗?会需要为了宣传而搞一个大一点的数字吗?有什么意义呢。。 这只能说明文档上写得不严谨,还能跟公司挂钩起来,也是有意思 |
7 missdeer 2017-11-22 08:43:58 +08:00 ![]() 第一看到 base64 *压缩*这种说法...+1 |
![]() | 8 azygote 2017-11-22 08:46:28 +08:00 压缩后体积会变大…… |
![]() | 9 MrSong0607 2017-11-22 08:48:47 +08:00 第一看到 base64 *压缩*这种说法...+2,base64 不是编码么 |
![]() | 10 xiaojunjor 2017-11-22 08:52:04 +08:00 “首先,base64 压缩后,得到的大小会增加约 1/3 ”。。。压缩后大小增加了??? |
11 leeg810312 2017-11-22 08:53:55 +08:00 via Android 百度和腾讯没有在文档说清大小是 base64 格式,谷歌说的是图片文件大小,为黑而黑,而且还说错了,base64 是压缩? |
12 xsd3169 2017-11-22 08:54:33 +08:00 第一看到 base64 * 压缩 * 这种说法...+3。。。确定不是 ** 膨胀 **吗? |
13 q409195961 2017-11-22 09:00:34 +08:00 第一看到 base64 *压缩*这种说法...+4 编码:aGVsbG8lMkN3b3JsZA== 明文:hello,world 压缩了?? |
![]() | 14 onlyice 2017-11-22 09:02:01 +08:00 ![]() 百度的文档[1],清晰地写着「 base64 编码后大小不超过 4M 」;腾讯的文档[2]写着「原始图片的 base64 编码数据(解码后大小上限 1MB,支持 JPG、PNG、BMP 格式)」。 楼主我不得不说这文章体现的是你的节操? [1] https://cloud.baidu.com/doc/OCR/OCR-API.html [2] https://ai.qq.com/doc/ocridcardocr.shtml |
![]() | 15 marcong95 2017-11-22 09:11:09 +08:00 via Android @onlyice 2M 跟 1M 翻了个倍,成本也翻倍,作为一家巨头公司成本翻倍不在意?多了 50%的利润空间根据邓宁格的说法就已经引起积极的冒险了。资本是逐利的,国内大型公司没节操的事情还见得少? 不过呢,这件事上好像并不怎么能黑,我看了下他们的文档,百度写的是 base64 字符串小于 4096K,腾讯写的是图片小于 1M,跟楼主所说的一致,两者好像都没有什么不严谨的地方。 |
17 mengzhuo 2017-11-22 09:13:56 +08:00 via iPhone 看到 base64 压缩之后就不想看后面,直接看评论 |
18 xfspace 楼主想黑百度腾讯,没想到被自己智商秀了一波 |
![]() | 19 onlyice 2017-11-22 09:16:58 +08:00 @marcong95 一个 OCR 服务能有多少成本?又不是全部服务都翻一倍。但这不是重点,重点还是人家文档已经写清楚了,楼主强行表示对方夸大 |
![]() | 20 AV1 2017-11-22 09:23:39 +08:00 此前见过说 base64 “加密”的,base64 “压缩”倒是第一次见…… |
21 abujj 2017-11-22 09:39:00 +08:00 via iPhone 谷歌 API 地址能发下看看吗? 楼主 |
22 bzzhou 2017-11-22 09:50:22 +08:00 ![]() base64 压缩,呵呵 |
![]() | 24 BBCCBB 2017-11-22 10:01:28 +08:00 |
![]() | 25 xiao17174 2017-11-22 10:15:21 +08:00 ![]() 显然楼主对于为什么用 base64 完全不懂,对于字符编码,字节,位什么的更是从来没有涉及过. 由此可以推断楼主在成为程序员后就一直从事高级语言的相关工作. 建议楼主可以适当下潜,多了解一些基础的东西. 最后解答一下楼主提出来的"请问这 4MB 如何计算?" 答:不要把字符编码和数据大小混在一起. 一个字符'a'占用几个字节是你自己决定的,当你声明你发送的是以 ascii 编码的数据时,它占一个字节.当你声明你发送的是以 chibaolecengde 编码的数据时,它可以是占 10 个字节. 既然人家都说了是要 base64 后的数据发送,那么显然是 ascii 编码.即编码后的数据,每一个可见的字符,如'A','='都是占用一个字节. |
26 keenwon 2017-11-22 10:17:20 +08:00 base64 是压缩? |
![]() | 27 xiao17174 2017-11-22 10:20:40 +08:00 ![]() 另外,多一次 base64 编码在麻烦程度上来说,对谁都没有好处.服务器在拿到你 base64 的数据后,必然是要做一次反编码来获取真实数据的.只是 base64 可以归一化所有的二进制数据到 ascii 码上,从而变成更通用的 string. |
28 keenwon 2017-11-22 10:20:51 +08:00 歪个楼,MD5 算加密吗? |
![]() | 29 xiao17174 2017-11-22 10:24:54 +08:00 ![]() @keenwon 是摘要算法.可以理解一个 md5 是一篇文章的中心思想. 加密成立的前提在我看来是可以解密,但是我们显然无法从中心思想反推全文,所以不算. |
![]() | 31 ioth 2017-11-22 11:20:10 +08:00 说明咱天朝人会过日子,节省 |
![]() | 32 Youen 2017-11-22 11:20:34 +08:00 阿里的我测试过,文档说图片大小不超过 1.5MB, 我用 1.47MB 文件 base64 编码后约 1.9MB 可以识别 |
![]() | 33 sneezry 2017-11-22 11:26:17 +08:00 其实 API 更严格的限制并不让人不快,即使百度最大图片支持 1.5MB 也没什么问题。问题是为了显示自己有优势而进行虚标,这在实际使用时会出现诡异的问题。 |
34 zwh2698 2017-11-22 11:31:19 +08:00 via Android 顶,兄弟 |
35 jyf 2017-11-22 11:34:37 +08:00 ![]() 从吐槽上也能看出一个人的素质 这不就是百度图省事 在上传服务器上做了个请求体大小的限制么 这种也要罗嗦一堆也真是 |
![]() | 36 nine99 2017-11-22 11:40:34 +08:00 itext 还不发布吗 |
37 veightz 2017-11-22 13:23:30 +08:00 一个 API 也许能代表某个开发,但是代表不了一个公司 |
![]() | 38 mikulch 2017-11-22 13:54:58 +08:00 国外的公司,在人性化,细节等方面本身就完爆中国的公司 从制造业就能看出来了。 |
![]() | 39 zhouyg 2017-11-22 14:51:11 +08:00 百度最喜欢搞虚假的东西,果然连技术人员的骨子里都是腐蚀透了 |
![]() | 40 moonsola 2017-11-22 15:06:19 +08:00 |
![]() | 41 schema 2017-11-22 15:59:12 +08:00 标题日常哗众取宠 |
![]() | 42 st2udio 2017-11-22 16:36:37 +08:00 原始图片的 base64 编码数据(解码后大小上限 1MB,支持 JPG、PNG、BMP 格式) base64 编码后大小不超过 4M,最短边至少 15px,最长边最大 4096px 有不对的宣传吗?不懂。。 [为什么实际大小与宣称大小不一致呢?] 还只是为了推广你的软件,所以要 |
![]() | 43 so898 2017-11-22 17:00:40 +08:00 腾讯那个确实有点难找,百度这个可是重复声明了 14 遍啊~~~~~~ 估计楼主的母语是英语吧,看英文仔细程度大于看中文仔细程度 |
44 yuriko 2017-11-22 17:04:10 +08:00 当喷国内公司变成政治正确的时候,不懂瞎说的也有底气了…… |
45 MushishiXian 2017-11-22 17:26:45 +08:00 v2 太可怕了... |
![]() | 46 Charkey 2017-11-22 17:30:03 +08:00 so 世界好可怕,到处 pen |
![]() | 47 quietjosen OP @xiao17174 在这些回复中,你的最有技术含量。 不过,事实上,如果发送 3MB 个字符(按你所说是 ASCII 编码)的 base64 编码的图片给百度,百度是会报错的,说图片尺寸不对。我也只能推测 http 请求是按 utf8 传送、每个字符占 2 位,所以要 /2 ;不然,我是没办法和事实对应。 |
![]() | 48 xiao17174 2017-11-22 18:12:30 +08:00 @quietjosen utf-8 是一种编码规范,实际上它是可变长的,并不是所谓的每个字符占 2 字节(不是位).而且正如楼上某位说的,utf8 是兼容 ascii 的,也就是说针对'a''A'这种,utf8 也规定只占用一个字节.可能我说这些你会听得一头雾水. 如果有空可以自己了解一下. 至于你说的猜测,我也有几个猜测. 1.你以为的 3MB 个字符其实并不是真的 3MB,实际的字节数已经超过 4MB,你可以看下你的 context-length 上标识的是多少. 2.如返回值所说,你传的图片的尺寸真的超出 15px*4096px 限制. 3.你传的数据在某个过程中被截断了.可能是你这边,也可能是在服务器那边,错误的数据导致了百度解析图片出错,而服务端的返回值延用了尺寸不对的错误码.本质上是数据解析(读取图片)出错. |
![]() | 49 xiao17174 2017-11-22 18:13:58 +08:00 我为什么这么空....伤脑筋啊... |
![]() | 50 quietjosen OP @xiao17174 谢谢回复。 1. 对,我说的是 3MB 个字符;如果确实是用 UTF8 编码、英文字符占 1 个字节,那按道理应该是 3MByte 了。 2. 图片没有超出尺寸限制 3. 应该不是,因为如果解析出错,返回的错误是不同的。 有时间,我测试下连续的尺寸,比如 2.01MB/2.02MB/…/3.00MB,看哪个尺寸开始不行。 问题就在于:为什么要让每个接入服务的开发者,花这么无谓的时间、做这种无谓的试错?看看人家 Google,只要原图 OK 就行。 |
51 xy90321 2017-11-22 19:34:01 +08:00 ![]() @quietjosen 如果照着 API 文档开发也能算试错的话,我建议你自己去发明所有轮子这样就不存在试错了 别人 API 文档里写的那么清楚了,哪里存在试的过程了。。。 要吐槽 API 不够人性化那就请明明白白吐槽 API 不够人性化 非要整点素质啊气质啊什么的,上升到百度腾讯就是渣渣,看我大谷歌秒杀全场 再加上顶楼里那简直可以称为之污蔑诽谤与事实完全不符的描述 这就是所谓的带节奏失败反过来装人畜无害吗? |
![]() | 52 sicongwang 2017-11-22 21:02:11 +08:00 为黑而黑, 已 block |
53 leonzoe 2017-11-22 23:25:01 +08:00 只能说同情楼主了.楼上一群人既没试过,也没给个公式算一下,这就开始喷了,斯阔以. |
![]() | 54 inoris 2017-11-23 00:06:27 +08:00 同情楼主。 |
![]() | 56 Technetiumer 2017-11-23 01:38:42 +08:00 via Android 明了 Google 更人性化 省了你的去算 base64 後大小 有人主了 那我也回复不要了 |
![]() | 57 chnyang 2017-11-23 08:01:50 +08:00 via Android @Technetiumer 指出楼主为喷而喷并不算喷 |
![]() | 58 dazui 2017-11-23 08:08:34 +08:00 国内都是参考切糕的卖法,只卖 10 元,然后你要算算是 1 克、1 块还是 1 斤 |
59 atcdef 2017-11-23 09:17:21 +08:00 楼上有很多抠字眼,base64 压缩,这样说应该明白楼主说的是编码,至于死抠“压缩”两个字么。 |
![]() | 60 root123 2017-11-23 09:23:26 +08:00 同情楼主。+1 很喜欢 LZ 的系列 APP,都很方便实用。 而且在开发 APP 的过程中,楼主也经常分享技术、运营的相关经验,很不错啊。 |
![]() | 61 Tokin 2017-11-23 09:41:23 +08:00 google 明显更人性化啊,虽然百度和腾讯文档写的很清楚,但是明明可以做的更好的。大概这就是气质??? |
![]() | 62 pathbox 2017-11-23 09:46:16 +08:00 via iPhone 讲真 API 文档这一类,是一家互联网科技公司的 “门面” 。大家共勉 |
![]() | 63 jimrok 2017-11-23 10:23:06 +08:00 google 确实比百度好不少,接口文档就是计算机里的电路板,看过苹果的,再看其他的机器就知道差距是全面的。 |
![]() | 64 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 是怎么得出来的。 另外,计算一个字符串占用空间很难吗? |
![]() | 65 quietjosen OP @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 」,普通版依然能正确识别? 我就不推导什么结论了,看官自己心里自有判断。 |
![]() | 66 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 。 高精度识别,你试试? |
![]() | 67 quietjosen OP @XYxe 我用你的图片试了,高精度可以识别。 那看来上一张图说明的问题是:通用文字识别对最大分辨率的判断不准确,而高精度识别是则是准确的。 另外,百度的错误码并没有区分是图片太大,还是分辨率太大,是混在一起的,不太好: 216202 image size error 上传的图片大小错误,现阶段我们支持的图片大小为:base64 编码后小于 4M,分辨率不高于 4096*4096,请重新上传图片 到目前,我奇怪的是,我之前确实出现过分辨率正确、图片尺寸太大,也返回 216202 这个错误。这次用你的图试,就没出现。之后有时间多造些图试试。不过目前打算中文抱腾讯的大腿了,因为感觉腾讯对英文的识别比百度好。国外用户抱 Google 大腿。 |
![]() | 68 Kisesy 2017-11-23 12:56:37 +08:00 @quietjosen 你就不能发个你不行的例子,让别人试一下吗 |
![]() | 69 quietjosen OP @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 和腾讯均未限制),也就不会出现问题。 |
![]() | 70 quietjosen OP 更正:上楼中的 2000*2000、大小为 5,217,759 bytes 的图,数据不正确,应该是 3000*3000、大小为 13,452,222 bytes ;多次测试过程中,数据贴错了,抱歉。 |