一荚孵、什么是orc?
引用百度百科的介紹妹窖,指利用光學字符識別(ORC全稱:Optical Character Recognition)技術,將圖片收叶、照片上的文字內(nèi)容骄呼,直接轉換為可編輯文本,支持JPG、PNG蜓萄、GIF隅茎、BMP、DOC等圖片格式嫉沽。簡單一句話辟犀,就是可以把圖片上的文字識別出來。應用的場景有很多绸硕,比如說:身份證號碼識別堂竟,銀行卡號識別等等。
二臣咖、效果展示
三跃捣、開始集成
Github上面已經(jīng)提供了android端的工具api,Github地址:https://github.com/rmtheis/tess-two<br />
集成流程<br />
1.下載中文簡體語言包
2.導入依賴
3.API的使用夺蛇,獲取TessBaseAPI mBaseAPI = new TessBaseAPI();
實例
4.API的使用疚漆,初始化TessBaseAPI設置,設置識別的語言和語言包所在文件路徑mBaseAPI.init(path + File.separator, "chi_sim");
5.API的使用刁赦,設置Bitmap娶聘,mBaseAPI.setImage(bitmap);
6.API的使用,從Bitmap獲取文字信息甚脉,mBaseAPI.getUTF8Text();
1.下載中文簡體語言包
語言包下載地址
找到tessdata——>chi_sim.traineddata<br />
下載好了之后丸升,需要放到sd卡中,目錄不限牺氨,但是必須要放在tessdata目錄里面狡耻,如果沒有tessdata目錄需要手動創(chuàng)建,例如我是Demo中是放在sd卡根目錄中猴凹,就直接在sd卡根目錄創(chuàng)建tessdata目錄夷狰,然后把下載好的chi_sim.traineddata
語言包丟進去,實際項目中,在識別時候最好坐下語言包是否復制到位的檢查郊霎,以免出現(xiàn)異常沼头。Demo中僅僅是檢查了是否創(chuàng)建tessdata目錄,這里實際上仍然存在風險的书劝。
2.導入依賴
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) {
// 沒有權限
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){
//如果沒勾選“不再詢問”进倍,向用戶發(fā)起權限請求
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 0);
}else{
Toast.makeText(this,"請前往設置——>存儲卡權限——>允許",Toast.LENGTH_SHORT).show();
}
} else {
// 有權限,接著你要干的活
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();//初始化需要耗時,可以啟動時程序時购对,預初始化
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();//耗時操作
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="識別結果展示區(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ù)字0識別成了字母O等垂蜗,這是因為我們的根本沒有進行樣本訓練坑赡。關于樣本的訓練,我目前還沒實際操作過么抗,因為公司的識別需求更為復雜,這個框架難以達到效果亚铁,公司買了第三方的一個識別框架蝇刀。不過僅僅是實現(xiàn)身份證號,銀行卡號徘溢,和一些簡單的文字信息吞琐,用這個框架足以實現(xiàn)。需要樣本訓練的童鞋可以參考這篇博客:樣本訓練博客 然爆。