前些天下午沒什么事,朋友有個需求掸刊,說要識別身份證上面的身份證號碼免糕,剛好閑著,就幫他解決了一下,不說多完美石窑,但是至少算是解決需求了牌芋,好了,閑話少說尼斧。
先來看一下我的DEMO吧
接下來我們一個個介紹(Demo我會放在最下面)
1.聯(lián)網(wǎng)識別
也是從別人的Demo里截出來的姜贡,其實(shí)也是用的別人的一個在線接口,但是我看了看應(yīng)該算“非正常調(diào)用”(這個意思大家自己理解吧)棺棵。下面分析一下這個方法的優(yōu)劣點(diǎn)吧楼咳。
優(yōu)點(diǎn):速度極快,上傳照片烛恤,會返回身份證上所有信息母怜,包括姓名 地址 出生等等
缺點(diǎn):“非正常”調(diào)用就有一定的不可靠性缚柏,如果哪天人家關(guān)了或者改了這個接口苹熏,就比較尷尬了,當(dāng)然你可以選擇購買人家的正式版币喧。
2.本地識別
基于Tess_two做的識別轨域,這個大家可放心使用。先看一下大概怎么使用吧杀餐!
首先引用:
compile 'com.rmtheis:tess-two:6.0.0'
然后使用干发,其實(shí)使用起來很簡單,但是要注意幾點(diǎn)
1.要在SD卡有他的識別庫史翘,這個庫你可以理解為一個字典枉长,這個字典可以自己訓(xùn)練,因?yàn)槲沂怯玫膭e人訓(xùn)練好的(只包含英文和數(shù)字)琼讽,所以就不說怎么訓(xùn)練了必峰,百度一下會有很多。
2.需要注意的是钻蹬,放他字典的路徑文件夾名必須為“tessdata”吼蚁,否則報錯
好了,準(zhǔn)備工作做好了问欠,接下來介紹怎么使用肝匆,我直接貼核心代碼,代碼有注釋溅潜,看不懂的留言或者私信我
//訓(xùn)練數(shù)據(jù)路徑,tessdata
static final String TESSBASE_PATH = Environment.getExternalStorageDirectory() + "/";
//識別語言英文
static final String DEFAULT_LANGUAGE = "eng";
/**
* 傳SD卡圖片路徑(當(dāng)然你們也可以傳Bitmap)
* @param url
*/
private void localre(String url) {
//把圖片轉(zhuǎn)為Bitmap
Bitmap bmp = BitmapFactory.decodeFile(url);
//創(chuàng)建Tess
final TessBaseAPI baseApi = new TessBaseAPI();
//下面這一塊代碼為裁取身份證號碼區(qū)域(否則識別亂碼薪伏,不準(zhǔn)確)
int x, y, w, h;
x = (int) (bmp.getWidth() * 0.340);
y = (int) (bmp.getHeight() * 0.800);
w = (int) (bmp.getWidth() * 0.6 + 0.5f);
h = (int) (bmp.getHeight() * 0.12 + 0.5f);
Bitmap bit_hm = Bitmap.createBitmap(bmp, x, y, w, h);
//這個只是我將裁取的號碼區(qū)展示在了一個ImageView上滚澜,這個可以沒有
iv_number.setImageBitmap(bit_hm);
//初始化OCR的訓(xùn)練數(shù)據(jù)路徑與語言
baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
//設(shè)置識別模式
baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_SINGLE_LINE);
//設(shè)置要識別的圖片
baseApi.setImage(bit_hm);
//設(shè)置字典白名單
baseApi.setVariable("tessedit_char_whitelist", "0123456789Xx");
//把識別內(nèi)容設(shè)置到EditText里
tv_result.setText(baseApi.getUTF8Text());
//收尾
baseApi.clear();
baseApi.end();
}
OK,就這么簡單,圖片清晰切裁取區(qū)域正確的情況下嫁怀,準(zhǔn)確度幾乎100%设捐;
給大家舉個身份證照片的例子吧借浊,否則裁取號碼會不正確
上一張結(jié)果圖
實(shí)時識別
其實(shí)就是本地識別的拓展版,把攝像頭的數(shù)據(jù)轉(zhuǎn)為Bitmap,去識別萝招,還是貼核心代碼吧蚂斤,看不懂的自己下Demo研究。
/**
* 攝像頭數(shù)據(jù)回調(diào)
* @param data
* @param camera
*/
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
camera.addCallbackBuffer(data);
//將byte數(shù)組轉(zhuǎn)為Bitmap
ByteArrayOutputStream baos;
byte[] rawImage;
Bitmap bitmap;
Camera.Size previewSize = camera.getParameters().getPreviewSize();//獲取尺寸,格式轉(zhuǎn)換的時候要用到
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
YuvImage yuvimage = new YuvImage(
data,
ImageFormat.NV21,
previewSize.width,
previewSize.height,
null);
baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);// 80--JPG圖片的質(zhì)量[0-100],100最高
rawImage = baos.toByteArray();
//將rawImage轉(zhuǎn)換成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
bitmap = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
if (bitmap == null) {
Log.d("zka", "bitmap is nlll");
return;
} else {
//裁取圖片中央身份證區(qū)域
int height = bitmap.getHeight();
int width = bitmap.getWidth();
final Bitmap bitmap1 = Bitmap.createBitmap(bitmap, width/2 - dip2px(150),height / 2 - dip2px(92), dip2px(300), dip2px(185));
//截取身份證號碼區(qū)域
int x, y, w, h;
x = (int) (bitmap1.getWidth() * 0.340);
y = (int) (bitmap1.getHeight() * 0.800);
w = (int) (bitmap1.getWidth() * 0.6 + 0.5f);
h = (int) (bitmap1.getHeight() * 0.12 + 0.5f);
Bitmap bit_hm = Bitmap.createBitmap(bitmap1, x, y, w, h);
// 識別
if(bit_hm != null){
String localre = localre(bit_hm);
if (localre.length() == 18) {
Log.e(TAG, "onPreviewFrame: "+localre );
Toast.makeText(getApplicationContext(),localre,Toast.LENGTH_SHORT).show();
}
}
}
}
/**
* 識別
* @param bm
* @return
*/
private String localre(Bitmap bm) {
String content = "";
bm = bm.copy(Bitmap.Config.ARGB_8888, true);
iv_result.setImageBitmap(bm);
TessBaseAPI baseApi = new TessBaseAPI();
baseApi.init(TESSBASE_PATH, DEFAULT_LANGUAGE);
//設(shè)置識別模式
baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_SINGLE_LINE);
//設(shè)置要識別的圖片
baseApi.setImage(bm);
baseApi.setVariable("tessedit_char_whitelist", "0123456789Xx");
Log.e(TAG, "localre: "+ baseApi.getUTF8Text());
content = baseApi.getUTF8Text();
baseApi.clear();
baseApi.end();
return content;
}
Ok槐沼,就這樣吧曙蒸!核心也就這些東西,有問題的可以留言或私信岗钩,有好的解決辦法也可以交流纽窟,喜歡的話點(diǎn)個喜歡或者給個Start吧,出于隱私兼吓,就把人家的信息打碼臂港, 不過識別出來準(zhǔn)確度是100%
GitHub直達(dá):https://github.com/bertsir/IDCardRecognition
2019.10.21 提示:全面屏手機(jī)需要調(diào)整裁切參數(shù),否則實(shí)時識別無效J硬I竽酢!