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

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

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

下面是核心代码:

package com.zhy.test; 

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");
 /**
  * 文件位置我防止在,项目同一路径
  */
 private String tessPath = new File("tesseract").getAbsolutePath(); 

 /**
  * @param imageFile
  *   传入的图像文件
  * @param imageFormat
  *   传入的图像格式
  * @return 识别后的字符串
  */
 public String recognizeText(File imageFile) throws Exception
 {
  /**
   * 设置输出文件的保存的文件目录
   */
  File outputFile = new File(imageFile.getParentFile(), "output"); 

  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("chi_sim");
  cmd.add("eng"); 

  ProcessBuilder pb = new ProcessBuilder();
  /**
   *Sets this process builder's working directory.
   */
  pb.directory(imageFile.getParentFile());
  cmd.set(1, imageFile.getName());
  pb.command(cmd);
  pb.redirectErrorStream(true);
  Process process = pb.start();
  // tesseract.exe 1.jpg 1 -l chi_sim
  // Runtime.getRuntime().exec("tesseract.exe 1.jpg 1 -l chi_sim");
  /**
   * the exit value of the process. By convention, 0 indicates normal
   * termination.
   */
//  System.out.println(cmd.toString());
  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*", "");
 }
}

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

测试代码:

package com.zhy.test; 

import java.io.File; 

public class Test
{
 public static void main(String[] args)
 {
  try
  { 

   File testDataDir = new File("testdata");
   System.out.println(testDataDir.listFiles().length);
   int i = 0 ;
   for(File file :testDataDir.listFiles())
   {
    i++ ;
    String recognizeText = new OCRHelper().recognizeText(file);
    System.out.print(recognizeText+"\t"); 

    if( i % 5 == 0 )
    {
     System.out.println();
    }
   } 

  } catch (Exception e)
  {
   e.printStackTrace();
  } 

 }
}

输出结果:

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

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

来张特写:

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

代码:

package com.zhy.test; 

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException; 

import javax.imageio.ImageIO; 

public class ClearImageHelper
{ 

 public static void main(String[] args) throws IOException
 { 

  File testDataDir = new File("testdata");
  final String destDir = testDataDir.getAbsolutePath()+"/tmp";
  for (File file : testDataDir.listFiles())
  {
   cleanImage(file, destDir);
  } 

 } 

 /**
  *
  * @param sfile
  *   需要去噪的图像
  * @param destDir
  *   去噪后的图像保存地址
  * @throws IOException
  */
 public static void cleanImage(File sfile, String destDir)
   throws IOException
 {
  File destF = new File(destDir);
  if (!destF.exists())
  {
   destF.mkdirs();
  } 

  BufferedImage bufferedImage = ImageIO.read(sfile);
  int h = bufferedImage.getHeight();
  int w = bufferedImage.getWidth(); 

  // 灰度化
  int[][] gray = new int[w][h];
  for (int x = 0; x < w; x++)
  {
   for (int y = 0; y < h; y++)
   {
    int argb = bufferedImage.getRGB(x, y);
    // 图像加亮(调整亮度识别率非常高)
    int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
    int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
    int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
    if (r >= 255)
    {
     r = 255;
    }
    if (g >= 255)
    {
     g = 255;
    }
    if (b >= 255)
    {
     b = 255;
    }
    gray[x][y] = (int) Math
      .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
        * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
   }
  } 

  // 二值化
  int threshold = ostu(gray, w, h);
  BufferedImage binaryBufferedImage = new BufferedImage(w, h,
    BufferedImage.TYPE_BYTE_BINARY);
  for (int x = 0; x < w; x++)
  {
   for (int y = 0; y < h; y++)
   {
    if (gray[x][y] > threshold)
    {
     gray[x][y] |= 0x00FFFF;
    } else
    {
     gray[x][y] &= 0xFF0000;
    }
    binaryBufferedImage.setRGB(x, y, gray[x][y]);
   }
  } 

  // 矩阵打印
  for (int y = 0; y < h; y++)
  {
   for (int x = 0; x < w; x++)
   {
    if (isBlack(binaryBufferedImage.getRGB(x, y)))
    {
     System.out.print("*");
    } else
    {
     System.out.print(" ");
    }
   }
   System.out.println();
  } 

  ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
    .getName()));
 } 

 public static boolean isBlack(int colorInt)
 {
  Color color = new Color(colorInt);
  if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
  {
   return true;
  }
  return false;
 } 

 public static boolean isWhite(int colorInt)
 {
  Color color = new Color(colorInt);
  if (color.getRed() + color.getGreen() + color.getBlue() > 300)
  {
   return true;
  }
  return false;
 } 

 public static int isBlackOrWhite(int colorInt)
 {
  if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730)
  {
   return 1;
  }
  return 0;
 } 

 public static int getColorBright(int colorInt)
 {
  Color color = new Color(colorInt);
  return color.getRed() + color.getGreen() + color.getBlue();
 } 

 public static int ostu(int[][] gray, int w, int h)
 {
  int[] histData = new int[w * h];
  // Calculate histogram
  for (int x = 0; x < w; x++)
  {
   for (int y = 0; y < h; y++)
   {
    int red = 0xFF & gray[x][y];
    histData[red]++;
   }
  } 

  // Total number of pixels
  int total = w * h; 

  float sum = 0;
  for (int t = 0; t < 256; t++)
   sum += t * histData[t]; 

  float sumB = 0;
  int wB = 0;
  int wF = 0; 

  float varMax = 0;
  int threshold = 0; 

  for (int t = 0; t < 256; t++)
  {
   wB += histData[t]; // Weight Background
   if (wB == 0)
    continue; 

   wF = total - wB; // Weight Foreground
   if (wF == 0)
    break; 

   sumB += (float) (t * histData[t]); 

   float mB = sumB / wB; // Mean Background
   float mF = (sum - sumB) / wF; // Mean Foreground 

   // Calculate Between Class Variance
   float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF); 

   // Check if new maximum found
   if (varBetween > varMax)
   {
    varMax = varBetween;
    threshold = t;
   }
  } 

  return threshold;
 }
}

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

(0)

