Java使用Tessdata做OCR图片文字识别的详细思路

说到文字识别,目前除了用一些现成的api,大概就是 tessdatacanvas或者 ocrad等。

1、百度接口用过(可以自己去百度开发者申请,免费的),识别率吧,还可以,但也不是百分百的,但是次数使用有限制,虽然也是够用,但是被限制总是害怕超过不让用。
2、canvas的话是需要对图片做具体的处理,涉及到图片的翻转、置灰、文字间隔的设定等等,成功率很高,但是公司产品验证码是各式各样的,没办法用这种方法处理,所以暂时放弃了。
3、ocrad这个目前用过其.js版本,识别率还是比较低的,具体使用后面会再写一篇文章介绍一下的。
虽然,网上对于 Tessdata的技术介绍文章一搜一大片,但是其实小仙真正用起来的时候,还是费了点周折的。:fendou:

思路:截全图–截取元素图片–处理–识别–输出

注意:图片截取格式统一为.jpg,用png会出问题。

1、添加项目依赖

在项目的pom.xml文件中,添加以下依赖

<!--<tess4j图片识别>-->
<dependency>
	<groupId>net.java.dev.jna</groupId>
	<artifactId>jna</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>net.sourceforge.tess4j</groupId>
	<artifactId>tess4j</artifactId>
	<version>2.0.1</version>
	<exclusions>
		<exclusion>
			<groupId>com.sun.jna</groupId>
			<artifactId>jna</artifactId>
		</exclusion>
	</exclusions>
</dependency>

2、从全图中截取元素图片

// 元素截图

public static String[] elementscreenShot(WebElement element )
		throws Exception {
	WrapsDriver wrapsDriver = (WrapsDriver) element;
	long time = System.currentTimeMillis();

	// 截图整个页面
	File screen = ((TakesScreenshot) wrapsDriver.getWrappedDriver())
			.getScreenshotAs(OutputType.FILE);
	BufferedImage img = ImageIO.read(screen);
	// 获得元素的高度和宽度
	int width = element.getSize().getWidth();
	int height = element.getSize().getHeight();
	// 创建一个矩形使用上面的高度,和宽度
	Rectangle rect = new Rectangle(width, height);
	// 得到元素的坐标
	Point p = element.getLocation();
	BufferedImage dest = img.getSubimage(p.getX(), p.getY(),
			(int) rect.getWidth(), (int) rect.getHeight());
	// 存为png格式
	ImageIO.write(dest, "png", screen);
	DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
	FileSystemView fsv = FileSystemView.getFileSystemView();
	File com = fsv.getHomeDirectory(); // 这便是读取桌面路径的方法了
	String url = com.getPath() + "/test";
	File location = new File(url);
	if (!location.exists()) {
		location.mkdirs();
	}

	String imgPath = location.getAbsolutePath() + File.separator + "pic_"
			+ time + ".jpg";
	String cleanPath = location.getAbsolutePath();
	//存了原图片和清楚后图片的地址
	String[] imgpath = { imgPath, cleanPath };
	File targetFile = new File(imgPath);
	try {
		FileUtils.copyFile(screen, targetFile);
	} catch (IOException e1) {
		e1.printStackTrace();
	}
	//元素图片路径
	return imgpath;
}

3、对截取图片进行处理:灰度化、二值化、去除干扰线等

以下是图像处理的类,其中对于去除干扰线的操作还是慎用,可能会把文字也剔除掉。

public class CleanElementImage {
    /**
     *
     * @param sfile
     *            需要去噪的图像
     * @param destDir
     *            去噪后的图像保存地址
     * @throws IOException
     */
    public static void handlImage(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 = 1; y < h-1; y++){
//            for(int x = 1; x < w-1; x++){
//                boolean flag = false ;
//                if(isBlack(binaryBufferedImage.getRGB(x, y))){
//                    //左右均为空时,去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){
//                        flag = true;
//                    }
//                    //上下均为空时,去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){
//                        flag = true;
//                    }
//                    //斜上下为空时,去掉此点
//                    if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){
//                        flag = true;
//                    }
//                    if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){
//                        flag = true;
//                    }
//                    if(flag){
//                        binaryBufferedImage.setRGB(x,y,-1);
//                    }
//                }
//            }
//        }
    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;
}
}

4、准备识别的语言包

默认是英文(识别字母和数字),如果要识别中文(数字 + 中文),需要制定语言包。
语言包可以指定一个路径,有就可以了。
源码下载地址
可以下载源码,然后到下面这个路径找到语言包,把语言包放到一个路径:
例如:XXX/tessdata/下面。

tesseract.js-master.zip\tesseract.js-master\tests\assets\traineddata 

5、对图片进行识别

/**
* 图片识别
* @author wangy
* @date 2019-08-26
* @param parameter
*/
public static  String  ocrResult(WebElement element ) throws Exception {

	FileSystemView fsv = FileSystemView.getFileSystemView();
	File com=fsv.getHomeDirectory();    //这便是读取桌面路径的方法了
	String url = "";
	String os = System.getProperty("os.name");
	//识别系统,找不同的语言包路径
	if (os.indexOf("Windows") == -1) {
		url = "/opt/google/";
	} else {
		url = com.getPath();
	}
	//获取元素截图的路径
        String path[]=Screenshot.elementscreenShot(element);
        //获取未处理的截图路径
        String imgpath=path[0];
	String result = null;
	File imageFile = new File(imgpath);
	//要对图片处理
        CleanElementImage.handlImage(imageFile,path[1]);
	ITesseract instance = new Tesseract();
	//读取语言包的路径地址
	instance.setDatapath(url + File.separator + "test" + File.separator
				+ "tessdata");
	// 默认是英文(识别字母和数字),如果要识别中文(数字 + 中文),需要制定语言包,这里是数字,所以没用语言包
        // instance.setLanguage("chi_sim");
        //为了防止没截完图片就识别,做了一个简单的循环
	try{
		String ocrResult=instance.doOCR(imageFile);
		if(imageFile.exists()&&ocrResult!=""){
			result=ocrResult;
		}else {
			while(true){
				Thread.sleep(1000);
				if(imageFile.exists()&&ocrResult!=""){
					result=ocrResult;
					break;
				}
			}
		}

	}catch(TesseractException e){
		System.out.println(e.getMessage());
	}
	return result;
}

这一部分由于项目问题,贴在这里做了特殊处理,原码有一点点区别。大家使用,如果有什么问题,欢迎反馈!

6、成果

这里简单放个对照,图片将就看一下效果,识别结果大概90%以上吧:

