标签:
【原创,转载请标明作者:森狗】
本文对第二种验证码,即管理员登入后台地址的验证码进行识别。
1.采集一些验证码,0~9都要有
2.观察验证码,用画图工具即可。
观察可发现,噪点即阴影,此处的阴影就是颜色比主体验证码略淡,以此为突破口。
3.去除噪点
color.getGreen() 获取绿色的值int,绿色值(0~255 从深到浅),大于200的就是浅色的噪点
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.二值化验证码
也在第3步的代码中了,如果不是噪点则设为黑色。
处理结果如下:
==================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.我之后对以上代码进行整理后并结合多线程写了完整的弱密码穷举系统。就不在这一一啰嗦了。
标签:
原文地址:http://www.cnblogs.com/sendog/p/5568618.html