查看: 1717|回复: 0

[Java代码] JavaSE图像验证码简单识别程序详解

发表于 2018-3-2 08:05:32

本文为大家分享了JavaSE图像验证码简单识别程序,供大家参考,具体内容如下

首先你应该对图片进行样本采集,然后将样本进行灰度处理,也就是变成黑白两色。

然后你就可以使用该类,对目标文件进行分析。具体怎么实现我觉得这个类非常清楚,就是将样本从左都有这么横向移动,匹配出一个合适的就将坐标调整到下个位置。

此程序已是3年多前写的,后来没有在深入写下去,图像识别一个很深的领域,得需要很深的数学功底跟思维能力,这个java的程序效率不高,也不能识别变形的或者拉伸的图片,但在那个年代,已经足够用了,大家如果有更好的开源的图像识别代码,请务必来信交流:)

  1. /**
  2. * 图片解析引擎,适合做网站验证码的分析。
  3. * 首先必须载入样品,解析器将从左到右横向扫描,发现于样本的就自动记录。
  4. * 当然本程序不适合样本不是唯一的,也就是说要识别的图片被缩放或者坐标变动和变形本程序无法进行这样的识别。
  5. * 如果图片中的颜色变化非常大,此程序可能会有问题,当然了你可以选择一个标准的值做为转换成0,1矩阵的标准。
  6. *
  7. * 样本的制作:请将样本转换成灰度模式,只含有两色最好,当然了不转换我也帮你转换了。
  8. *
  9. */
  10. import java.awt.Image;
  11. import java.awt.image.BufferedImage;
  12. import java.io.File;
  13. import java.util.ArrayList;
  14. import java.util.Iterator;
  15. import java.util.List;
  16. import javax.imageio.ImageIO;
  17. public class ImageParser {
  18. // ------------------------------------------------------------ Private Data
  19. // 样本的矩阵
  20. private static List swatches = null;
  21. // 样本的值
  22. private static List swatcheValues = null;
  23. // 图片文件的矩阵化
  24. private byte[][] targetColors;
  25. // ------------------------------------------------------------ Test main method
  26. public static void main(String[] args) {
  27. // 加入样本与其样本对应的数值
  28. String[] files = new String[10];
  29. String[] values = new String[10];
  30. for (int i = 0; i < files.length; i++){
  31. files[i] = "D:/workspace/SZXClientAPP/res/" + i + ".jpg";
  32. values[i] = String.valueOf(i);
  33. }
  34. ImageParser parse = new ImageParser(files, values);
  35. long startime = System.currentTimeMillis();
  36. try {
  37. // 解析图片
  38. System.out.println(parse.parseValue("D:/workspace/SZXClientAPP/res/ValidateNum"));
  39. long sincetime = System.currentTimeMillis();
  40. System.out.println("所花时间 = " + (sincetime - startime));
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. // ------------------------------------------------------------ Constructors
  46. /**
  47. * 载入所有样本路径与其样本对应的数值
  48. *
  49. * @param files
  50. */
  51. public ImageParser(String[] files, String[] values) {
  52. // 只允许样本创建一次即可
  53. if (swatches == null && swatcheValues == null) {
  54. int fileslength = files.length;
  55. int valueslength = values.length;
  56. if(fileslength != valueslength){
  57. System.out.println("样本文件与样本数值不匹配!请重新设置!");
  58. return;
  59. }
  60. swatches = new ArrayList(fileslength);
  61. swatcheValues = new ArrayList(valueslength);
  62. int i = 0;
  63. try {
  64. for (; i < files.length; i++) {
  65. swatches.add(imageToMatrix(files[i]));
  66. swatcheValues.add(i, values[i]);
  67. }
  68. } catch (Exception e) {
  69. System.out.println(files[i] + " can not be parsed");
  70. e.printStackTrace();
  71. }
  72. }
  73. }
  74. public ImageParser() {
  75. super();
  76. if (swatches == null || swatcheValues == null) {
  77. System.out.println("您未载入样本,请先载入样本!");
  78. }
  79. }
  80. /**
  81. * 解析图片的值
  82. *
  83. * @param parseFilePath
  84. * 给出图片路径
  85. * @return 返回字符串
  86. * @throws Exception
  87. */
  88. public String parseValue(String parseFilePath) throws Exception {
  89. StringBuffer result = new StringBuffer();
  90. targetColors = imageToMatrix(parseFilePath);
  91. // printMatrix(targetColors);
  92. int height = targetColors.length;
  93. int targetWidth = targetColors[0].length;
  94. int width = 0;
  95. Iterator it = swatches.iterator();
  96. while (it.hasNext()) {
  97. byte[][] bytes = (byte[][]) it.next();
  98. int templen = bytes[0].length;
  99. if (templen > width)
  100. width = templen;
  101. }
  102. // System.out.println("MaxWidth = " + width);
  103. // System.out.println("MaxHeight = " + height);
  104. int xTag = 0;
  105. while ((xTag + width) < targetWidth) {
  106. cout: {
  107. Iterator itx = swatches.iterator();
  108. int i = 0;
  109. while (itx.hasNext()) {
  110. byte[][] bytes = (byte[][]) itx.next();
  111. byte[][] temp = splitMatrix(targetColors, xTag, 0, width, height);
  112. // System.out.println(i++);
  113. if (isMatrixInBigMatrix(bytes, temp)) {
  114. xTag += width;
  115. // System.out.println("new maxtrix: ");
  116. // printMatrix(temp);
  117. result.append(swatcheValues.get(i));
  118. break cout;
  119. }
  120. i++;
  121. }
  122. xTag++;
  123. }
  124. }
  125. return result.toString();
  126. }
  127. // ------------------------------------------------------------ Private methods
  128. /**
  129. * 判断一个矩阵是否在另外的矩阵中
  130. *
  131. * @param source
  132. * 源矩阵
  133. * @param bigMatrix
  134. * 大的矩阵
  135. * @return 如果存在就返回 true
  136. */
  137. private static final boolean isMatrixInBigMatrix(byte[][] source, byte[][] bigMatrix) {
  138. if (source == bigMatrix)
  139. return true;
  140. if (source == null || bigMatrix == null)
  141. return false;
  142. if (source.length > bigMatrix.length)
  143. return false;
  144. try {
  145. for (int i = 0; i < source.length; i++) {
  146. if (source[i].length > bigMatrix[i].length)
  147. return false;
  148. }
  149. } catch (ArrayIndexOutOfBoundsException e) {
  150. return false;
  151. }
  152. int height = source.length;
  153. int width = source[0].length;
  154. int x = 0, y = 0;
  155. int i = 0, j = 0;
  156. int count = 0;
  157. int comparecount = height * width;
  158. for (; i < bigMatrix.length - height + 1; i++) {
  159. for (j = 0; j < bigMatrix[i].length - width + 1; j++) {
  160. cout: {
  161. x = 0;
  162. count = 0;
  163. for (int k = i; k < height + i; k++) {
  164. y = 0;
  165. for (int l = j; l < width + j; l++) {
  166. // System.out.println("bytes[" + x + "][" + y + "]"
  167. // + " = " + source[x][y] + ", " + "other["
  168. // + k + "][" + l + "] = " + bigMatrix[k][l]);
  169. if ((source[x][y] & bigMatrix[k][l]) == source[x][y]) {
  170. count++;
  171. } else
  172. break cout;
  173. y++;
  174. }
  175. x++;
  176. }
  177. // System.out.println("count = " + count);
  178. if (count == comparecount)
  179. return true;
  180. }
  181. }
  182. }
  183. return false;
  184. }
  185. /**
  186. * 切割矩阵
  187. *
  188. * @param source
  189. * 源矩阵
  190. * @param x
  191. * X坐标
  192. * @param y
  193. * Y坐标
  194. * @param width
  195. * 矩阵的宽度
  196. * @param height
  197. * 矩阵的高度
  198. * @return 切割后的矩阵
  199. */
  200. private static final byte[][] splitMatrix(byte[][] source, int x, int y, int width, int height) {
  201. byte[][] resultbytes = new byte[height][width];
  202. for (int i = y, k = 0; i < height + y; i++, k++) {
  203. for (int j = x, l = 0; j < width + x; j++, l++) {
  204. resultbytes[k][l] = source[i][j];
  205. // System.out.println("source[" + i + "][" + j + "]" + " = " +
  206. // source[i][j] + ", " + "resultbytes["
  207. // + k + "][" + l + "] = " + resultbytes[k][l]);
  208. }
  209. }
  210. return resultbytes;
  211. }
  212. /**
  213. * 图片转换成矩阵数组
  214. *
  215. * @param filePath
  216. * 文件路径
  217. * @return 返回矩阵
  218. * @throws Exception
  219. * 可能会抛出异常
  220. */
  221. private byte[][] imageToMatrix(String filePath) throws Exception {
  222. // 读入文件
  223. Image image = ImageIO.read(new File(filePath));
  224. int w = image.getWidth(null);
  225. int h = image.getHeight(null);
  226. BufferedImage src = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  227. src.getGraphics().drawImage(image, 0, 0, null);
  228. byte[][] colors = new byte[h][w];
  229. for (int i = 0; i < h; i++) {
  230. for (int j = 0; j < w; j++) {
  231. int rgb = src.getRGB(j, i);
  232. // 像素进行灰度处理
  233. String sRed = Integer.toHexString(rgb).substring(2, 4);
  234. String sGreen = Integer.toHexString(rgb).substring(4, 6);
  235. String sBlank = Integer.toHexString(rgb).substring(6, 8);
  236. long ired = Math.round((Integer.parseInt(sRed, 16) * 0.3 + 0.5d));
  237. long igreen = Math.round((Integer.parseInt(sGreen, 16) * 0.59 + 0.5d));
  238. long iblank = Math.round((Integer.parseInt(sBlank, 16) * 0.11 + 0.5d));
  239. long al = ired + igreen + iblank;
  240. // if (al > 127)
  241. // System.out.print(" " + " ");
  242. // else
  243. // System.out.print(" " + "1");
  244. // System.out.print(" " + (tempint > = maxint ? 0 : 1));
  245. // System.out.println("tempInt = " + tempint);
  246. /* 将图像转换成0,1 */
  247. // 此处的值可以将来修改成你所需要判断的值
  248. colors[i][j] = (byte) (al > 127 ? 0 : 1);
  249. }
  250. // System.out.println();
  251. }
  252. return colors;
  253. }
  254. /**
  255. * 打印矩阵
  256. *
  257. * @param matrix
  258. */
  259. private static final void printMatrix(byte[][] matrix) {
  260. for (int i = 0; i < matrix.length; i++) {
  261. for (int j = 0; j < matrix[i].length; j++) {
  262. if (matrix[i][j] == 0)
  263. System.out.print(" ");
  264. else
  265. System.out.print(" 1");
  266. }
  267. System.out.println();
  268. }
  269. }
  270. }
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报