經過兩個星期的試錯,終於成功的在android平台上識別出圖片。
我的完整代碼可以從 這兒 下載。這是一個完整工程。若要使用,請詳細查看下面的說明。
代碼講解:
我使用的是 黑暗伯爵 已經編譯好tess-two.zip,里面有已經編譯好的so文件(linux下的類似於dll文件的動態庫)和jar文件。
使用方法:
1.解壓
2.將googlecode文件夾(從其他地方下載)拷貝到自己工程里的com文件夾內
3.將里面的libs文件夾拷貝到工程根目錄下
4.將tess-two.tesseract3.01-leptonica1.68-LibJPEG6b.jar包也直接拷貝到工程的libs里面,然后再導入這個jar
然后,我的測試代碼是從 這個博客 上拷貝的。不過我修改了幾點,否則會報錯。下面是改正過后的代碼,如果不對,估計您還要自己再改改。
public class SliderTessActivity extends Activity { private static final String TAG = "MainActivity ..."; private static final String TESSBASE_PATH = "/mnt/sdcard/tesseract/"; private static final String DEFAULT_LANGUAGE = "eng"; private static final String IMAGE_PATH = "/mnt/sdcard/ocr.jpg"; private static final String EXPECTED_FILE = TESSBASE_PATH + "tessdata/" + DEFAULT_LANGUAGE + ".traineddata"; private TessBaseAPI service; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); testOcr(); } public void testOcr(){ mHandler.post(new Runnable() { @Override public void run() { Log.d(TAG, "begin>>>>>>>"); ocr(); //test(); } }); } public void test(){ // First, make sure the eng.traineddata file exists. /*assertTrue("Make sure that you've copied " + DEFAULT_LANGUAGE + ".traineddata to " + EXPECTED_FILE, new File(EXPECTED_FILE).exists());*/ final TessBaseAPI baseApi = new TessBaseAPI(); baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE); final Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); //digits is a .jpg image I found in one of the issues here. ImageView img = (ImageView) findViewById(R.id.image); img.setImageBitmap(bmp);//I can see the ImageView. So we know that it should work if I sent it to the setImage() baseApi.setImage(bmp); Log.v("Kishore","Kishore:Working");//This statement is never reached. Futhermore, on putting some more Log.v commands in the setImage function, I found out that the native function nativeSetImagePix is never accessed. I have attached the Logcat output below to show that it is not accessed. String outputText = baseApi.getUTF8Text(); Log.v("Kishore","Kishore:"+outputText); baseApi.end(); bmp.recycle(); } protected void ocr() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bitmap = BitmapFactory.decodeFile(IMAGE_PATH, options); Log.d("nimei", "---in ocr() before try--"); try { Log.v(TAG, "not in the exception"); ExifInterface exif = new ExifInterface(IMAGE_PATH); int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); Log.v(TAG, "Orient: " + exifOrientation); int rotate = 0; switch (exifOrientation) { case ExifInterface.ORIENTATION_ROTATE_90: rotate = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: rotate = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: rotate = 270; break; } Log.v(TAG, "Rotation: " + rotate); // if (rotate != 0) { //這兒必須要注釋掉,否則會報錯 什么 ARGB_8888之類的 // Getting width & height of the given image. int w = bitmap.getWidth(); int h = bitmap.getHeight(); // Setting pre rotate Matrix mtx = new Matrix(); mtx.preRotate(rotate); // Rotating Bitmap bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false); // tesseract req. ARGB_8888 bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); // } //這兒必須要注釋掉,否則會報錯 什么 ARGB_8888之類的 } catch (IOException e) { Log.e(TAG, "Rotate or coversion failed: " + e.toString()); Log.v(TAG, "in the exception"); } ImageView iv = (ImageView) findViewById(R.id.image); iv.setImageBitmap(bitmap); iv.setVisibility(View.VISIBLE); Log.v(TAG, "Before baseApi"); TessBaseAPI baseApi = new TessBaseAPI(); baseApi.setDebug(true); baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE); baseApi.setImage(bitmap); String recognizedText = baseApi.getUTF8Text(); baseApi.end(); Log.v(TAG, "OCR Result: " + recognizedText); // clean up and show if (DEFAULT_LANGUAGE.equalsIgnoreCase("eng")) { recognizedText = recognizedText.replaceAll("[^a-zA-Z0-9]+", " "); } if (recognizedText.length() != 0) { ((TextView) findViewById(R.id.field)).setText(recognizedText.trim()); } } private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { }; }; }
說明:
代碼工作前提:
1.新建HelloWorld項目,打開helloworldActivity.java,全選,將我們的代碼全部復制進去,保存。
2.import之類的錯誤,自己按照MyEclipse的提示自己加。(鼠標放在出錯的位置懸停足夠時間,出現彈出框后選擇 “import”,如果兩個import盡量選android開頭的)
3.與代碼配套的main.xml文件也要修改一下
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/field" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </LinearLayout>
4./mnt/sdcard/tesseract/tessdata目錄下要有xxx.traineddata文件,代碼中是 eng.traineddata(識別英文)。這個文件我會提供下載,您要把這個文件拷貝到模擬器的SD卡中。(window -> show view -> other -> File Explorer然后可以直接拖拽:選中tessdata文件夾將文件eng.traineddata拖進tessdata文件夾)
5./mnt/sdcard/ocr.jpg其中ocr.jpg是要測試的圖片,復雜的沒試過,只試過自己用畫圖直接寫的幾個單詞,可以正確識別。
6.代碼中有很多我加上的調試代碼,我沒有去掉,方便大家定位錯誤信息。(查看方式:Window-show view-other-Logcat)
遇到的錯誤:
當我從項目外部導入jar時,運行總是出現“Conversion to Dalvik format failed with error 1”的錯誤
后來,將那個jar包索性直接拷貝到了libs目錄下,然后在Buile Path中刪掉了那個引入的jar包,哎,反而沒錯了,真不知道為什么。
另外注明我的系統環境:
PC :windows7
IDE:MyEclispe 8.6
android SDK: 2.2
jdk :1.6
還有什么大家可以問哈。
其他的我暫時也相不出什么了,希望大家都能調試通過!
參考:
黑暗伯爵的 tess-two.zip http://www.cnblogs.com/hangxin1940/archive/2012/01/13/2321507.html
slider 的 測試代碼 http://www.cnblogs.com/slider/archive/2012/03/21/2409888.html#commentform
另外,還有國外的鏈接。多半是講解如何從官網上git包,然后又怎樣在linux的android環境下用ndk怎樣編譯,編譯好又如何設置Is Library,總之比較繁瑣,但也體現出專心和細致。
注:自己重新編譯比較復雜,必須要在linux環境下,並且要是用ndk,ant等工具。我一一安裝后,又由於對ndk的最新版本不支持原因無法編譯正確(可以編譯但是不可用)。如果時間充分,可以研究,時間不多,建議使用 黑暗伯爵 的 tess-two.zip(我成功識別圖片)
http://wolfpaulus.com/journal/android-journal/android-and-ocr
http://gaut.am/making-an-ocr-android-app-using-tesseract/
http://www.harshadura.net/2011/12/making-simple-ocr-android-app-using.html
http://rmtheis.wordpress.com/2011/08/06/using-tesseract-tools-for-android-to-create-a-basic-ocr-app/
后記:
這里只是識別圖片,我是要做一個拍照取詞的詞典,所以還有很多事情要做。
補:
沒想到一年之后的畢業設計也要做一個相關的課題:利用數字圖像和模式識別來識別車牌號,這次估計要嘗試去理解算法了。我還是很想在圖像識別領域做些事情的,希望大家一起進步!
補(編輯時間:2013.01.30):
最近看到一個JAVA語言利用開源OCR引擎Tesseract 3.0識別中文的博客文章,看效果圖發現代碼效果相當的優秀。當然也很容易發現它是識別的圖片,並且因該博主沒有隱藏文章中的換行符號導致頻繁出現換行后冒出一個誤識別的錯字。下面是該博客鏈接:
http://blog.csdn.net/zhoushuyan/article/details/5948289#1567946