Android開發如何輕鬆實現基於Tesseract的Android OCR應用程序

介紹 此應用程序使用Tesseract 3的Tesseract OCR引擎,該引擎經過識別字符模式( https://github.com/tesseract-ocr/tesseract )來工做。 Tesseract具備unicode(UTF-8)支持,能夠開箱即用識別100多種語言。 背景 我嘗試了Google文本識別API- https://deveandroid

介紹

此應用程序使用Tesseract 3的Tesseract OCR引擎,該引擎經過識別字符模式(https://github.com/tesseract-ocr/tesseract)來工做。Tesseract具備unicode(UTF-8)支持,能夠「開箱即用」識別100多種語言。git

背景

我嘗試了Google文本識別API- https://developers.google.com/vision/android/text-overview,但它不適合我,因此我找到了這個驚人的引擎。github

使用代碼

開始吧!在Android studio中建立一個新項目(我使用的是3.2.1版),或者您能夠下載源文件並選擇:File-New-Import項目。ide

Android開發輕鬆實現基於Tesseract的Android OCR應用程序

添加到build.gradle應用程序級別:函數

implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' implementation 'com.rmtheis:tess-two:9.0.0'

我使用Butterknife庫,它很是有用,主庫是 - ' tess-two:9.0.0'' - 它包含一個Android的Tesseract工具(tesseract-android-tools的分支,它增長了一些額外的功能。此外,咱們須要相機和寫入權限,所以將其添加到AndroidManifest.xml工具

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" />

作一個簡單的佈局文件ButtonTextView而且ImageView佈局

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:fillViewport="true"      tools:context=".MainActivity"> <LinearLayout          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:orientation="vertical"> <LinearLayout              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:orientation="vertical"> <Button                  android:id="@+id/scan_button"                  android:layout_width="wrap_content"                  android:layout_height="wrap_content"                  android:layout_gravity="center"                  android:text="scan" /> </LinearLayout> <LinearLayout              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_margin="4dp"              android:orientation="horizontal"> <TextView                  android:id="@+id/ocr_text"                  android:layout_width="match_parent"                  android:layout_height="wrap_content"                  android:layout_gravity="fill"                  android:text=" text"> </TextView> </LinearLayout> <LinearLayout              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:orientation="vertical"> <ImageViewandroid:id="@+id/ocr_image"android:layout_width="match_parent"android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout> </ScrollView>

咱們獲得這樣的東西:gradle

Android開發輕鬆實現基於Tesseract的Android OCR應用程序

編寫一些代碼來檢查權限:ui

void checkPermissions() {
    if (!hasPermissions(context, PERMISSIONS)) { requestPermissions(PERMISSIONS, PERMISSION_ALL); flagPermissions = false; } flagPermissions = true; } public static boolean hasPermissions(Context context, String... permissions) { if (context != null && permissions != null) { for (String permission : permissions) { if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } } return true; }

和代碼來建立一個文件:this

public File createImageFile() throws IOException { // Create an image file name String timeStamp = new SimpleDateFormat("MMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = image.getAbsolutePath(); return image; }

首先,咱們須要寫onClickScanButton函數,它:

@OnClick(R.id.scan_button)
void onClickScanButton() { // check permissions if (!flagPermissions) { checkPermissions(); return; } //prepare intent Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) { File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { Toast.makeText(context, errorFileCreate, Toast.LENGTH_SHORT).show(); Log.i("File error", ex.toString()); } // Continue only if the File was successfully created if (photoFile != null) { oldPhotoURI = photoURI1; photoURI1 = Uri.fromFile(photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI1); startActivityForResult(takePictureIntent, REQUEST_IMAGE1_CAPTURE); } } }

咱們能夠在這裏查看結果:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_IMAGE1_CAPTURE: { if (resultCode == RESULT_OK) { Bitmap bmp = null; try { InputStream is = context.getContentResolver().openInputStream(photoURI1); BitmapFactory.Options options = new BitmapFactory.Options(); bmp = BitmapFactory.decodeStream(is, null, options); } catch (Exception ex) { Log.i(getClass().getSimpleName(), ex.getMessage()); Toast.makeText(context, errorConvert, Toast.LENGTH_SHORT).show(); } firstImage.setImageBitmap(bmp); doOCR(bmp); OutputStream os; try { os = new FileOutputStream(photoURI1.getPath()); if (bmp != null) { bmp.compress(Bitmap.CompressFormat.JPEG, 100, os); } os.flush(); os.close(); } catch (Exception ex) { Log.e(getClass().getSimpleName(), ex.getMessage()); Toast.makeText(context, errorFileCreate, Toast.LENGTH_SHORT).show(); } } else { { photoURI1 = oldPhotoURI; firstImage.setImageURI(photoURI1); } } } } }

接下來將Tesseract集成到咱們的項目中,進行額外的課程:TesseractOCR

Assets文件夾中爲英語語言添加了訓練有素的數據文件「 eng.traineddata 」 ,所以咱們須要將其從APK複製到內部存儲器文件目錄,而後啓動Tesseract系統:mTess.init(dstInitPathDir, language)

public class TesseractOCR { private final TessBaseAPI mTess; public TesseractOCR(Context context, String language) { mTess = new TessBaseAPI(); boolean fileExistFlag = false; AssetManager assetManager = context.getAssets(); String dstPathDir = "/tesseract/tessdata/"; String srcFile = "eng.traineddata"; InputStream inFile = null; dstPathDir = context.getFilesDir() + dstPathDir; String dstInitPathDir = context.getFilesDir() + "/tesseract"; String dstPathFile = dstPathDir + srcFile; FileOutputStream outFile = null; try { inFile = assetManager.open(srcFile); File f = new File(dstPathDir); if (!f.exists()) { if (!f.mkdirs()) { Toast.makeText(context, srcFile + " can't be created.", Toast.LENGTH_SHORT).show(); } outFile = new FileOutputStream(new File(dstPathFile)); } else { fileExistFlag = true; } } catch (Exception ex) { Log.e(TAG, ex.getMessage()); } finally { if (fileExistFlag) { try { if (inFile != null) inFile.close(); mTess.init(dstInitPathDir, language); return; } catch (Exception ex) { Log.e(TAG, ex.getMessage()); } } if (inFile != null && outFile != null) { try { //copy file byte[] buf = new byte[1024]; int len; while ((len = inFile.read(buf)) != -1) { outFile.write(buf, 0, len); } inFile.close(); outFile.close(); mTess.init(dstInitPathDir, language); } catch (Exception ex) { Log.e(TAG, ex.getMessage()); } } else { Toast.makeText(context, srcFile + " can't be read.", Toast.LENGTH_SHORT).show(); } } } public String getOCRResult(Bitmap bitmap) { mTess.setImage(bitmap); return mTess.getUTF8Text(); } public void onDestroy() { if (mTess != null) mTess.end(); } }

OCR代碼很簡單 - 咱們須要將圖像(位圖BMP)傳遞給該對象並得到結果:

public String getOCRResult(Bitmap bitmap) { mTess.setImage(bitmap); return mTess.getUTF8Text(); }

OCR可能須要很長時間,所以咱們須要在另外一箇中進行Thread

private void doOCR(final Bitmap bitmap) { if (mProgressDialog == null) { mProgressDialog = ProgressDialog.show(this, "Processing", "Doing OCR...", true); } else { mProgressDialog.show(); } new Thread(new Runnable() { public void run() { final String srcText = mTessOCR.getOCRResult(bitmap); runOnUiThread(new Runnable() { @Override public void run() { if (srcText != null && !srcText.equals("")) { ocrText.setText(srcText); } mProgressDialog.dismiss(); } }); } }).start(); }

源圖像以下:

Android開發輕鬆實現基於Tesseract的Android OCR應用程序

OCR的結果以下:

Android開發輕鬆實現基於Tesseract的Android OCR應用程序

相關文章
相關標籤/搜索