文字识别一般都用的tesseract-ocr。
GitHub:https://github.com/tesseract-ocr/tesseract
而Android对应的比较推荐的有个tess-two。
GitHub:https://github.com/rmtheis/tess-two

Demo的github地址:https://github.com/wangyisll/TessTwoDemo

先看效果图

我主要是识别截图,所以图片比较规范,识别率应该很高。

![Screenshot_2017-03-17-16-53-25-879_com.sunlinlin..png](http://upload-images.jianshu.io/upload_images/2062943-5e205d16418fb691.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

简介什么都不说了,直接看简单的用法吧


首先肯定是引入依赖了

dependencies {    compile 'com.rmtheis:tess-two:6.2.0'}

简单的用法其实就几行代码:

TessBaseAPI tessBaseAPI = new TessBaseAPI();tessBaseAPI.init(DATAPATH, DEFAULT_LANGUAGE);//参数后面有说明。tessBaseAPI.setImage(bitmap);String text = tessBaseAPI.getUTF8Text();

就这样简单的把一个bitmap设置进去,就能识别到里面的文字并输出了。
但是真正用的时候还是遇到了点麻烦,虽然只是简单的识别。
主要是tessBaseAPI.init(DATAPATH, DEFAULT_LANGUAGE)这个方法容易出错。
先看一下这个方法的源码吧:

public boolean init(String datapath, String language) {        return init(datapath, language, OEM_DEFAULT);    }/**     * Initializes the Tesseract engine with the specified language model(s). Returns     * true on success.     *     * @see #init(String, String)     *     * @param datapath the parent directory of tessdata ending in a forward     *            slash     * @param language an ISO 639-3 string representing the language(s)     * @param ocrEngineMode the OCR engine mode to be set     * @return true on success     */    public boolean init(String datapath, String language, int ocrEngineMode) {        if (datapath == null)            throw new IllegalArgumentException("Data path must not be null!");        if (!datapath.endsWith(File.separator))            datapath += File.separator;        File datapathFile = new File(datapath);        if (!datapathFile.exists())            throw new IllegalArgumentException("Data path does not exist!");        File tessdata = new File(datapath + "tessdata");        if (!tessdata.exists() || !tessdata.isDirectory())            throw new IllegalArgumentException("Data path must contain subfolder tessdata!");        //noinspection deprecation        if (ocrEngineMode != OEM_CUBE_ONLY) {            for (String languageCode : language.split("\\+")) {                if (!languageCode.startsWith("~")) {                    File datafile = new File(tessdata + File.separator +                             languageCode + ".traineddata");                    if (!datafile.exists())                        throw new IllegalArgumentException("Data file not found at " + datafile);                }            }        }        boolean success = nativeInitOem(mNativeData, datapath, language, ocrEngineMode);        if (success) {            mRecycled = false;        }        return success;    }

注意

从下面的方法中抛出的几个异常可以看出来,初始化的时候,第一个参数是个文件夹,而且这个文件夹中必须有一个tessdata的文件夹;而且这个文件夹中要有个文件叫做 第二个参数.traineddata 。具体的可以看下面代码里的注释。这些文件夹和文件没有的一定要创建好,不然会报错。

第二个参数.traineddata 是个什么文件呢?
这个是识别用到的语言库还是文字库什么的,按那个初始化方法的意思是哟啊放到SD卡中的。可以在下面的地址下载。我的demo里把这个文件放在了assets中,启动的时候复制到内存卡里。
https://github.com/tesseract-ocr/tessdata

chi_sim.traineddata应该是健体中文吧,我用的是这个。中英文都能识别。

代码

下面是主要代码:

import android.Manifest;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Build;import android.os.Bundle;import android.os.Environment;import android.support.annotation.NonNull;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import com.googlecode.tesseract.android.TessBaseAPI;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    private Button btn;    private TextView tv;    /**     * TessBaseAPI初始化用到的第一个参数,是个目录。     */    private static final String DATAPATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;    /**     * 在DATAPATH中新建这个目录,TessBaseAPI初始化要求必须有这个目录。     */    private static final String tessdata = DATAPATH + File.separator + "tessdata";    /**     * TessBaseAPI初始化测第二个参数,就是识别库的名字不要后缀名。     */    private static final String DEFAULT_LANGUAGE = "chi_sim";    /**     * assets中的文件名     */    private static final String DEFAULT_LANGUAGE_NAME = DEFAULT_LANGUAGE + ".traineddata";    /**     * 保存到SD卡中的完整文件名     */    private static final String LANGUAGE_PATH = tessdata + File.separator + DEFAULT_LANGUAGE_NAME;    /**     * 权限请求值     */    private static final int PERMISSION_REQUEST_CODE=0;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn = (Button) findViewById(R.id.btn);        tv = (TextView) findViewById(R.id.tv);        if (Build.VERSION.SDK_INT >= 23) {            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||                    checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);            }        }        //Android6.0之前安装时就能复制,6.0之后要先请求权限,所以6.0以上的这个方法无用。        copyToSD(LANGUAGE_PATH, DEFAULT_LANGUAGE_NAME);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                new Thread(new Runnable() {                    @Override                    public void run() {                        Log.i(TAG, "run: kaishi " + System.currentTimeMillis());                        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.quanbu);                        Log.i(TAG, "run: bitmap " + System.currentTimeMillis());                        TessBaseAPI tessBaseAPI = new TessBaseAPI();                        tessBaseAPI.init(DATAPATH, DEFAULT_LANGUAGE);                        tessBaseAPI.setImage(bitmap);                        final String text = tessBaseAPI.getUTF8Text();                        Log.i(TAG, "run: text " + System.currentTimeMillis() + text);                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                tv.setText(text);                            }                        });                        tessBaseAPI.end();                    }                }).start();            }        });    }    /**     * 将assets中的识别库复制到SD卡中     * @param path  要存放在SD卡中的 完整的文件名。这里是"/storage/emulated/0//tessdata/chi_sim.traineddata"     * @param name  assets中的文件名 这里是 "chi_sim.traineddata"     */    public void copyToSD(String path, String name) {        Log.i(TAG, "copyToSD: "+path);        Log.i(TAG, "copyToSD: "+name);        //如果存在就删掉        File f = new File(path);        if (f.exists()){            f.delete();        }        if (!f.exists()){            File p = new File(f.getParent());            if (!p.exists()){                p.mkdirs();            }            try {                f.createNewFile();            } catch (IOException e) {                e.printStackTrace();            }        }        InputStream is=null;        OutputStream os=null;        try {            is = this.getAssets().open(name);            File file = new File(path);            os = new FileOutputStream(file);            byte[] bytes = new byte[2048];            int len = 0;            while ((len = is.read(bytes)) != -1) {                os.write(bytes, 0, len);            }            os.flush();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (is != null)                    is.close();                if (os != null)                    os.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 请求到权限后在这里复制识别库     * @param requestCode     * @param permissions     * @param grantResults     */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {            Log.i(TAG, "onRequestPermissionsResult: "+grantResults[0]);        switch (requestCode){            case PERMISSION_REQUEST_CODE:                if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){                    Log.i(TAG, "onRequestPermissionsResult: copy");                    copyToSD(LANGUAGE_PATH, DEFAULT_LANGUAGE_NAME);                }                break;            default:                break;        }    }}

demo下载地址

http://download.csdn.net/detail/qq_25806863/9783651

更多相关文章

  1. android 动态改变控件位置和大小
  2. Android(安卓)OpenCV java.lang.UnsatisfiedLinkError n_mat
  3. Android——FragmentTabHost-快速实现底部导航模式的解决方案
  4. 1. Android启动过程
  5. 【COCOS2DX-ANDROID-游戏开发之二三】 界面中嵌入Android的WebVi
  6. Android菜单定制总结
  7. 获取Android设备屏幕的相关参数
  8. Flutter 基础(二)基本组件ListView
  9. Android-NDK开发之基础--Android(安卓)JNI实例代码(四)-- JNI中

随机推荐

  1. Android(安卓)UI 学习 自定义的布局 平滑
  2. Error while executing process D:\Andr
  3. Android获取手机应用程序包的信息
  4. android 基本概念和一些术语
  5. Android中改变一个图片的透明度
  6. 2011.09.26(2)——— android sample之Note
  7. android HTTP 登陆链接Mysql数据库实现登
  8. Didn't find class "androidx.core.conte
  9. 阅读《Android 从入门到精通》(2)——熟悉
  10. Android使用MQTT协议