程序员开发实例大全宝库

网站首页 > 编程文章 正文

Java OCR tesseract 图像智能字符识别技术 Java代码实现

zazugpt 2024-08-31 05:12:45 编程文章 18 ℃ 0 评论

给大家介绍了tesseract 在命令行的简单用法,当然了要继承到我们的程序中,还是需要代码实现的,下面给大家分享下java实现的例子。

拿代码扫描上面的图片,然后输出结果。主要思想就是利用Java调用系统任务。

下面是核心代码:


  1. package com.zhy.test;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.InputStreamReader;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import org.jdesktop.swingx.util.OS;
  9. public class OCRHelper
  10. {
  11. private final String LANG_OPTION = "-l";
  12. private final String EOL = System.getProperty("line.separator");
  13. /**
  14. * 文件位置我防止在,项目同一路径
  15. */
  16. private String tessPath = new File("tesseract").getAbsolutePath();
  17. /**
  18. * @param imageFile
  19. * 传入的图像文件
  20. * @param imageFormat
  21. * 传入的图像格式
  22. * @return 识别后的字符串
  23. */
  24. public String recognizeText(File imageFile) throws Exception
  25. {
  26. /**
  27. * 设置输出文件的保存的文件目录
  28. */
  29. File outputFile = new File(imageFile.getParentFile(), "output");
  30. StringBuffer strB = new StringBuffer();
  31. List<String> cmd = new ArrayList<String>();
  32. if (OS.isWindowsXP())
  33. {
  34. cmd.add(tessPath + "\\tesseract");
  35. } else if (OS.isLinux())
  36. {
  37. cmd.add("tesseract");
  38. } else
  39. {
  40. cmd.add(tessPath + "\\tesseract");
  41. }
  42. cmd.add("");
  43. cmd.add(outputFile.getName());
  44. cmd.add(LANG_OPTION);
  45. //cmd.add("chi_sim");
  46. cmd.add("eng");
  47. ProcessBuilder pb = new ProcessBuilder();
  48. /**
  49. *Sets this process builder's working directory.
  50. */
  51. pb.directory(imageFile.getParentFile());
  52. cmd.set(1, imageFile.getName());
  53. pb.command(cmd);
  54. pb.redirectErrorStream(true);
  55. Process process = pb.start();
  56. // tesseract.exe 1.jpg 1 -l chi_sim
  57. // Runtime.getRuntime().exec("tesseract.exe 1.jpg 1 -l chi_sim");
  58. /**
  59. * the exit value of the process. By convention, 0 indicates normal
  60. * termination.
  61. */
  62. //System.out.println(cmd.toString());
  63. int w = process.waitFor();
  64. if (w == 0)// 0代表正常退出
  65. {
  66. BufferedReader in = new BufferedReader(new InputStreamReader(
  67. new FileInputStream(outputFile.getAbsolutePath() + ".txt"),
  68. "UTF-8"));
  69. String str;
  70. while ((str = in.readLine()) != null)
  71. {
  72. strB.append(str).append(EOL);
  73. }
  74. in.close();
  75. } else
  76. {
  77. String msg;
  78. switch (w)
  79. {
  80. case 1:
  81. msg = "Errors accessing files. There may be spaces in your image's filename.";
  82. break;
  83. case 29:
  84. msg = "Cannot recognize the image or its selected region.";
  85. break;
  86. case 31:
  87. msg = "Unsupported image format.";
  88. break;
  89. default:
  90. msg = "Errors occurred.";
  91. }
  92. throw new RuntimeException(msg);
  93. }
  94. new File(outputFile.getAbsolutePath() + ".txt").delete();
  95. return strB.toString().replaceAll("\\s*", "");
  96. }
  97. }

代码很简单,中间那部分ProcessBuilder其实就类似Runtime.getRuntime().exec("tesseract.exe 1.jpg 1 -l chi_sim"),大家不习惯的可以使用Runtime。测试代码:


  1. package com.zhy.test;
  2. import java.io.File;
  3. public class Test
  4. {
  5. public static void main(String[] args)
  6. {
  7. try
  8. {
  9. File testDataDir = new File("testdata");
  10. System.out.println(testDataDir.listFiles().length);
  11. int i = 0 ;
  12. for(File file :testDataDir.listFiles())
  13. {
  14. i++ ;
  15. String recognizeText = new OCRHelper().recognizeText(file);
  16. System.out.print(recognizeText+"\t");
  17. if( i % 5 == 0 )
  18. {
  19. System.out.println();
  20. }
  21. }
  22. } catch (Exception e)
  23. {
  24. e.printStackTrace();
  25. }
  26. }
  27. }

输出结果:

对比第一张图片,是不是很完美~哈哈 ,当然了如果你只需要实现验证码的读写,那么上面就足够了。下面继续普及图像处理的知识。

----------------------------------------我的分割线-----------------------------------

当然了,有时候图片被扭曲或者模糊的很厉害,很不容易识别,所以下面我给大家介绍一个去噪的辅助类,绝对碉堡了,先看下效果图。

来张特写:

一个类,不依赖任何jar,把图像中的干扰线消灭了,是不是很给力,然后再拿这样的图片去识别,会不会效果更好呢,嘿嘿,大家自己实验~

