騰訊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的使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM