zoukankan      html  css  js  c++  java
  • 腾讯Ocr文字识别

    简述

    上篇文章记录了百度Ocr的两种模式用法,接下来这篇文章开始记录腾讯Ocr的使用方法。腾讯Ocr的通用印刷体识别模式使用比较简单,直接接入sdk即可,但手写体的识别相对比较麻烦,需要自己post表单(也可能是能用sdk的,但我是没有找到)

    通用文字识别

    1.直接在Android Studio的app->build.gradle->dependencies中添加:

     implementation 'com.qcloud:qcloud-image-sdk:2.3.6'
    

    2.初始化识别程序:

    ImageClient imageClient = new ImageClient(APPID, SecretId, SecretKey,
    ImageClient.NEW_DOMAIN_recognition_image_myqcloud_com);
    

    其中APPID、SecretId、SecretKey这些和百度一样是需要去注册获取的,具体获取方式没什么难度就不详说(点击前往腾讯AI开放平台)。最后一个参数是服务器域名,默认使用新域名,也就是:

    ImageClient.NEW_DOMAIN_recognition_image_myqcloud_com
    

    如果是老用户,修改为以下域名:

    ImageClient.OLD_DOMAIN_service_image_myqcloud_com
    

    3.开始进行文字识别:

      GeneralOcrRequest request = new GeneralOcrRequest("", getBitmapFile(mBitmap));
            try {
                String orcResult = imageClient.generalOcr(request);
            } catch (AbstractImageException e) {
                e.printStackTrace();
            }
    

    GeneralOcrRequest的第一个参数是bucketName实际上没什么用(官方说是遗留字段,至少对我来说没什么用,不知道实际上是什么样子),可以直接用空字符填充,第二个参数是File,上面代码是我项目中从bitmap获取file文件的写法。代码中的orcResult即为文字识别结果,返回的是一段json数据,需要自己去转换,推荐使用fastjson框架。

    手写体文字识别

    1.本项目中使用的是okhttp3框架进行get-post操作,因此是okhttp3框架的代码写法,实际使用因框架的不同而不同,但发送的数据都一样。如果要识别的图片是一个url地址,则用以下的post数据形式:

    POST /ocr/handwriting HTTP/1.1
    Authorization: 自己生成签名
    Host: recognition.image.myqcloud.com
    Content-Length: 自定义长度       ps:有使用者称加上这个会报错,本人使用的时候是不加上Content-Length的
    Content-Type: application/json
    {
      "appid":"你的appid",
      "bucket":"",
      "url":"图片url地址"
    }
    

    如果识别本地图片,则使用以下post数据形式(本人就是使用本地图片,因此之后的代码是用这种方式):

    POST /ocr/handwriting HTTP/1.1
    Authorization: 自己生成签名
    Host: recognition.image.myqcloud.com
    Content-Length: 自定义长度                      ps:同上
    Content-Type: multipart/form-data;boundary=--------------acebdf13572468
    
    ----------------acebdf13572468
    Content-Disposition: form-data; name="appid";
    
    你的appid
    ----------------acebdf13572468
    Content-Disposition: form-data; name="bucket";
    
    空串
    ----------------acebdf13572468
    Content-Disposition: form-data; name="image"; filename="test.jpg"
    Content-Type: image/jpeg
    
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ----------------acebdf13572468--
    

    上面这些数据让不懂multipart/form-data格式的童鞋来说,看上去就眼花缭乱,不知道该怎么用,但是不要紧,实际上我们根本不需要写这么多东西,这就是使用http框架的好处,它已经帮我们做了很多事。
    2.首先需要自己生成签名:

    public class Sign {
        /**
         * 生成 Authorization 签名字段
         *
         * @param appId
         * @param secretId
         * @param secretKey
         * @param bucketName
         * @param expired
         * @return
         * @throws Exception
         */
        public static String appSign(long appId, String secretId, String secretKey, String bucketName,
                                     long expired) throws Exception {
            long now = System.currentTimeMillis() / 1000;
            int rdm = Math.abs(new Random().nextInt());
            String plainText = String.format("a=%d&b=%s&k=%s&t=%d&e=%d&r=%d", appId, bucketName,
                    secretId, now, now + expired, rdm);
            byte[] hmacDigest = HmacSha1(plainText, secretKey);
            byte[] signContent = new byte[hmacDigest.length + plainText.getBytes().length];
            System.arraycopy(hmacDigest, 0, signContent, 0, hmacDigest.length);
            System.arraycopy(plainText.getBytes(), 0, signContent, hmacDigest.length,
                    plainText.getBytes().length);
            return Base64Encode(signContent);
        }
    
        /**
         * 生成 base64 编码
         *
         * @param binaryData
         * @return
         */
        public static String Base64Encode(byte[] binaryData) {
            String encodedstr = Base64.getEncoder().encodeToString(binaryData);
            return encodedstr;
        }
    
        /**
         * 生成 hmacsha1 签名
         *
         * @param binaryData
         * @param key
         * @return
         * @throws Exception
         */
        public static byte[] HmacSha1(byte[] binaryData, String key) throws Exception {
            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            mac.init(secretKey);
            byte[] HmacSha1Digest = mac.doFinal(binaryData);
            return HmacSha1Digest;
        }
    
        /**
         * 生成 hmacsha1 签名
         *
         * @param plainText
         * @param key
         * @return
         * @throws Exception
         */
        public static byte[] HmacSha1(String plainText, String key) throws Exception {
            return HmacSha1(plainText.getBytes(), key);
        }
    }
    

    上面代码可以直接复制使用,获取签名就是调用appSign这个方法,方法的前四个参数就是之前说的三个值,就不多说了,最后一个参数是时间值,也就是从现在开始,授权多久的时间,单位是秒。获取签名:

      String sign = "";
            try {
                sign = Sign.appSign(APPID, SECRETID, SECRETKEY, "", 2592000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    

    3.请求头和请求体:

            File file = getBitmapFile(mBitmap);
            OkHttpClient okHttpClient = new OkHttpClient();
            RequestBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("image", file.getAbsolutePath(), RequestBody.create(MediaType.parse("image/png"), file))
                    .addFormDataPart("appid", APPID)
                    .build();
            Request request = new Request.Builder()
                    .header("host", "recognition.image.myqcloud.com")
                    .addHeader("authorization", sign)
                    .url("https://recognition.image.myqcloud.com/ocr/handwriting")
                    .post(requestBody)
                    .build();
    

    重点要注意第一个addFormDataPart方法,第一个参数是“image”无需改动,第二个参数是文件的路径,第三个参数是文件的类型,第四个参数就是file本身。其他的设置项都是默认的,不需要修改。
    4.开始post并返回结果:

     okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.d("TAG", "onFailure: " + e.getMessage());
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    JSONObject jsonObject=new JSONObject();
                    jsonObject= JSON.parseObject(response.body().string());
                    Log.i("TAG", "tencent handwrite: " +jsonObject.toString());
                }
            });
    

    返回的结果也是json数据体,需要自己解析。

    两种模式相互比较和与百度比较

    印刷体模式操作比较简单,毕竟已经封装好了,手写体需要自己post数据比较麻烦。从识别率上,这两种方式都差别不大。在我的测试样例中,百度的高精度印刷体模式识别率是最好的,其次到百度的手写体模式,腾讯的两种识别率都不是很好。

    总结

    图片识别目前使用百度的sdk准确率比较高。但如果识别的是印刷体,四种都差不多,腾讯印刷体使用最为简单。但这四种都不是很符合本人项目的需要,因此抛弃了光学字符识别,找了另一种方式识别:联机手写识别技术,该方式适合有笔迹过程记录的文字识别(例如输入法的手写输入),下篇文章记录灵云的HWR的使用。

  • 相关阅读:
    了解什么是版本控制 & 用tortoiseSVN 建立本地版本库来管理自己的代码
    windows下用wampServer 为wordpress 搭建本地服务器运行环境
    使用Windows Live Writer 作为博客园PC客户端发表博客
    重装SQL前,一定要把SQL2005、SQL2008之类的彻底删除干净
    jdk-7u40-windows-i586的安装
    【react】---Immutable的基本使用
    【巷子】---webpack配置非CMD规范的模块
    【巷子】---Mock---基本使用
    【巷子】---fetch---基本使用
    【巷子】---vue基于mint-ui三级联动---【vue】
  • 原文地址:https://www.cnblogs.com/newbyblog/p/10457458.html
Copyright © 2011-2022 走看看