代码:


  1. package com.zhy.test;
  2. import java.awt.Color;
  3. import java.awt.image.BufferedImage;
  4. import java.io.File;
  5. import java.io.IOException;
  6. import javax.imageio.ImageIO;
  7. public class ClearImageHelper
  8. {
  9. public static void main(String[] args) throws IOException
  10. {
  11. File testDataDir = new File("testdata");
  12. final String destDir = testDataDir.getAbsolutePath()+"/tmp";
  13. for (File file : testDataDir.listFiles())
  14. {
  15. cleanImage(file, destDir);
  16. }
  17. }
  18. /**
  19. *
  20. * @param sfile
  21. * 需要去噪的图像
  22. * @param destDir
  23. * 去噪后的图像保存地址
  24. * @throws IOException
  25. */
  26. public static void cleanImage(File sfile, String destDir)
  27. throws IOException
  28. {
  29. File destF = new File(destDir);
  30. if (!destF.exists())
  31. {
  32. destF.mkdirs();
  33. }
  34. BufferedImage bufferedImage = ImageIO.read(sfile);
  35. int h = bufferedImage.getHeight();
  36. int w = bufferedImage.getWidth();
  37. // 灰度化
  38. int[][] gray = new int[w][h];
  39. for (int x = 0; x < w; x++)
  40. {
  41. for (int y = 0; y < h; y++)
  42. {
  43. int argb = bufferedImage.getRGB(x, y);
  44. // 图像加亮(调整亮度识别率非常高)
  45. int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
  46. int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
  47. int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
  48. if (r >= 255)
  49. {
  50. r = 255;
  51. }
  52. if (g >= 255)
  53. {
  54. g = 255;
  55. }
  56. if (b >= 255)
  57. {
  58. b = 255;
  59. }
  60. gray[x][y] = (int) Math
  61. .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
  62. * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
  63. }
  64. }
  65. // 二值化
  66. int threshold = ostu(gray, w, h);
  67. BufferedImage binaryBufferedImage = new BufferedImage(w, h,
  68. BufferedImage.TYPE_BYTE_BINARY);
  69. for (int x = 0; x < w; x++)
  70. {
  71. for (int y = 0; y < h; y++)
  72. {
  73. if (gray[x][y] > threshold)
  74. {
  75. gray[x][y] |= 0x00FFFF;
  76. } else
  77. {
  78. gray[x][y] &= 0xFF0000;
  79. }
  80. binaryBufferedImage.setRGB(x, y, gray[x][y]);
  81. }
  82. }
  83. // 矩阵打印
  84. for (int y = 0; y < h; y++)
  85. {
  86. for (int x = 0; x < w; x++)
  87. {
  88. if (isBlack(binaryBufferedImage.getRGB(x, y)))
  89. {
  90. System.out.print("*");
  91. } else
  92. {
  93. System.out.print(" ");
  94. }
  95. }
  96. System.out.println();
  97. }
  98. ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
  99. .getName()));
  100. }
  101. public static boolean isBlack(int colorInt)
  102. {
  103. Color color = new Color(colorInt);
  104. if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
  105. {
  106. return true;
  107. }
  108. return false;
  109. }
  110. public static boolean isWhite(int colorInt)
  111. {
  112. Color color = new Color(colorInt);
  113. if (color.getRed() + color.getGreen() + color.getBlue() > 300)
  114. {
  115. return true;
  116. }
  117. return false;
  118. }
  119. public static int isBlackOrWhite(int colorInt)
  120. {
  121. if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730)
  122. {
  123. return 1;
  124. }
  125. return 0;
  126. }
  127. public static int getColorBright(int colorInt)
  128. {
  129. Color color = new Color(colorInt);
  130. return color.getRed() + color.getGreen() + color.getBlue();
  131. }
  132. public static int ostu(int[][] gray, int w, int h)
  133. {
  134. int[] histData = new int[w * h];
  135. // Calculate histogram
  136. for (int x = 0; x < w; x++)
  137. {
  138. for (int y = 0; y < h; y++)
  139. {
  140. int red = 0xFF & gray[x][y];
  141. histData[red]++;
  142. }
  143. }
  144. // Total number of pixels
  145. int total = w * h;
  146. float sum = 0;
  147. for (int t = 0; t < 256; t++)
  148. sum += t * histData[t];
  149. float sumB = 0;
  150. int wB = 0;
  151. int wF = 0;
  152. float varMax = 0;
  153. int threshold = 0;
  154. for (int t = 0; t < 256; t++)
  155. {
  156. wB += histData[t]; // Weight Background
  157. if (wB == 0)
  158. continue;
  159. wF = total - wB; // Weight Foreground
  160. if (wF == 0)
  161. break;
  162. sumB += (float) (t * histData[t]);
  163. float mB = sumB / wB; // Mean Background
  164. float mF = (sum - sumB) / wF; // Mean Foreground
  165. // Calculate Between Class Variance
  166. float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
  167. // Check if new maximum found
  168. if (varBetween > varMax)
  169. {
  170. varMax = varBetween;
  171. threshold = t;
  172. }
  173. }
  174. return threshold;
  175. }
  176. }

好了,就到这里。如果这篇文章对你有用,赞一个吧~

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表