相关推荐

  • Java基于直方图应用的相似图片识别实例

    本文实例讲述了Java实现基于直方图应用的相似图片识别,是非常实用的技巧.分享给大家供大家参考.具体分析如下: 一.算法概述: 首先对源图像与要筛选的图像进行直方图数据采集,对采集的各自图像直方图进行归一化再使用巴氏系数算法对直方图数据进行计算,最终得出图像相似度值,其值范围在[0, 1]之间 0表示极其不同,1表示极其相似(相同). 二.算法步骤详解: 大致可以分为两步,根据源图像与候选图像的像素数据,生成各自直方图数据.第二步:使用第一步输出的直方图结果,运用巴氏系数(Bhattachary

  • 识别率很高的java文字识别技术

    java文字识别程序的关键是寻找一个可以调用的OCR引擎.tesseract-ocr就是一个这样的OCR引擎,在1985年到1995年由HP实验室开发,现在在Google.tesseract-ocr 3.0发布,支持中文.不过tesseract-ocr 3.0不是图形化界面的客户端,别人写的FreeOCR图形化客户端还不支持导入新的 3.0 traineddata.但这标志着,现在有自由的中文OCR软件了. java中使用tesseract-ocr3.01的步骤如下: 1.下载安装tessera

  • java网络编程之识别示例 获取主机网络接口列表

    获取主机地址信息 在Java中我们使用InetAddress类来代表目标网络地址,包括主机名和数字类型的地址信息,并且InetAddress的实例是不可变的,每个实例始终指向一个地址.InetAddress类包含两个子类,分别对应两个IP地址的版本: 复制代码 代码如下: Inet4AddressInet6Address 我们通过前面的笔记可以知道:IP地址实际上是分配给主机与网络之间的连接,而不是主机本身,NetworkInterface类提供了访问主机所有接口的信息的功能.下面我们通过一个简

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

    接着上一篇OCR所说的,上一篇给大家介绍了tesseract 在命令行的简单用法,当然了要继承到我们的程序中,还是需要代码实现的,下面给大家分享下Java实现的例子. 拿代码扫描上面的图片,然后输出结果.主要思想就是利用Java调用系统任务. 下面是核心代码: package com.zhy.test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.i

  • JCrop+ajaxUpload 图像切割上传的实例代码

    先给大家展示下效果图: 页面代码 里面用户的uuid是写死的test <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE> <html lang="en"> <head> <title>用户头像剪裁</title>

  • Java获取彩色图像中的主色彩的实例代码

    本文讲述了Java获取彩色图像中的主色彩的实例代码.分享给大家供大家参考,具体如下: 一:基本思路 对于一张RGB色彩空间的彩色图像,很多时间我们想通过程序获得该图像有几种主要的色彩,但是对一般图像来说,在色彩交界处都是通过像素混合来实现自然过渡,所以直接扫描图像的像素值,得到的不同颜色值可能多达上百中,而实际上图像可能只有3-4种的主要色彩,如何去掉那些混合颜色,准确提取出来这3-4中的主色彩,根据一般图像的特征,图像在不同色彩的边界处混合不同的颜色值,此可以视为图像的边缘特性之一,因此可以根

  • java 对文件夹目录进行深度遍历实例代码

    java 对文件夹目录进行深度遍历实例代码 1.题目 对指定目录进行所有内容的列出(包含子目录中的内容),也可以理解为对目录进行深度遍历. 2.解题思想 从电脑中获取文件目录,建立函数对其遍历,在这个函数中需要对该目录中的每个文件进行判断,如果文件还是目录,则调用函数本身继续对其进行遍历,如果文件不是目录,则直接输出文件名.为了加强显示的效果,我们还可以建立一个getSpace函数,对其进行缩进. 需要注意的是,不要直接遍历C盘的内容,其目录层次太深,含有太多的系统级文件,容易返回为空,导致空指

  • Java发送带html标签内容的邮件实例代码

    如下所示: package test; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import javax.mail.Session; import javax.mail.MessagingException; import javax.mail.Transport; public class

  • java使用RandomAccessFile类基于指针读写文件实例代码

    java API中提供了一个基于指针操作实现对文件随机访问操作的类,该类就是RandomAccessFile类,该类不同于其他很多基于流方式读写文件的类.它直接继承自Object. public class RandomAccessFile extends Objectimplements DataOutput, DataInput, Closeable{...} 1.使用该类时可以指定对要操作文件的读写模式. 第一种模式是只读模式,第二种模式是读写模式.在创建该类实例时指定. @Test pu

  • java 使用memcached以及spring 配置memcached完整实例代码

    Memcached是一个高性能的分布式内存对象缓存系统,本文介绍了java 使用memcached以及spring 配置memcached完整实例代码,分享给大家 本文涉及以下内容: 1,要使用的jar包 2,java 使用memcached 3,spring 配置memcached 导入jar java_memcached-release_2.6.6.jar commons-pool-1.5.6.jar slf4j-api-1.6.1.jar slf4j-simple-1.6.1.jar 示例

  • java 实现截取字符串并按字节分别输出实例代码

    java 实现截取字符串并按字节分别输出实例代码 前言: 请编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串.但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输入"我ABC汉DEF"6,应该输出"我ABC",而不是"我ABC"+"汉"字的半个. 2.解析思想 本题容易产生困惑的是中文字符和英文字符如何处理,在这里需要考虑汉字和英文字符的占用字节

  • java公众平台通用接口工具类HttpConnectUtil实例代码

    实例如下: package com.common.util; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import

  • java把excel内容上传到mysql实例代码

    mysql 表列名 num1,num2,num3,num4,num5,num6 表名Excle 上传的方法 package com.web.connection; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import org.apache.commons.logging.Log; import org.apache.commons.loggi

随机推荐