tess-two庫(kù)實(shí)現(xiàn)身份證識(shí)別
最近工作中遇到身份證上次需要驗(yàn)證問(wèn)題,在網(wǎng)上搜索了大量信息,大概都是用tess-two庫(kù)實(shí)現(xiàn),但識(shí)別率不是很高,在它基礎(chǔ)上,做了點(diǎn)優(yōu)化,識(shí)別率比它高那么點(diǎn)
所做的優(yōu)化方式就是,對(duì)圖片進(jìn)行二值化以及灰度化,然后再獲取圖片上的信息,至少能獲取到身份證號(hào)碼,其他中文字實(shí)在是無(wú)法匹配。
編程工具為:eclipse
首先需要做的步驟是:1、有下載tess-two庫(kù),當(dāng)然,需要包括.so文件的,不然你還需要編譯一遍,編譯步驟需要在網(wǎng)上找,在上篇文章中寫了編譯過(guò)程中出現(xiàn)的問(wè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)?{ //?得到圖片的長(zhǎng)和寬 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; ???????} //?對(duì)圖像進(jìn)行線性灰度變化 public?static?Bitmap?lineGrey(Bitmap?image)?{ //?得到圖像的寬度和長(zhǎng)度 int?width?=?image.getWidth(); int?height?=?image.getHeight(); //?創(chuàng)建線性拉升灰度圖像 Bitmap?linegray?=?null; linegray?=?image.copy(Config.ARGB_8888,?true); //?依次循環(huán)對(duì)圖像的像素進(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); //?對(duì)圖像像素越界進(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)對(duì)圖像進(jìn)行二值化處理 public?static?Bitmap?gray2Binary(Bitmap?graymap)?{ //?得到圖形的寬度和長(zhǎng)度 int?width?=?graymap.getWidth(); int?height?=?graymap.getHeight(); //?創(chuàng)建二值化圖像 Bitmap?binarymap?=?null; binarymap?=?graymap.copy(Config.ARGB_8888,?true); //?依次循環(huán),對(duì)圖像的像素進(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代替原來(lái)的RGB int?gray?=?(int)?((float)?red?*?0.3?+?(float)?green?*?0.59?+?(float)?blue?*?0.11); //?對(duì)圖像進(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];?//?通過(guò)位圖的大小創(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í)別率不是很好,希望能有大神能夠完善下,謝謝!