tess-two庫實(shí)現(xiàn)身份證識(shí)別
最近工作中遇到身份證上次需要驗(yàn)證問題,在網(wǎng)上搜索了大量信息,大概都是用tess-two庫實(shí)現(xiàn),但識(shí)別率不是很高,在它基礎(chǔ)上,做了點(diǎn)優(yōu)化,識(shí)別率比它高那么點(diǎn)
所做的優(yōu)化方式就是,對圖片進(jìn)行二值化以及灰度化,然后再獲取圖片上的信息,至少能獲取到身份證號(hào)碼,其他中文字實(shí)在是無法匹配。
編程工具為:eclipse
首先需要做的步驟是:1、有下載tess-two庫,當(dāng)然,需要包括.so文件的,不然你還需要編譯一遍,編譯步驟需要在網(wǎng)上找,在上篇文章中寫了編譯過程中出現(xiàn)的問題,可以借鑒下, 現(xiàn)在提供下未做修改的代碼下載地址:http://download.csdn.net/detail/a1031359915/9523864
將chi_sim.traineddata文件拷貝到/mnt/sdcard/tesseract/目錄下。
下面是優(yōu)化的代碼:
import?java.io.File;
import?com.googlecode.tesseract.android.TessBaseAPI;
import?com.googlecode.tesseract.android.test.R;
import?android.app.Activity;
import?android.graphics.Bitmap;
import?android.graphics.BitmapFactory;
import?android.os.Bundle;
import?android.widget.ImageView;
import?android.widget.TextView;
public?class?TestActivity?extends?Activity?{
private?static?final?String?TESSBASE_PATH?=?"/mnt/sdcard/tesseract/";??
????private?static?final?String?DEFAULT_LANGUAGE?=?"eng";??
????private?static?final?String?CHINESE_LANGUAGE?=?"chi_sim";?//?chi_tra?chi_sim
@Override
protected?void?onCreate(Bundle?savedInstanceState)?{
//?TODO?Auto-generated?method?stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
ImageView?img?=?(ImageView)?findViewById(R.id.img);
???????
?????????
??????????????TessBaseAPI?baseApi?=?new?TessBaseAPI();??
??????????????baseApi.init(TESSBASE_PATH,?CHINESE_LANGUAGE);??
// ???????baseApi.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO);??
// ???????File?file?=?new?File("/mnt/sdcard/sf.jpg");
// ???????if?(file.exists()){
// ???? ???baseApi.setImage(file);??
// ???????}
?????????Bitmap?bitmap?=?BitmapFactory.decodeFile("/mnt/sdcard/sf.jpg");
?????????bitmap?=??ImageFilter.gray2Binary(bitmap);//?圖片二值化
?????????bitmap?=??ImageFilter.grayScaleImage(bitmap);//?圖片灰度化
?????????img.setImageBitmap(bitmap);
?????????baseApi.setImage(bitmap);??
???????//?Ensure?that?the?result?is?correct.??
???????final?String?outputText?=?baseApi.getUTF8Text();??
???????TextView?view?=?(TextView)?findViewById(R.id.tv_test);
???????view.setText(outputText);
???????baseApi.end();?
}
}
圖片處理類:
import?android.graphics.Bitmap;
import?android.graphics.Bitmap.Config;
import?android.graphics.Canvas;
import?android.graphics.Color;
import?android.graphics.ColorMatrix;
import?android.graphics.ColorMatrixColorFilter;
import?android.graphics.Paint;
import?android.util.Log;
public?class?ImageFilter?{
//?圖像灰度化
public?static?Bitmap?bitmap2Gray(Bitmap?bmSrc)?{
//?得到圖片的長和寬
int?width?=?bmSrc.getWidth();
int?height?=?bmSrc.getHeight();
//?創(chuàng)建目標(biāo)灰度圖像
Bitmap?bmpGray?=?null;
bmpGray?=?Bitmap.createBitmap(width,?height,?Bitmap.Config.ARGB_8888);
//?創(chuàng)建畫布
Canvas?c?=?new?Canvas(bmpGray);
Paint?paint?=?new?Paint();
ColorMatrix?cm?=?new?ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter?f?=?new?ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmSrc,?0,?0,?paint);
return?bmpGray;
}
//?圖像灰度化
public?static?Bitmap?grayScaleImage(Bitmap?src)?{
????????//?constant?factors
????????final?double?GS_RED?=?0.299;
????????final?double?GS_GREEN?=?0.587;
????????final?double?GS_BLUE?=?0.114;
//??????final?double?GS_RED?=?0.235;
//??????final?double?GS_GREEN?=?0.589;
//??????final?double?GS_BLUE?=?0.119;
????????
????????//?create?output?bitmap
????????Bitmap?bmOut?=?Bitmap.createBitmap(src.getWidth(),?src.getHeight(),?src.getConfig());
????????//?pixel?information
????????int?A,?R,?G,?B;
????????int?pixel;
????????
????????//?get?image?size
????????int?width?=?src.getWidth();
????????int?height?=?src.getHeight();
????????
????????//?scan?through?every?single?pixel
????????for(int?x?=?0;?x?<?width;?++x)?{
?????????for(int?y?=?0;?y?<?height;?++y)?{
??????????//?get?one?pixel?color
??????????pixel?=?src.getPixel(x,?y);
??????????//?retrieve?color?of?all?channels
??????????A?=?Color.alpha(pixel);
??????????R?=?Color.red(pixel);
??????????G?=?Color.green(pixel);
??????????B?=?Color.blue(pixel);
??????????//?take?conversion?up?to?one?single?value
??????????R?=?G?=?B?=?(int)(GS_RED?*?R?+?GS_GREEN?*?G?+?GS_BLUE?*?B);
??????????//?set?new?pixel?color?to?output?bitmap
??????????bmOut.setPixel(x,?y,?Color.argb(A,?R,?G,?B));
?????????}
????????}
????????
????????//?return?final?image
????????return?bmOut;
???????}
//?對圖像進(jìn)行線性灰度變化
public?static?Bitmap?lineGrey(Bitmap?image)?{
//?得到圖像的寬度和長度
int?width?=?image.getWidth();
int?height?=?image.getHeight();
//?創(chuàng)建線性拉升灰度圖像
Bitmap?linegray?=?null;
linegray?=?image.copy(Config.ARGB_8888,?true);
//?依次循環(huán)對圖像的像素進(jìn)行處理
for?(int?i?=?0;?i?<?width;?i++)?{
for?(int?j?=?0;?j?<?height;?j++)?{
//?得到每點(diǎn)的像素值
int?col?=?image.getPixel(i,?j);
int?alpha?=?col?&?0xFF000000;
int?red?=?(col?&?0x00FF0000)?>>?16;
int?green?=?(col?&?0x0000FF00)?>>?8;
int?blue?=?(col?&?0x000000FF);
//?增加了圖像的亮度
red?=?(int)?(1.1?*?red?+?30);
green?=?(int)?(1.1?*?green?+?30);
blue?=?(int)?(1.1?*?blue?+?30);
//?對圖像像素越界進(jìn)行處理
if?(red?>=?255)?{
red?=?255;
}
if?(green?>=?255)?{
green?=?255;
}
if?(blue?>=?255)?{
blue?=?255;
}
//?新的ARGB
int?newColor?=?alpha?|?(red?<<?16)?|?(green?<<?8)?|?blue;
//?設(shè)置新圖像的RGB值
linegray.setPixel(i,?j,?newColor);
}
}
return?linegray;
}
//?該函數(shù)實(shí)現(xiàn)對圖像進(jìn)行二值化處理
public?static?Bitmap?gray2Binary(Bitmap?graymap)?{
//?得到圖形的寬度和長度
int?width?=?graymap.getWidth();
int?height?=?graymap.getHeight();
//?創(chuàng)建二值化圖像
Bitmap?binarymap?=?null;
binarymap?=?graymap.copy(Config.ARGB_8888,?true);
//?依次循環(huán),對圖像的像素進(jìn)行處理
for?(int?i?=?0;?i?<?width;?i++)?{
for?(int?j?=?0;?j?<?height;?j++)?{
//?得到當(dāng)前像素的值
int?col?=?binarymap.getPixel(i,?j);
//?得到alpha通道的值
int?alpha?=?col?&?0xFF000000;
//?得到圖像的像素RGB的值
int?red?=?(col?&?0x00FF0000)?>>?16;
int?green?=?(col?&?0x0000FF00)?>>?8;
int?blue?=?(col?&?0x000000FF);
//?用公式X?=?0.3×R+0.59×G+0.11×B計(jì)算出X代替原來的RGB
int?gray?=?(int)?((float)?red?*?0.3?+?(float)?green?*?0.59?+?(float)?blue?*?0.11);
//?對圖像進(jìn)行二值化處理
if?(gray?<=?95)?{
gray?=?0;
}?else?{
gray?=?255;
}
//?新的ARGB
int?newColor?=?alpha?|?(gray?<<?16)?|?(gray?<<?8)?|?gray;
//?設(shè)置新圖像的當(dāng)前像素值
binarymap.setPixel(i,?j,?newColor);
}
}
return?binarymap;
}
/**
?????*?將彩色圖轉(zhuǎn)換為黑白圖
?????*?
?????*?@param?位圖
?????*?@return?返回轉(zhuǎn)換好的位圖
?????*/
????public?static?Bitmap?convertToBlackWhite(Bitmap?bmp)?{
????????int?width?=?bmp.getWidth();?//?獲取位圖的寬
????????int?height?=?bmp.getHeight();?//?獲取位圖的高
????????int[]?pixels?=?new?int[width?*?height];?//?通過位圖的大小創(chuàng)建像素點(diǎn)數(shù)組
????????bmp.getPixels(pixels,?0,?width,?0,?0,?width,?height);
????????int?alpha?=?0xFF?<<?24;
????????for?(int?i?=?0;?i?<?height;?i++)?{
????????????for?(int?j?=?0;?j?<?width;?j++)?{
????????????????int?grey?=?pixels[width?*?i?+?j];
????????????????int?red?=?((grey?&?0x00FF0000)?>>?16);
????????????????int?green?=?((grey?&?0x0000FF00)?>>?8);
????????????????int?blue?=?(grey?&?0x000000FF);
????????????????grey?=?(int)?(red?*?0.3?+?green?*?0.59?+?blue?*?0.11);
????????????????grey?=?alpha?|?(grey?<<?16)?|?(grey?<<?8)?|?grey;
????????????????pixels[width?*?i?+?j]?=?grey;
????????????}
????????}
????????Bitmap?newBmp?=?Bitmap.createBitmap(width,?height,?Config.ARGB_8888);
????????newBmp.setPixels(pixels,?0,?width,?0,?0,?width,?height);
????????return?newBmp;
????}
????
????/**
?????*?圖片銳化(拉普拉斯變換)
?????*?
?????*?@param?bmp
?????*?@return
?????*/
????public?static?Bitmap?sharpenImageAmeliorate(Bitmap?bmp)?{
????????//?拉普拉斯矩陣
????????int[]?laplacian?=?new?int[]?{?-1,?-1,?-1,?-1,?9,?-1,?-1,?-1,?-1?};
????????int?width?=?bmp.getWidth();
????????int?height?=?bmp.getHeight();
????????Bitmap?bitmap?=?Bitmap.createBitmap(width,?height,
????????????????Bitmap.Config.ARGB_8888);
????????int?pixR?=?0;
????????int?pixG?=?0;
????????int?pixB?=?0;
????????int?pixColor?=?0;
????????int?newR?=?0;
????????int?newG?=?0;
????????int?newB?=?0;
????????int?idx?=?0;
????????float?alpha?=?0.3F;
????????int[]?pixels?=?new?int[width?*?height];
????????bmp.getPixels(pixels,?0,?width,?0,?0,?width,?height);
????????for?(int?i?=?1,?length?=?height?-?1;?i?<?length;?i++)?{
????????????for?(int?k?=?1,?len?=?width?-?1;?k?<?len;?k++)?{
????????????????idx?=?0;
????????????????for?(int?m?=?-1;?m?<=?1;?m++)?{
????????????????????for?(int?n?=?-1;?n?<=?1;?n++)?{
????????????????????????pixColor?=?pixels[(i?+?n)?*?width?+?k?+?m];
????????????????????????pixR?=?Color.red(pixColor);
????????????????????????pixG?=?Color.green(pixColor);
????????????????????????pixB?=?Color.blue(pixColor);
????????????????????????newR?=?newR?+?(int)?(pixR?*?laplacian[idx]?*?alpha);
????????????????????????newG?=?newG?+?(int)?(pixG?*?laplacian[idx]?*?alpha);
????????????????????????newB?=?newB?+?(int)?(pixB?*?laplacian[idx]?*?alpha);
????????????????????????idx++;
????????????????????}
????????????????}
????????????????newR?=?Math.min(255,?Math.max(0,?newR));
????????????????newG?=?Math.min(255,?Math.max(0,?newG));
????????????????newB?=?Math.min(255,?Math.max(0,?newB));
????????????????pixels[i?*?width?+?k]?=?Color.argb(255,?newR,?newG,?newB);
????????????????newR?=?0;
????????????????newG?=?0;
????????????????newB?=?0;
????????????}
????????}
????????bitmap.setPixels(pixels,?0,?width,?0,?0,?width,?height);
????????return?bitmap;
????}
}
至此,身份證號(hào)碼應(yīng)該能獲取到,再聲明下,識(shí)別率不是很好,希望能有大神能夠完善下,謝謝!





