標籤:
最近因為工作的原因,好久沒有寫部落格了。(看到有很多評論和留言,都不能一一回複啦~)
過年之前Oracle組織過一次內部的編程馬拉松,當時選擇的題目是OCR相關的,但是但是做出來的效果不是很好,就一直想著把代碼重新整理一下,最佳化一下效果。
目前隨著國內互連網火的一塌糊塗,似乎也帶動了影像處理的發展與引用,以前一直覺得影像處理很難找到合適的工作,所以找工作的時候就換了自然語言處理,然後現在發現互連網招聘影像處理工程師也很多。。。
廢話不多說,來看OCR on Android .
作OCR的話,需要使用一些已有的sdk, 例如tesseract,這個是Google的一個開源項目貌似國內訪問這個比較費勁。
tesseract是C語言開發的,如果想要使用的Android平台上,需要通過Android平台的JNI調用機制,有興趣的朋友可以參考:http://blog.csdn.net/watkinsong/article/details/9849973
對於大部分朋友來說,完全不需要直接操作底層的c語言,畢竟通過JNI調用非常難調試。 為了便於使用tesseract,github上有個叫tess-two的項目,把tesseract的底層API封裝為Android平台可以直接使用的java API, 這樣直接引用這個項目就可以直接進行OCR開發了。
如果不想看下面的羅嗦,直接下載我的Demo項目,直接看代碼就可以了,: https://github.com/weixsong/libra, 注意,這是一個項目的集合,找到OCRDemo檔案夾就是相應的項目。
第一步: 到 https://github.com/weixsong/tess-two 下載最新的tess-two項目,通過eclipse匯入該羨慕
第二部:建立你自己的OCR項目,然後引用tess-two項目,這樣就可以使用tess-two項目提供的API以及.so檔案了。
第三步:到https://code.google.com/p/tesseract-ocr/, 下載你需要的對應的語言的已經訓練好的訓練資料(至於這個資料是模板,還是個神經網路,還是分類器。。。我不知道), 然後把訓練資料放入Android 項目的 asset檔案目錄中,
需要注意的是,在寫Android程式時,需要把訓練好的分類檔案拷貝到Android儲存中:
private void checkAndCopyFiles() {String[] paths = new String[] { DATA_PATH, DATA_PATH_TESSDATA };for (String path : paths) {File dir = new File(path);if (!dir.exists()) {if (!dir.mkdirs()) {Log.v(TAG, "ERROR: Creation of directory " + path+ " on sdcard failed");return;} else {Log.v(TAG, "Created directory " + path + " on sdcard");}}}for (String lang : langs) {String traineddata_path = DATA_PATH_TESSDATA + lang+ ".traineddata";String asset_tessdata = "tessdata/" + lang + ".traineddata";if (!(new File(traineddata_path)).exists()) {try {AssetManager assetManager = getAssets();InputStream in = assetManager.open(asset_tessdata);OutputStream os = new FileOutputStream(traineddata_path);// Transfer bytes from in to outbyte[] buf = new byte[1024];int len;while ((len = in.read(buf)) > 0) {os.write(buf, 0, len);}in.close();os.close();Log.v(TAG, "Copied " + lang + " traineddata");} catch (IOException e) {Log.e(TAG,"unable to copy " + lang + " traineddata "+ e.toString());}}}}
第四步:就可以使用tess-two進行OCR識別了,當然,你需要提供一張照片。。。
package com.example.homework;import android.graphics.Bitmap;import android.util.Log;import com.googlecode.tesseract.android.TessBaseAPI;public class TesstwoOCR {private static final String TAG = "TesstwoOCR";private TessBaseAPI ocr_eng;private TessBaseAPI ocr_chi;public TesstwoOCR() {Log.v(TAG, "BaseApi initializing...");ocr_eng = new TessBaseAPI();ocr_eng.setDebug(true);ocr_eng.init(MainActivity.DATA_PATH, MainActivity.LANG_EN);ocr_chi = new TessBaseAPI();ocr_chi.setDebug(true);ocr_chi.init(MainActivity.DATA_PATH, MainActivity.LANG_ZH);}public String doOCR(Bitmap bitmap, String lang) {String result = "";if (lang.equals(MainActivity.LANG_EN)) {ocr_eng.setImage(bitmap);result = ocr_eng.getUTF8Text();} else if (lang.equals(MainActivity.LANG_ZH)) {ocr_chi.setImage(bitmap);result = ocr_chi.getUTF8Text();} else {//nothing}return result.trim();}}
上面的代碼我分別使用了中文和英文的OCR識別,因為再我的Demo中可以進行中英文識別的切換。
因為這裡給出了Demo的原始碼, 所以整個流程說明的比較簡單。大家還是盡量參考Demo代碼進行對應的OCR識別的開發。 Demo :https://github.com/weixsong/libra, 在原始碼中,也有詳細的如何使用該項目的說明。
下面是OCR識別的效果, 總體來說,目前的效果還是相當不錯的:
Android OCR demo