到此这篇关于Java使用Tessdata做OCR图片文字识别的详细思路的文章就介绍到这了,更多相关java Tessdata图片文字内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java实现百度云文字识别接口代码

    本文实例为大家分享了java实现百度云文字识别的接口具体代码,供大家参考,具体内容如下 public class Images { public static String getResult() { String otherHost = "https://aip.baidubce.com/rest/2.0/ocr/v1/general"; // 本地图片路径 String str="你的本地图片路径" String filePath = "str&quo

  • java实现图片文字识别ocr

    最近在开发的时候需要识别图片中的一些文字,网上找了相关资料之后,发现google有一个离线的工具,以下为java使用的demo 在此之前,使用这个工具需要在本地安装OCR工具: 下面一个是一定要安装的离线包,建议默认安装 上面一个是中文的语言包,如果网络可以FQ的童鞋可以在安装的时候就选择语言包在线安装,有多种语言可供选择,默认只有英文的 exe安装好之后,把上面一个文件拷到安装目录下tessdata文件夹下 如C:\Program Files (x86)\Tesseract-OCR\tessd

  • 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实现百度云OCR文字识别 高精度OCR识别身份证信息

    本文为大家分享了java实现百度云OCR识别的具体代码,高精度OCR识别身份证信息,供大家参考,具体内容如下 1.通用OCR文字识别 这种OCR只能按照识别图片中的文字,且是按照行识别返回结果,精度较低. 首先引入依赖包: <dependency> <groupId>com.baidu.aip</groupId> <artifactId>java-sdk</artifactId> <version>4.6.0</version&

  • 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

  • JAVA演示阿里云图像识别API,印刷文字识别-营业执照识别

    最近有由于需要,我开始接触阿里云的云市场的印刷文字识别-营业执照识别这里我加上了官网的申请说明,只要你有阿里云账号就可以用,前500次是免费的,API说明很简陋,只能做个简单参考. 一.API介绍 JAVA示例: public static void main(String[] args) { String host = "https://dm-58.data.aliyun.com"; String path = "/rest/160601/ocr/ocr_business_

  • 识别率很高的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使用Tessdata做OCR图片文字识别的详细思路

    说到文字识别,目前除了用一些现成的api,大概就是 tessdata.canvas或者 ocrad等. 1.百度接口用过(可以自己去百度开发者申请,免费的),识别率吧,还可以,但也不是百分百的,但是次数使用有限制,虽然也是够用,但是被限制总是害怕超过不让用. 2.canvas的话是需要对图片做具体的处理,涉及到图片的翻转.置灰.文字间隔的设定等等,成功率很高,但是公司产品验证码是各式各样的,没办法用这种方法处理,所以暂时放弃了. 3.ocrad这个目前用过其.js版本,识别率还是比较低的,具体使

  • SpringBoot+OCR 实现图片文字识别

    本篇介绍的是基于百度人工智能接口的文字识别实现. 1. 注册百度云,获得AppID 此处百度云非百度云盘,而是百度智能云. 大家可进入https://cloud.baidu.com/自行注册,这里就不多说了. 接下来,我们进行应用的创建 所需接口根据实际勾选,我们暂时只需前四个即可. 2. 日常demo操作 pom.xml: <dependencies> <!-- 百度人工智能依赖 --> <!-- https://mvnrepository.com/artifact/com

  • Android实现图片文字识别

    导言 OCR,tess-two ,openCV等晕人的东西先分清,OCR,tess-two是图片文字识别,而openCV是图像识别比对,对于更复杂的图片文字识别需求可以采用百度云人工智能通用文字识别开发的SDK,准确性更高 可运行的步骤 1.添加依赖 implementation 'com.rmtheis:tess-two:8.0.0' 2.下载字体识别库(chi_sim.traineddata 中文简体,chi_tra.traineddata 中文繁体,eng.traineddata 英文库)

  • Python图像处理之图片文字识别功能(OCR)

    OCR与Tesseract介绍 将图片翻译成文字一般被称为光学文字识别(Optical Character Recognition,OCR).可以实现OCR 的底层库并不多,目前很多库都是使用共同的几个底层OCR 库,或者是在上面进行定制. Tesseract 是一个OCR 库,目前由Google 赞助(Google 也是一家以OCR 和机器学习技术闻名于世的公司).Tesseract 是目前公认最优秀.最精确的开源OCR 系统. 除 了极高的精确度,Tesseract 也具有很高的灵活性.它可

  • Python调用百度OCR实现图片文字识别的示例代码

    百度AI提供了一天50000次的免费文字识别额度,可以愉快的免费使用!下面直接上方法: 首先在百度AI创建一个应用,按照下图创建即可,创建后会获得如下: 创建后会获得如下信息: APP_ID = '******' API_KEY = '************' SECRET_KEY = '**************' 下面就是百度API包的安装,在终端cmd输入如下语句直接pip方式安装,注意是 baidu-api 哦! pip install --user baidu-aip 接下来上py

  • Python 图片文字识别的实现之PaddleOCR

    目录 项目使用 项目结构 环境部署 1.安装Anaconda,构造虚拟环境 2.依赖包下载 测试代码 参数补充 总结 前言 什么是OCR? 光学字符识别(Optical Character Recognition, OCR),是指对文本资料的图像文件进行分析识别处理,获取文字及版面信息的过程.简而言之,检测图像中的文本资料,并且识别出文本的内容. 那么有哪些应用场景呢? 其实我们日常生活中处处都有ocr的影子,比如在疫情期间身份证识别录入信息.车辆车牌号识别.自动驾驶等.我们的生活中,机器学习已

  • Python3一行代码实现图片文字识别的示例

    自学Python3第5天,今天突发奇想,想用Python识别图片里的文字.没想到Python实现图片文字识别这么简单,只需要一行代码就能搞定 from PIL import Image import pytesseract #上面都是导包,只需要下面这一行就能实现图片文字识别 text=pytesseract.image_to_string(Image.open('denggao.jpeg'),lang='chi_sim') print(text) 我们以识别诗词为例 下面是我们要识别的图片 先

  • C# SDK实现百度云OCR的文字识别功能

    最近项目要用到文字识别功能,所以花了几天时间整理了一下.今天就记录一下用C#实现文字识别的过程. 一.登录百度云进入控制台界面,创建应用获取秘钥 1.在百度云的产品里找到文字识别 2.找到通用文字识别点击立即使用.然后进入控制台.(这里可能会进入购买页面,可以直接购买免费版) 3.在控制台点击创建应用.然后填写相关内容就可以获得应用秘钥. 二.获得C#SDK 1.百度云C#SDK下载:下载地址 2.可以到官网直接下载:下载链接 三.将C#SDK导入VS 找到解决方案里的引用目录,右键,选择第一个

  • java实现腾讯ocr图片识别接口调用

    最近开发了一个拍车牌识别车牌号的功能,主要调用了腾讯的ocr车牌识别接口,直接上代码: 首先生成签名以及读取配置的工具类: package com.weaver.formmodel.integration.ocr; import java.util.Random; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import weaver.general.Base64; public class SignUtil

随机推荐