参考资料如下:
图像处理之错切变换 适用于错切变换小于90度的情况,大于90度最后需要平移
爬山算法 模拟退火算法 http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
图像二值化----otsu(最大类间方差法、大津算法)http://blog.csdn.net/abcjennifer/article/details/6671288
十三种基于直方图的图像全局二值化算法原理、实现、代码及效果(转)
二值图像膨胀腐蚀算法的几种实现方式 http://www.tuicool.com/articles/YNB3Mf
实现验证码变形 http://www.shangxueba.com/jingyan/103044.html
支持向量机上课版(上) http://www.julyedu.com/video/play/?id=38&course=23
计算机图形学 http://www.icourse163.org/course/cau-45006?tid=263003#/info
Qi Qi Web portal - AI course http://qiqi789.github.io/teaching/AI/ 老师的人工智能课程
Web验证码的生成与识别_李颖 这篇论文给我很多帮助,这次也让我学会了如何利用论文,以前都是在百度看博文(并不是最佳的)。
不足之处:该系统比较局限,只能较好的处理无粘连有扭曲的图像,对粘连验证码的处理还需要继续研究。
svm
Libsvm java版代码注释及详解 http://blog.sina.com.cn/s/blog_8095e51d010152xf.html
训练
package svm; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import utility.Tool; public class InitModelData { public static void main(String[] args) { init(); // check(); } //训练数据存放 static String path = "SVM/train.txt"; private static void check() { String context = Tool.inputFile(path); System.out.println(context); } private static void init() { File file = new File("train"); File[] trainList = file.listFiles(); String identity; String content = ""; for (int i = 0; i < trainList.length; i++) { try { if (!trainList[i].isFile()) { continue; } BufferedImage codeImg = ImageIO.read(trainList[i]); identity = trainList[i].getName().split("-")[0]; content += dataTemplate(identity, codeImg); } catch (IOException e) { e.printStackTrace(); } } Tool.outputFile(content, path); System.out.print(content); initModel(); } /** * 利用训练数据模板生成模型数据 */ private static void initModel() { /*"-v","20" ,"-c","500", */ String[] arg = {"-v","20" ,//模型参数设置 "svm/train.txt", //存放SVM训练模型用的数据的路径 "svm/model.txt" }; //存放SVM模型数据 // 创建一个训练对象 svm_train t = new svm_train(); try { t.main(arg); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 调用 } /** * svm数据模板 * @param charString * @param codeImg * @return */ public static String dataTemplate(String charString, BufferedImage codeImg) { String content = ""; content += charString + " "; int width = codeImg.getWidth(); for (int x = 0; x < width; x++) { for (int y = 0; y < codeImg.getHeight(); y++) { int num = x * width + y; content += num + ":"; int isBlack = Tool.isBlack(codeImg.getRGB(x, y)) ? 1 : 0; content += isBlack + " "; } } content += "\n"; return content; } }
识别
private static String svmProcess(List<BufferedImage> charImgs) { String content = ""; for (BufferedImage bufferedImage : charImgs) { content += InitModelData.dataTemplate("1", bufferedImage); } System.out.println(content); // 输出测试文件 Tool.outputFile(content, "SVM/test.txt"); return svmMatch(); } private static String svmMatch() { String[] parg = { "SVM/test.txt", // 这个是存放测试数据 "SVM/model.txt", // 调用的是训练以后的模型 "SVM/result.txt" }; // 生成的结果的文件的路径 svm_predict p = new svm_predict(); try { p.main(parg); } catch (IOException e) { e.printStackTrace(); } // 调用 String content = Tool.inputFile("SVM/result.txt"); // content把小数1.02.0 小数点和小数点后的0消除 content = content.replaceAll(".\\d", ""); return content; }
2016/4/1更新
利用encog神经网络图像识别验证码
encog搜索过没有中文资料,只能从官网给的资料学习。
http://files.cnblogs.com/files/linkarl/Encog3Java-User.pdf
学习这本书的关于图像识别部分
chapter 2 obtaining data for encog
chapter 4 constructing neural networks in java
chapter 5 propagation traing
chapter 9 using image data
import java.awt.Image; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import javax.imageio.ImageIO; import org.encog.ml.data.MLData; import org.encog.ml.data.basic.BasicMLData; import org.encog.ml.train.strategy.ResetStrategy; import org.encog.neural.networks.BasicNetwork; import org.encog.neural.networks.training.propagation.resilient.ResilientPropagation; import org.encog.persist.EncogDirectoryPersistence; import org.encog.platformspecific.j2se.TrainingDialog; import org.encog.platformspecific.j2se.data.image.ImageMLData; import org.encog.platformspecific.j2se.data.image.ImageMLDataSet; import org.encog.util.downsample.SimpleIntensityDownsample; import org.encog.util.simple.EncogUtility; public class TrainProcess { private static ImgList imgList = new ImgList(); private static ImageMLDataSet trainDataSet; private static BasicNetwork network; private static int downsampleHeight = 100; private static int downsampleWidth = 100; // RGB彩色图片 // RGBDownsample downsample=new RGBDownsample(); // 采样 private static SimpleIntensityDownsample downsample = new SimpleIntensityDownsample(); public static final String FILENAME = "encogexample.eg"; public static void main(String[] args) { inputTrain(); processNetwork(); networkConfig(); trainNetwork(); System.out.println("Saving network"); EncogDirectoryPersistence.saveObject(new File(FILENAME), network) } private static void trainNetwork() { // 图形界面 String mode = "gui"; // The number of minutes to train for. int minutes = 1; // the minimum error must achieve double strategyError = 0.1; // the number of cycles achieve the error rate int strategyCycles = 20; // Resilient弹性 final ResilientPropagation train = new ResilientPropagation(network, trainDataSet); train.addStrategy(new ResetStrategy(strategyError, strategyCycles)); // strategies // Greedy HybridStrategy ResetStrategy // SmartLearningRate SmartMomentum // StopTrainingStrategy // gui界面 TrainingDialog.trainDialog(network, trainDataSet); // 或者 console界面 // EncogUtility.trainConsole(train, network, training, minutes); System.out.println("train end"); } private static void networkConfig() { // 第一隐藏层神经元数目 int hidden1 = 30; // 第二隐藏层神经元数目 int hidden2 = 30; // true:use a hyperbolic tangent activation function. network = EncogUtility.simpleFeedForward(trainDataSet.getInputSize(), hidden1, hidden2, trainDataSet.getIdealSize(), true); System.out.println("Created network:" + network.toString()); } /** * 用训练数据设置网络 */ private static void processNetwork() { trainDataSet = new ImageMLDataSet(downsample, false, 1, 0); // processNetwork for (final ImagePair pair : imgList) { try { final MLData idealOutputData = returnIdealOutputData(pair); Image img = ImageIO.read(pair.getFile()); final ImageMLData actualInputdata = new ImageMLData(img); // The ideal output should be specified when using supervised // 1:actual input data 2:ideal output data. trainDataSet.add(actualInputdata, idealOutputData); } catch (IOException e) { e.printStackTrace(); } } trainDataSet.downsample(downsampleHeight, downsampleWidth); } /** * 设置该标识对应输出神经元为1,其余的为0的理想数据(设置情况) ideal output data. * * @param pair * @return */ private static MLData returnIdealOutputData(final ImagePair pair) { // hold the ideal output for each output neuron int outputCount = ImgList.outputCount; final MLData ideal = new BasicMLData(outputCount); int indexOutputNeuron = pair.getIndexOutputNeuron(); // corresponds to the identity of the image currently being trained // will be set to 1 for (int i = 0; i < outputCount; i++) { if (i == indexOutputNeuron) { ideal.setData(i, 1); } else { ideal.setData(i, -1); } } return ideal; } /** * 输入训练数据 */ private static void inputTrain() { File[] trainList = new File("trainData").listFiles(); for (File file : trainList) { if (!file.isFile()) { continue; } String identity = file.getName().split("-")[0]; imgList.add(file, identity); System.out.println(identity); } outputImgList(); } /** * 序列化imgList对象保存 */ private static void outputImgList() { try { ObjectOutputStream outputStream = new ObjectOutputStream( new FileOutputStream("imgList.object")); outputStream.writeObject(imgList); outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class ImgList extends ArrayList<ImagePair> implements Serializable { public final Map<String, Integer> identity2neuron = new HashMap<String, Integer>(); public final Map<Integer, String> neuron2identity = new HashMap<Integer, String>(); public static int outputCount = 0; public void add(File file, String identity) { int indexOutputNeuron = assignIdentity(identity); this.add(new ImagePair(file, indexOutputNeuron)); } private int assignIdentity(final String identity) { String lowerCase = identity.toLowerCase(); if (identity2neuron.containsKey(lowerCase)) { return identity2neuron.get(lowerCase); } final int result = outputCount++; identity2neuron.put(lowerCase, result); neuron2identity.put(result, lowerCase); return result; } }
import java.io.File; import java.io.Serializable; /** * links the image to its output neuron index number. * * @author Administrator * */ public class ImagePair implements Serializable { private final File file; private final int indexOutputNeuron; public ImagePair(File file, int indexOutputNeuron) { super(); this.file = file; this.indexOutputNeuron = indexOutputNeuron; } public File getFile() { return file; } public int getIndexOutputNeuron() { return indexOutputNeuron; } }
import java.awt.Image; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import javax.imageio.ImageIO; import org.encog.neural.networks.BasicNetwork; import org.encog.persist.EncogDirectoryPersistence; import org.encog.platformspecific.j2se.data.image.ImageMLData; import org.encog.util.downsample.SimpleIntensityDownsample; public class RecognizeProcess { public static final String FILENAME = "encogexample.eg"; private static int downsampleHeight = 20; private static int downsampleWidth = 20; private static SimpleIntensityDownsample downsample = new SimpleIntensityDownsample(); public static void main(String[] args) { ImgList imgList = inputImgList(); BasicNetwork network = (BasicNetwork) EncogDirectoryPersistence .loadObject(new File(FILENAME)); File[] files = new File("recognise").listFiles(); int num = 0; for (File file : files) { if (!file.isFile()) { continue; } try { Image img = ImageIO.read(file); ImageMLData input = new ImageMLData(img); input.downsample(downsample, false, downsampleHeight, downsampleWidth, 1, -1); final int winner = network.winner(input); String name = file.getName().split("[\\.-]")[2]; String result = imgList.neuron2identity.get(winner); System.out.println(name + " " + result); if (name.equals(result)) { num++; } } catch (IOException e) { e.printStackTrace(); } } System.out.println(num); } /** * 反序列化imgList对象 * * @return */ private static ImgList inputImgList() { ImgList imgList = null; try { ObjectInputStream inputStream = new ObjectInputStream( new FileInputStream("imgList.object")); imgList = (ImgList) inputStream.readObject(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return imgList; } }