Android OCR之tesseract

實現小猿搜題、做業幫相似效果。
基於Google Tesseract-OCR實現,因爲這是基於C++開發,Android中不能直接使用,因此本項目使用tess-two是對於Android的分支。java

準備工做

1)Android Studio導入gradle依賴(懶人作法)

//編譯好的SO庫 和 jar包
compile 'com.rmtheis:tess-two:6.1.1'
//圖像裁剪
compile 'com.edmodo:cropper:1.0.1'複製代碼

其實也能夠本身下載github.com/rmtheis/tes…源碼在Linux環境中進行編譯。linux

2)第二種方法 本身編譯源碼(!!!)

  • 安裝虛擬機VMware
  • 安裝linux系統Ubuntu
  • 安裝必要工具
sudo apt-get update
sudo apt-get install git複製代碼
  • 配置JDK、NDK、SDK環境(踩了一萬個坑)
  • 下載tess-two代碼
git clone https://github.com/rmtheis/tess-two.git tess複製代碼
  • 開始編譯
cd /tess/tess-two/jni

ndk-build複製代碼
  • 使用
    將編譯好的tess-two目錄複製到本身項目的libraries下,將項目下的app關聯 libraries。

tess-two使用

  • 數據字典下載,在app/main目錄下新建assets目錄,從github.com/tesseract-o…下載對應語言的字典庫。git

  • MainActivity.java
    主要就是將assets中的字典文件寫到手機文件目錄github

/** * 將assets中的文件複製出 * * @param path */
public void deepFile(String path) {
    String newPath = getExternalFilesDir(null) + "/";
    try {
        String str[] = getAssets().list(path);
        if (str.length > 0) {//若是是目錄
            File file = new File(newPath + path);
            file.mkdirs();
            for (String string : str) {
                path = path + "/" + string;
                deepFile(path);
                path = path.substring(0, path.lastIndexOf('/'));//回到原來的path
            }
        } else {//若是是文件
            InputStream is = getAssets().open(path);
            FileOutputStream fos = new FileOutputStream(new File(newPath + path));
            byte[] buffer = new byte[1024];
            int count = 0;
            while (true) {
                count++;
                int len = is.read(buffer);
                if (len == -1) {
                    break;
                }
                fos.write(buffer, 0, len);
            }
            is.close();
            fos.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}複製代碼

點擊跳轉到拍照界面canvas

public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_camera:
                Intent intent = new Intent(this, TakePhoteActivity.class);
                startActivity(intent);
                break;
        }
    }複製代碼

  • TakePhoteActivity.java
    主要執行拍照、裁剪操做。

如下是拍照成功後回掉接口,拍照成功後顯示剪裁界面app

/** * 拍照成功後回調 * 存儲圖片並顯示截圖界面 * * @param data */
    @Override
    public void onCameraStopped(byte[] data) {
        Log.i("TAG", "==onCameraStopped==");
        // 建立圖像
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        // 系統時間
        long dateTaken = System.currentTimeMillis();
        // 圖像名稱
        String filename = DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString() + ".jpg";
        // 存儲圖像(PATH目錄)
        Uri source = insertImage(getContentResolver(), filename, dateTaken, PATH, filename, bitmap, data);
        //準備截圖
        try {
            mCropImageView.setImageBitmap(MediaStore.Images.Media.getBitmap(this.getContentResolver(), source));
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
        showCropperLayout();
    }複製代碼

剪裁操做,完成後跳轉到識別界面ide

private View.OnClickListener cropcper = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn_closecropper:
                    showTakePhotoLayout();
                    break;
                case R.id.btn_startcropper:
                    //獲取截圖並旋轉90度
                    Bitmap cropperBitmap = mCropImageView.getCroppedImage();
                    Bitmap bitmap = Utils.rotate(cropperBitmap, -90);

                    // 系統時間
                    long dateTaken = System.currentTimeMillis();
                    // 圖像名稱
                    String filename = DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString() + ".jpg";
                    Uri uri = insertImage(getContentResolver(), filename, dateTaken, PATH, filename, bitmap, null);

                    Intent intent = new Intent(TakePhoteActivity.this, ShowCropperedActivity.class);
                    intent.setData(uri);
                    intent.putExtra("path", PATH + filename);
                    intent.putExtra("width", bitmap.getWidth());
                    intent.putExtra("height", bitmap.getHeight());
// intent.putExtra("cropperImage", bitmap);
                    startActivity(intent);
                    bitmap.recycle();
                    finish();
                    break;
            }
        }
    };複製代碼
  • ShowCropperedActivity.java
    主要是識別操做

初始化識別器工具

//sd卡路徑
private static String LANGUAGE_PATH = "";
//識別語言
private static final String LANGUAGE = "chi_sim";//chi_sim | eng
private TessBaseAPI baseApi = new TessBaseAPI();

@Override
protected void onCreate(Bundle savedInstanceState) {
    LANGUAGE_PATH = getExternalFilesDir("") + "/";

    baseApi.init(LANGUAGE_PATH, LANGUAGE);
    //設置設別模式
    baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO);
}複製代碼

將圖片灰度化處理,去除雜色能夠提升準確度gradle

/** * 灰度化處理 * * @param bitmap3 * @return */
public Bitmap convertGray(Bitmap bitmap3) {
    colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(0);
    ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);

    Paint paint = new Paint();
    paint.setColorFilter(filter);
    Bitmap result = Bitmap.createBitmap(bitmap3.getWidth(), bitmap3.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(result);

    canvas.drawBitmap(bitmap3, 0, 0, paint);
    return result;
}複製代碼

開始識別ui

//傳入圖片
baseApi.setImage(bitmap);
//獲取識別後的結果
String result = baseApi.getUTF8Text();
//結束識別
baseApi.end();複製代碼

結果

Demo已上傳Github如須要可下載github.com/wangtaoT/An…

相關文章
相關標籤/搜索