在Android中呼叫百度的OCR介面
前言
最近實驗室開了個新專案,是一個通過掃描單詞後把掃描過的單詞生成遊戲來讓小朋友記單詞的APP,掃描單詞這個功能需要用到OCR.
現在常用的OCR有
-
Tesseract 這個用的人比較多,而且開源,目前google正在維護,但是我嘗試了一下,發現識別準確率不是特別理想。
-
微軟的Azure上的認知服務 識別率很高,但是收費,現在有1元體驗的套餐,而且不需要驗證信用卡,感興趣的同學可以試試。
-
百度的文字識別 之所以用這個是因為免費,不過有每天的限制次數,對於學生專案來說夠用,還要什麼自行車。
下面進入正文
如何在Android 中呼叫百度的OCR進行文字識別
1.獲取百度文字識別產品服務的 Ak/Sk
1.在百度AI開放平臺中進入控制檯
2.找到文字識別 產品服務
3,建立應用
4,填寫資訊,注意這裡的包名一定要和專案的包名一致
5.獲得AK/SK
6.下載license檔案,在專案中如果直接用AK/SK明文呼叫百度的OCR,很不安全,可能會被別人反編譯之後獲得你的AK.SK
license檔案集成了AK/SK 放在專案中可以防止別人破解。
7.下載之後將獲得的api.license檔案放入main目錄下的assets目錄中
2.新增百度OCR的SDK到專案中
1.下載 百度OCR的android Sdk
2.下載的SDK壓縮包將其解壓,並將libs下的ocr-sdk的jar包放入專案的libs目錄下
3.在main目錄下新建jniLibs目錄,並將libs資料夾中的其他檔案放入其中
4.在app下的build,gradle中新增
將新增在libs下的sdk JAR包編譯
5.這裡下載的壓縮包中包括了百度提供的相機掃描時的UI,在拍完照有裁剪框,比較方便,這裡我們可以作為module引入專案中
3.呼叫百度OCR
做完準備工作我們就可以開始呼叫百度的OCR介面了。
首先在我們需要進行識別的頁面所在的檔案中建立 根據License檔案初始化OCR例項的函式,並在onCreate()方法中呼叫
/**
* 自定義license的檔案路徑和檔名稱,以license檔案方式初始化
*/
private void initAccessTokenLicenseFile() {
OCR.getInstance(mActivity.getApplicationContext()).initAccessToken(new OnResultListener<AccessToken>() {
@Override
public void onResult(AccessToken accessToken) {
String token = accessToken.getAccessToken();
Log.d(TAG,token);
hasGotToken = true;
}
@Override
public void onError(OCRError error) {
error.printStackTrace();
alertText("自定義檔案路徑licence方式獲取token失敗", error.getMessage());
}
}, "aip.license", mActivity.getApplicationContext());
}
定義我們的開啟相機事件
/**
* 開啟相機,進入的相機頁面是借用百度OCR 官方DEMO中的相機頁面
* 能夠在相機中裁剪圖片,和進入相簿
* @author cyd
*/
private void openCameraForResult() {
if (!checkTokenStatus()) {
return;
}
Intent intent = new Intent(mActivity, CameraActivity.class);
intent.putExtra(CameraActivity.KEY_OUTPUT_FILE_PATH,
FileUtil.getSaveFile(getActivity()).getAbsolutePath());
intent.putExtra(CameraActivity.KEY_CONTENT_TYPE,
CameraActivity.CONTENT_TYPE_GENERAL);
startActivityForResult(intent, REQUEST_CODE_GENERAL_BASIC);
}
這裡的CameraActivity用的是引入OCR_UI中的相機活動,自帶剪裁框
接下來需要我們新建一個可以存放OCR的識別方法的類RecognizeService
**
* 這個類是用於將拍攝或者相簿中獲得的圖片進行識別,返回JSON格式的字串。
*/
public class RecognizeService {
public interface ServiceListener {
public void onResult(String result);
}
//高精度版
public static void recAccurateBasic(Context ctx, String filePath, final ServiceListener listener) {
GeneralParams param = new GeneralParams();
param.setDetectDirection(true);
param.setVertexesLocation(true);
param.setLanguageType(GeneralBasicParams.ENGLISH);
param.setRecognizeGranularity(GeneralParams.GRANULARITY_SMALL);
param.setImageFile(new File(filePath));
//這裡的recognizeAccurateBasic方法為百度OCR識別的核心方法
OCR.getInstance(ctx).recognizeAccurateBasic(param, new OnResultListener<GeneralResult>() {
@Override
public void onResult(GeneralResult result) {
StringBuilder sb = new StringBuilder();
for (WordSimple wordSimple : result.getWordList()) {
WordSimple word = wordSimple;
sb.append(word.getWords());
sb.append("\n");
}
listener.onResult(result.getJsonRes());
}
@Override
public void onError(OCRError error) {
listener.onResult(error.getMessage());
}
});
}
}
在onActivityResult方法中,我們呼叫剛剛新建的類的recAccurateBasic方法,此方法接收三個引數,分別是context,拍照獲取的圖片路徑,和在RecognizeService類中定義的監聽介面,這裡的獲取圖片路徑方法,我用的是百度官方DEMO中的方法
在onResult方法中,返回的result字串即為識別結果的json字串,只需要對JSON解析一下就能得到識別結果啦
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_GENERAL_BASIC:
if (resultCode == Activity.RESULT_OK) {
RecognizeService.recAccurateBasic(mActivity, FileUtil.getSaveFile(mActivity.getApplicationContext()).getAbsolutePath(),
new RecognizeService.ServiceListener() {
@Override
public void onResult(String result) {
Bundle bundle = new Bundle();
bundle.putString("wordResultJson",result );
Intent intent = new Intent(mActivity,SelectWordsActivity.class);
intent.putExtra("wordResultBundle",bundle );
startActivity(intent);
}
});
}
break;
default:
Log.d(TAG, "onActivityResult: "+"run in default");
break;
}
}
FileUtil類
public class FileUtil {
public static File getSaveFile(Context context) {
File file = new File(context.getFilesDir(), "pic.jpg");
return file;
}
}