Android中使用orc實(shí)現(xiàn)文字識別實(shí)例
一、什么是orc?
引用百度百科的介紹,指利用光學(xué)字符識別(ORC全稱:Optical Character Recognition)技術(shù),將圖片、照片上的文字內(nèi)容,直接轉(zhuǎn)換為可編輯文本,支持JPG、PNG、GIF、BMP、DOC等圖片格式。簡單一句話,就是可以把圖片上的文字識別出來。應(yīng)用的場景有很多,比如說:身份證號碼識別,銀行卡號識別等等。
二、效果展示
這里筆者實(shí)現(xiàn)的僅僅是一個(gè)效果,實(shí)際使用可能需要對它進(jìn)行訓(xùn)練以提高識別率,第一次做gif圖片,效果不是很好
三、開始集成
Github上面已經(jīng)提供了android端的工具api,Github地址:https://github.com/rmtheis/tess-two
集成流2
1.下載中文簡體語言包
2.導(dǎo)入依賴
3.API的使用,獲取TessBaseAPI mBaseAPI = new TessBaseAPI();實(shí)例
4.API的使用,初始化TessBaseAPI設(shè)置,設(shè)置識別的語言和語言包所在文件路徑 mBaseAPI.init(path + File.separator, "chi_sim");
5.API的使用,設(shè)置Bitmap,mBaseAPI.setImage(bitmap);
6.API的使用,從Bitmap獲取文字信息,mBaseAPI.getUTF8Text();
1.下載中文簡體語言包
找到tessdata——>chi_sim.traineddata
下載好了之后,需要放到sd卡中,目錄不限,但是必須要放在tessdata目錄里面,如果沒有tessdata目錄需要手動創(chuàng)建,例如我是Demo中是放在sd卡根目錄中,就直接在sd卡根目錄創(chuàng)建tessdata目錄,然后把下載好的chi_sim.traineddata語言包丟進(jìn)去,實(shí)際項(xiàng)目中,在識別時(shí)候最好坐下語言包是否復(fù)制到位的檢查,以免出現(xiàn)異常。Demo中僅僅是檢查了是否創(chuàng)建tessdata目錄,這里實(shí)際上仍然存在風(fēng)險(xiǎn)的。
2.導(dǎo)入依賴
Gradle方式添加:https://github.com/rmtheis/tess-two
3.MainActivity代碼
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView mTvInfo; private TessBaseAPI mBaseAPI; private ProgressBar mProbar; private String path; private RadioGroup mRadioGroup; private RadioButton mRbtnIdCard; private RadioButton mRbtnBankNumber; private RadioButton mRbtnTxt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_start).setOnClickListener(this); mProbar = (ProgressBar) findViewById(R.id.pb); mTvInfo = (TextView) findViewById(R.id.tv_info); mRadioGroup = (RadioGroup) findViewById(R.id.rg); mRbtnIdCard = (RadioButton) findViewById(R.id.rb_idCard); mRbtnBankNumber = (RadioButton) findViewById(R.id.rb_bankNumber); mRbtnTxt = (RadioButton) findViewById(R.id.rb_txt); mRadioGroup.check(0); path = Environment.getExternalStorageDirectory().getAbsoluteFile().getAbsolutePath(); } @Override public void onClick(View v) { mTvInfo.setText(""); switch (v.getId()) { case R.id.btn_start: if (Build.VERSION.SDK_INT >= 23) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 沒有權(quán)限 if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){ //如果沒勾選“不再詢問”,向用戶發(fā)起權(quán)限請求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 0); }else{ Toast.makeText(this,"請前往設(shè)置——>存儲卡權(quán)限——>允許",Toast.LENGTH_SHORT).show(); } } else { // 有權(quán)限,接著你要干的活 startReadText(); } }else{ startReadText(); } break; } } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: String s = (String) msg.obj; if (!TextUtils.isEmpty(s)) { mProbar.setVisibility(View.GONE); mTvInfo.setText(s); //釋放bitmap mBaseAPI.clear(); } else { mProbar.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "識別圖片內(nèi)容失敗", Toast.LENGTH_SHORT).show(); } break; case 1: Toast.makeText(MainActivity.this, "讀取圖片失敗", Toast.LENGTH_SHORT).show(); break; } } }; private Bitmap getBitmap(int id) { Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeResource(getResources(), id); } catch (Exception e) { return null; } return bitmap; } /** * 開始識別文字 */ private void startReadText() { File f = new File(path+"/tessdata") ; if(!f.exists()){ Toast.makeText(this,"請先下載好語言包置于sd/tessdata目錄",Toast.LENGTH_SHORT).show(); return; } final int btnId = mRadioGroup.getCheckedRadioButtonId(); final int resId ; if(R.id.rb_idCard==btnId){ resId = R.drawable.idcard; }else if(R.id.rb_bankNumber==btnId){ resId = R.drawable.bank_number; }else{ resId = R.drawable.tet_info; } mProbar.setVisibility(View.VISIBLE); new Thread() { @Override public void run() { mBaseAPI = new TessBaseAPI();//初始化需要耗時(shí),可以啟動時(shí)程序時(shí),預(yù)初始化 mBaseAPI.init(path + File.separator, "chi_sim"); Bitmap bitmap = getBitmap(resId); if (bitmap == null) { mHandler.sendEmptyMessage(1); } else { mBaseAPI.setImage(bitmap); //根據(jù)Init的語言,獲得ocr后的字符串 String t = mBaseAPI.getUTF8Text();//耗時(shí)操作 Message obtain = Message.obtain(); obtain.what = 0; obtain.obj = t; mHandler.sendMessage(obtain); } } }.start(); } }
4.activity_main.xml代碼
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.demo.orc.MainActivity"> <RadioGroup android:id="@+id/rg" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <RadioButton android:checked="true" android:id="@+id/rb_idCard" android:text="身份證" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <RadioButton android:id="@+id/rb_bankNumber" android:text="銀行卡" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <RadioButton android:id="@+id/rb_txt" android:text="文字" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RadioGroup> <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="開始識別"/> <TextView android:text="識別結(jié)果展示區(qū):" android:layout_width="match_parent" android:layout_height="wrap_content" /> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar android:id="@+id/pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:visibility="gone"/> <TextView android:id="@+id/tv_info" android:layout_width="match_parent" android:layout_height="match_parent" android:text=""/> </FrameLayout> </LinearLayout>
四、提高識別率
Demo識別率其實(shí)不是很理想,比如把數(shù)字0識別成了字母O等,這是因?yàn)槲覀兊母緵]有進(jìn)行樣本訓(xùn)練。關(guān)于樣本的訓(xùn)練,我目前還沒實(shí)際操作過,因?yàn)楣镜淖R別需求更為復(fù)雜,這個(gè)框架難以達(dá)到效果,公司買了第三方的一個(gè)識別框架。不過僅僅是實(shí)現(xiàn)身份證號,銀行卡號,和一些簡單的文字信息,用這個(gè)框架足以實(shí)現(xiàn)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android使用Handler實(shí)現(xiàn)下載文件功能
這篇文章主要為大家詳細(xì)介紹了Android使用Handler實(shí)現(xiàn)下載文件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Android自定義PopupWindow實(shí)現(xiàn)炫酷的IOS對話框效果
這篇文章主要給大家介紹如何在android中實(shí)現(xiàn)高仿ios對話框效果,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05Android編程之線性布局LinearLayout實(shí)例簡析
這篇文章主要介紹了Android編程之線性布局LinearLayout用法,結(jié)合實(shí)例形式簡單分析了Android線性布局的使用技巧,需要的朋友可以參考下2016-01-01RxJava+Retrofit+OkHttp實(shí)現(xiàn)文件上傳
本篇文章主要介紹了RxJava+Retrofit+OkHttp實(shí)現(xiàn)文件上傳,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11Android基于注解的6.0權(quán)限動態(tài)請求框架詳解
這篇文章主要介紹了Android基于注解的6.0權(quán)限動態(tài)請求框架詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04在當(dāng)前Activity之上創(chuàng)建懸浮view之WindowManager懸浮窗效果
這篇文章主要介紹了在當(dāng)前Activity之上創(chuàng)建懸浮view之WindowManager懸浮窗效果的相關(guān)資料,需要的朋友可以參考下2016-01-01Android編程圖片操作類定義與用法示例【拍照,相冊選圖及裁剪】
這篇文章主要介紹了Android編程圖片操作類定義與用法,涉及Android拍照,相冊選圖及裁剪等圖片操作功能及權(quán)限控制相關(guān)操作技巧,需要的朋友可以參考下2018-02-02