背景介紹:
這段時間正在做一個流動人口管理項目,其中要求使用H5網頁拍照識別身份證,當時就蒙圈了,這不是APP的功能嗎?產品為了快速迭代一直把APP的功能往H5上堆砌,沒辦法只有想辦法解決了。
查了一些資料,發現除了收費的OCR(百度、雲脈等等)比較好的並支持中文的就只有tesseract了,當然我收費的OCR我也沒測試。
暫時決定使用tesseract了。
思路介紹
我的思路是這樣的:
由H5調用攝像頭—–>拍照上傳到服務端—->服務端識別身份信息—–>服務端返回身份信息。
關鍵點提高識別率
因為整張身份證的識別率太過讓人失望,所以必須對身份證圖片進行處理。
假設我們能把身份證上的關鍵信息截取下來,是不是可以提高OCR的識別率?
遵循這個假設開始測試。
安裝tesseract-ocr
我是在windows下進行測試的,Linux安裝大家可以參考這篇博客Linux安裝tesseract-ocr
windows下比較簡單,下載程序安裝就好,其中需要語言包的可以在安裝選項中選擇下載中文語言包,默認只有英文的。我安裝的版本是tesseract-ocr3.01-1
Tesseract下載地址
因為wall的原因,這個網址無法直接打開,你懂的,所以使用迅雷下載吧。復制鏈接地址到迅雷新建任務,可以的。
同意,下一步,選擇語言包。我選了簡體中文,但因為wall的原因沒安裝上!!!
中文的識別率太低了,這個大家也知道,結果跟產品扯了下皮,先做一版識別身份證號碼的好了。這也是為什么我的標題是 識別身份證號碼而不是識別身份信息了。
裝完之后測試一下,找一個數字圖片測試一下
進入圖片目錄 運行cmd tesseract 1.png result
tesseract 是命令
1.png 是圖片
result 是需要生成結果的txt文檔名,隨便取
這結果令人堪憂啊。。
還好我們可以提高識別率的方法。
提高數字識別率,指定識別字符范圍
找到安裝目錄下的tessdata\configs,打開其中的digits文件,使用文本編輯就好了。
我安裝的在這個目錄下
D:\Program Files (x86)\Tesseract-OCR\tessdata\configs\digits
你會看見下面這句話,我們只要識別數字那就只留下數字和X好了。
tessedit_char_whitelist 0123456789-.
改為
tessedit_char_whitelist 0123456789X
保存
這個時候再測試一下,不過命令需要變一下,后面加上digits
tesseract 1.png result digits
效果比較令人滿意。
接下來就要使用Java調用識別命令了,其實很簡單,就是使用java調用CMD命令。
使用java調用識別命令
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; /** * Created by Gavin Wang on 16-3-3. */ public class Tesseract { private final String LANG_OPTION = "-l"; private final String EOL = System.getProperty("line.separator"); /** * 文件位置我防止在,項目同一路徑 */ private String tessPath = new File("tesseract").getAbsolutePath(); /** * @param imageFile * 傳入的圖像文件 * @param imageFormat * 傳入的圖像格式 * @return 識別后的字符串 */ public String recognizeText(File imageFile) throws Exception { /** * 設置輸出文件的保存的文件目錄 */ File outputFile = new File(imageFile.getParentFile(), "output"); StringBuffer strB = new StringBuffer(); List<String> cmd = new ArrayList<String>(); String os = System.getProperty("os.name"); if(os.toLowerCase().startsWith("win")){ cmd.add("tesseract"); }else { cmd.add("tesseract"); } // cmd.add(tessPath + "\\tesseract"); cmd.add(imageFile.getName()); cmd.add(outputFile.getName()); // cmd.add(LANG_OPTION); // cmd.add("chi_sim"); cmd.add("digits"); // cmd.add("eng"); // cmd.add("-psm 7"); ProcessBuilder pb = new ProcessBuilder(); /** *Sets this process builder's working directory. */ pb.directory(imageFile.getParentFile()); // cmd.set(1, imageFile.getName()); pb.command(cmd); pb.redirectErrorStream(true); Process process = pb.start(); // Process process = pb.command("ipconfig").start(); // System.out.println(System.getenv().get("Path")); // Process process = pb.command("D:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe",imageFile.getName(),outputFile.getName(),LANG_OPTION,"eng").start(); // tesseract.exe 1.jpg 1 -l chi_sim // Runtime.getRuntime().exec("tesseract.exe 1.jpg 1 -l chi_sim"); /** * the exit value of the process. By convention, 0 indicates normal * termination. */ // System.out.println(cmd.toString()); int w = process.waitFor(); if (w == 0)// 0代表正常退出 { BufferedReader in = new BufferedReader(new InputStreamReader( new FileInputStream(outputFile.getAbsolutePath() + ".txt"), "UTF-8")); String str; while ((str = in.readLine()) != null) { strB.append(str).append(EOL); } in.close(); } else { String msg; switch (w) { case 1: msg = "Errors accessing files. There may be spaces in your image's filename."; break; case 29: msg = "Cannot recognize the image or its selected region."; break; case 31: msg = "Unsupported image format."; break; default: msg = "Errors occurred."; } throw new RuntimeException(msg); } new File(outputFile.getAbsolutePath() + ".txt").delete(); return strB.toString().replaceAll("\\s*", ""); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
注釋掉的內容大家都可刪掉,是我測試的時候遺留的
下面是main方法
import java.io.File; import java.io.IOException; /** * Created by Gavin Wang on 16-3-3. */ public class Start { public static void main(String[] args) throws Exception { Tesseract("/1.png"); Tesseract("/2.png"); Tesseract("/3.png"); Tesseract("/4.png"); Tesseract("/5.png"); Tesseract("/6.png"); } private static void Tesseract(String fileString) throws Exception { String filePath = Start.class.getResource(fileString).getFile().toString(); // processImg(filePath); File file = new File(filePath); String recognizeText = new Tesseract().recognizeText(file); System.out.println(recognizeText); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
有可能你執行出錯,無法在XX目錄執行 tesseract…..
這個時候重啟一下電腦就好了,原因是環境變量沒有在idea中生效。
測試結果如下,目前還是比較滿意的
后記
識別就先到這告一段落吧,下一篇日志我們繼續如何使用H5識別身份證號碼。
對識別率提高的其他思考
其實對號碼的識別我也想過做一些處理,比如把身份證的背景紋路去掉,只留下身份證的數字。變成下面這樣的
但是我發現,處理之后時候有的識別率反而降低了,沒研究過tesseract-orc的原理,不知為何這樣識別率反而降低。希望大家能研究一下如何提高識別率在下面留言告訴我,多謝了。
第二篇如何使用H5識別身份證號碼可以在我的博客地址找到http://blog.csdn.net/hiredme
(轉自http://blog.csdn.net/hiredme/article/details/50894814)