首先我得認可,關注tesseract-ocr, 是衝着下面這篇文章的噱頭去的,26行groovy代碼破解網站驗證碼
http://www.kellyrob99.com/blog/2010/03/14/breaking-weak-captcha-in-slightly-more-than-26-lines-of-groovy-code/
固然,看了以後才知道,原來是調用了三方庫tesseract-ocr……
http://code.google.com/p/tesseract-ocr/
儘管如此,本着鄧爺爺的「無論白貓黑貓,能抓住老鼠的就是好貓」的原則,趁着假期也開始了「文字識別」的初級研究
HP的tesseract最近被Google支持並開支持英文字母和數字,聽說辨識程度是世界排名第三的;更難能難得的是,提供多國語言包下載(包括中文,精度不咋的卻是真的……),並自帶訓練工具。
安裝完並跑過自帶例子以後,首先想到的應用天然是用於驗證碼分析
按照說明,送入tesseract的圖片的質量直接影響識別的效果,所以,簡單的預處理是不可或缺的
1.首先灰度化,灰度值=0.3R+0.59G+0.11B:
-
- for (int y = minY; y < height; y++) {
- for (int x = minX; x < width; x++) {
- int rgb = srcImg.getRGB(x, y);
- Color color = new Color(rgb);
- int gray = (int) (0.3 * color.getRed() + 0.59
- * color.getGreen() + 0.11 * color.getBlue());
- Color newColor = new Color(gray, gray, gray);
- srcImg.setRGB(x, y, newColor.getRGB());
- }
- }
結果如圖:
2.其次是灰度反轉:
- for (int y = minY; y < height; y++) {
- for (int x = minX; x < width; x++) {
- int rgb = buffImg.getRGB(x, y);
- Color color = new Color(rgb);
- Color newColor = new Color(255 - color.getRed(), 255 - color
- .getGreen(), 255 - color.getBlue());
- buffImg.setRGB(x, y, newColor.getRGB());
- }
- }
結果如圖:
3.再次是二值化,取圖片的平均灰度做爲閾值,低於該值的全都爲0,高於該值的全都爲255:
- for (int y = minY; y < height; y++) {
- for (int x = minX; x < width; x++) {
- int rgb = buffImg.getRGB(x, y);
- Color color = new Color(rgb);
- int value = 255 - color.getBlue();
- if (value > average) {
- Color newColor = new Color(0, 0, 0);
- buffImg.setRGB(x, y, newColor.getRGB());
- } else {
- Color newColor = new Color(255, 255, 255);
- buffImg.setRGB(x, y, newColor.getRGB());
- }
- }
- }
結果如圖:
看看效果還湊合,就省卻尺寸調整、中值濾波以及噪點去除等步驟了。
以上完成圖片預處理工做;Tesseract沒有開放api,純命令行調用:
- List<String> cmd = new ArrayList<String>();
- cmd.add(tessPath + "\\tesseract");
- cmd.add("");
- cmd.add(outputFile.getName());
- cmd.add(LANG_OPTION);
- cmd.add("eng");
- ProcessBuilder pb = new ProcessBuilder();
- pb.directory(imageFile.getParentFile());
-
- cmd.set(1, tempImage.getName());
-
- pb.command(cmd);
- pb.redirectErrorStream(true);
- Process process = pb.start();
-
- int w = process.waitFor();
結果輸出表示一切正常
固然,真正要用好tesseract-ocr,還需用到其強大地訓練工具,就是後話了……
另外,關於文字識別,除去做爲破解驗證碼的反制手段以外,咱們是否也有相關的應用呢?