这篇的内容其实跟python的关系不是很大,是在使用python做文字识别的时候遇到的一个坑,这里大概记录一下,希望大家在使用百度智能云的OCR文字识别的时候,能够快速的解决这个问题。
业务需求大概是这个样子的,学生在使用仪器做完实验之后,仪器会将实验结果,打印在一张小票上。正常,学生需要将小票上边的数据,逐一输入到系统中,但是,客户觉得这个操作太麻烦了,想用文字识别将小票上边的数据识别出来,自动填入,学生只需要检查一遍识别的是否正确即可。
需求很简单,我这里的后端是使用PHP做的,这也不耽误我使用python做文字识别。最开始的python文字识别的尝试,我这里就不做赘述了,具体,请移步《Python爬虫(八)图形验证码识别——自定义OCR文字识别》
但是,之前没有现成的例子,从头写,从头训练模型,代价有点大,后来我们一致决定,使用百度智能云的OCR文字识别来实现这个小功能。具体怎么用,这玩意,有SDK,有官方文档,照着写就行了。这边 通用文字识别(标准版)就可以满足我的需求。其他的模式(高精度,交通场景,卡证等)我就没有深入研究。
这次,客户需求升级,需要读取仪器上边的电子仪表的数据,我这边使用之前接好的通用文字识别(标准版)的接口做测试,对电子屏幕的文字识别率很低。
我这边去百度的产品列表中看了一下,他是有 仪器仪表盘读数识别 这个功能的。价格如下图所示:
买了一万次的,开始霍霍。
他家的调用还是很简洁的,我这里使用的是laravel5.8框架,调用代码如下图所示:
ini
复制代码
/** * @name: 百度文字识别 * @author: camellia * @date: 2022-03-23 * @param $filePath string 文件url */ public function baiduOcr($url) { $client = new \AipOcr($this->AppID, $this->API_Key, $this->Secret_Key); // 调用仪表文字识别, 图片参数为远程url图片 $info = $client->meter($url); // $info = $client->basicAccurate($url); // $info = $client->basicGeneralUrl($url); return $info; }
然后,结果,报错了
css
复制代码
{ "code": 1, "msg": "解密成功!", "words_result": { "log_id": 1527573108083997023, "error_msg": "image format error", "error_code": 216201 } }
Words_result是百度云给我返回的结果。错误码是216201,啥意思呢?官方文档是这样告诉我们的:
我就不明白,我上传的png图片,哪里错了呢?
查文档吧,没有别的办法啊。
官方文档给出的示例代码是这个样子的:
php
复制代码
<?php /** * 发起http post请求(REST API), 并获取REST请求的结果 * @param string $url * @param string $param * @return - http response body if succeeds, else false. */ function request_post($url = '', $param = '') { if (empty($url) || empty($param)) { return false; } $postUrl = $url; $curlPost = $param; // 初始化curl $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $postUrl); curl_setopt($curl, CURLOPT_HEADER, 0); // 要求结果为字符串且输出到屏幕上 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // post提交方式 curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $curlPost); // 运行curl $data = curl_exec($curl); curl_close($curl); return $data; } $token = '[调用鉴权接口获取的token]'; $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/meter?access_token=' . $token; $img = file_get_contents('[本地文件路径]'); $img = base64_encode($img); $bodys = array( 'image' => $img ); $res = request_post($url, $bodys); var_dump($res);
这真是官方文档啊,我用你的SDK一共加上返回值就写了三行代码,调试的时候你让我获取token?也就是说我还得去看看token是怎么获取的呗,不出意外,您这token应该还有过期时间吧。天……
然后,我瞄了一眼他实例代码上方对参数的描述:
注意我红框标注的位置。
我又去他的SDK中看了一下,他的源码:
php
复制代码
/** * 仪器仪表盘读数识别 * * @param string $image * @param bool $probability * @param bool $polyLocation * @param array|options $ * @return bool|mix|mixed|string[] */ public function meter($image, $options = array()) { $data = array(); $data['image'] = base64_encode($image); $data = array_merge($data, $options); return $this->request($this->meter, $data); }
对比一下,各位看官是否发现了问题呢?
您的官方文档中显示的参数是image和url两个参数二选一,但是您实际的代码中,只有image赋值,这我给你传图片url不报错才怪了呢……
咱就说,SDK上线之前能不能和文档对一下。这么低级的错误……
行啊,我这里放一下我修改之后的方法:
php
复制代码
/** * 仪器仪表盘读数识别 * * @param string $image * @param bool $probability * @param bool $polyLocation * @param array|options $ * @return bool|mix|mixed|string[] */ public function meter($image, $options = array()) { $data = array(); // $data['image'] = base64_encode($image); $data['url'] = $image; $data = array_merge($data, $options); return $this->request($this->meter, $data); }
我这里传的是文件的url,所以就不考虑传base64的情况了。改的比较粗暴。各位看官勿喷。
当然,有这个问题的接口,不止这一个,其他的我没有用到,这里就不做修改了。下次有同学遇到类似的问题,记得对照官方文档看一下源码。
有好的建议,请在下方输入你的评论。