【原創,轉載請標明做者:森狗】java
本文對第二種驗證碼,即管理員登入後臺地址的驗證碼進行識別。多線程
1.採集一些驗證碼,0~9都要有app
2.觀察驗證碼,用畫圖工具便可。工具
觀察可發現,噪點即陰影,此處的陰影就是顏色比主體驗證碼略淡,以此爲突破口。測試
3.去除噪點ui
color.getGreen() 獲取綠色的值int,綠色值(0~255 從深到淺),大於200的就是淺色的噪點this
public static int isWhite(int colorInt) { Color color = new Color(colorInt); if (color.getGreen()>=200) { return 1; } return 0; }
public void photo(File imgfile) throws IOException{ File file = imgfile;//圖片地址 String newFile = "testdata"+"/new"+imgfile.getName(); BufferedImage img = getPic(file); int width = img.getWidth(); int height = img.getHeight(); for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { if (isWhite(img.getRGB(x, y)) == 1) { img.setRGB(x, y, Color.WHITE.getRGB()); } else { img.setRGB(x, y, Color.BLACK.getRGB()); } } } saveImg(img,newFile); }
4.二值化驗證碼spa
也在第3步的代碼中了,若是不是噪點則設爲黑色。.net
處理結果以下:線程
==================OCR文本訓練======================
5.以後須要調用tesseract-ocr對驗證碼進行識別,可是識別以前須要對驗證碼進行字符訓練,提升識別成功率。
樣本訓練須要使用工具jTessBoxEditor
具體步驟能夠參考:http://blog.csdn.net/senblingbling/article/details/50683054
這裏面可能有一點錯誤,最後識別的時候調用的語言文件應該是本身生成的語言文件,而不是eng了
像我生成的是 num這個語言文件,語言文件放到ocr對應的目錄裏面了,而後執行
=============================================================
6.Java調用OCR以及這個語言文件來識別咱們的驗證碼
引入這個工具類:
package step2; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.jdesktop.swingx.util.OS; public class OCRHelper { private final String LANG_OPTION = "-l"; private final String EOL = System.getProperty("line.separator"); /** * tesseract 安裝目錄 */ private String tessPath = "D:/備份/桌面/教務處驗證碼識別/tesseract-ocr-setup-3.01-1/"; /** * @param imageFile * 傳入的圖像文件 * @param imageFormat * 傳入的圖像格式 * @return 識別後的字符串 */ public String recognizeText(File imageFile,String photoName) throws Exception { /** * 設置輸出文件的保存的文件目錄 */ File outputFile = new File(imageFile.getParentFile(), photoName); StringBuffer strB = new StringBuffer(); List<String> cmd = new ArrayList<String>(); if (OS.isWindowsXP()) { cmd.add(tessPath + "\\tesseract"); } else if (OS.isLinux()) { cmd.add("tesseract"); } else { cmd.add(tessPath + "\\tesseract"); } cmd.add(""); cmd.add(outputFile.getName()); cmd.add(LANG_OPTION); cmd.add("wss"); //調優後的文件 ProcessBuilder pb = new ProcessBuilder(); /** *Sets this process builder's working directory. */ pb.directory(imageFile.getParentFile()); //System.out.println(imageFile.toString()); cmd.set(1, imageFile.getName()); pb.command(cmd); pb.redirectErrorStream(true); //System.out.println("cmd:"+cmd.toString()); //System.out.println("photoName:"+imageFile.getName()); Process process = pb.start(); /** * the exit value of the process. By convention, 0 indicates normal * termination. */ 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*", ""); } }
以及調用工具類的測試類:
public class WssOcr { /** 驗證碼識別*/ public static void main(String[] args) throws IOException { String photoName = "2.jpg"; WssOcr wss = new WssOcr(); String valid = wss.photoOcr(photoName); System.out.println(valid); } /** * @param photoFile 驗證碼圖片地址 * @param file 舊的圖片地址 */ public String photoOcr(String photoName) { try { String photoFile = "validPhoto/"+photoName; File file = new File(photoFile); PhotoDeal pd = new PhotoDeal(); pd.photo(file);// String newFile = "testdata"+"/new"+file.getName(); File dataFile = new File(newFile); String recognizeText = new OCRHelper().recognizeText(dataFile,photoName); File outputFile = new File("validPhoto/"+photoName+".txt"); if(file.exists()) file.delete(); //刪除驗證碼 if(dataFile.exists()) dataFile.delete(); //刪除二值化驗證碼 if(outputFile.exists()) dataFile.delete(); return recognizeText; } catch (IOException e) { e.printStackTrace(); }catch (Exception e) { e.printStackTrace(); } return ""; } }
調用後測試能夠發現,識別驗證碼的正確率達到百分百,OCR在你處理乾淨驗證碼圖片後仍是很給力的!
=========================================================
PS:
1.識別完驗證碼以後幹什麼? 確定是寫多線程來窮舉嘗試密碼了!
2.我以後對以上代碼進行整理後並結合多線程寫了完整的弱密碼窮舉系統。就不在這一一囉嗦了。