驗證碼識別系統以及人工智慧總結 神經網路encog影象識別入門
參考資料如下:
影象處理之錯切變換適用於錯切變換小於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
Libsvmjava版程式碼註釋及詳解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; } }