当前位置:   article > 正文

JAVA用tess4j识别复杂的验证码,自定义字库,计算题验证码,jTessBoxEditor,tess4j,验证码识别_java 识别复杂验证码

java 识别复杂验证码

场景

爬虫爬取数据的过程中可能会遇到各种验证码,导致爬虫无法继续。本文讲解如果在java中如何使用tess4j识别图片中的文本、自定义模型。

JAVA用tess4j识别文本

MAVEN依赖

<dependency>
    <groupId>net.sourceforge.tess4j</groupId>
    <artifactId>tess4j</artifactId>
    <version>5.6.0</version>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.15</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

等下需要用到脚本引擎计算表达式

traineddata文件下载

github下载地址:https://github.com/tesseract-ocr/tessdata

常用的语言及其traineddata文件对照表

语言文件
简体中文chi_sim.traineddata
Englisheng.traineddata

识别英文

代码

package com.beiyoufamily;

import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.io.File;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2023/6/3 15:25
 */

public class EnglishIdentification {

    public static void main(String[] args) throws TesseractException {
        //要是别的验证码图片
        File captchaImageFile = new File("C:/Files/images/captcha/test/English.png");
        //创建tesseract对象
        Tesseract tesseract = new Tesseract();
        //设置traineddata文件目录
        tesseract.setDatapath("C:/Files/images/captcha/traineddata");
        //设置语言(不需要写扩展名)
        tesseract.setLanguage("eng");
        String result = tesseract.doOCR(captchaImageFile);
        System.out.println(result);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

运行结果:在这里插入图片描述

标准的英文字符识别率非常高

识别中文

代码

package com.beiyoufamily;

import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.io.File;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2023/6/3 15:25
 */

public class ChineseIdentification {

    public static void main(String[] args) throws TesseractException {
        //要是别的验证码图片
        File captchaImageFile = new File("C:/Files/images/captcha/test/Chinese.png");
        //创建tesseract对象
        Tesseract tesseract = new Tesseract();
        //设置traineddata文件目录
        tesseract.setDatapath("C:/Files/images/captcha/traineddata");
        //设置语言(不需要写扩展名)
        tesseract.setLanguage("chi_sim");
        String result = tesseract.doOCR(captchaImageFile);
        System.out.println(result);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

运行结果
在这里插入图片描述

看了一下识别结果,不能说不太准确,只能说是非常糟糕。总所周知tess4j除了对中文不太友好以外,其他语言都挺准确的。

JAVA用tess4j识别验证码

常见验证码的类型

  • 数字类型
    在这里插入图片描述

  • 滑块验证码
    在这里插入图片描述

  • 计算题
    请添加图片描述

识别

上述验证码中,第一种数字类型的比较简单,只需要对图像做二值化之后进行识别,准确率还是很高的,第二种滑块的验证码比较恶心,今天暂时不讨论它;今天讨论的是第三种,计算题验证码(方法同样适用于第一种验证码)。

代码

package com.beiyoufamily;

import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.io.File;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2023/6/3 15:09
 */

public class CaptchaIdentification {

    public static void main(String[] args) throws TesseractException {
        //要是别的验证码图片
        File captchaImageFile = new File("C:/Files/images/captcha/test/captcha.png");
        //创建tesseract对象
        Tesseract tesseract = new Tesseract();
        //设置traineddata文件目录
        tesseract.setDatapath("C:/Files/images/captcha/traineddata");
        //设置语言(不需要写扩展名)
        tesseract.setLanguage("eng");
        String result = tesseract.doOCR(captchaImageFile);
        System.out.println(result);
    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

运行结果
在这里插入图片描述
很尴尬,除了两个数字被正确识别之外,符号一个没识别出来,换成中文识别率更低,有兴趣的小伙伴可以试试其他语言。很显然这不是我们想要的效果,所以引出今天的重点——自定义字库

自定义字库,提高识别率

下载jTessBoxEditor

官网下载:https://udomain.dl.sourceforge.net/project/vietocr/jTessBoxEditor/jTessBoxEditor-2.4.1.zip

解压

在这里插入图片描述

添加环境变量

在这里插入图片描述
操作步骤:右键此电脑-属性-高级系统设置-环境变量-Path-添加-输入JTessBoxEditor的tesseract-ocr目录

运行

双击jTessBoxEditor.jar运行
在这里插入图片描述
在这里插入图片描述

准备素材

素材当然是越多越好,这样训练出来之后识别率会更高
在这里插入图片描述

合并PNG为tif文件

依次点击Tools - Merge TIFF...
在这里插入图片描述
文件类型选为png(根据实际类型选择),不然看不到你的文件,全选素材,然后点击打开
在这里插入图片描述

注意!!! 这一步的文件名是有讲究的,不能随意命名!

在这里插入图片描述
tif文件命名格式需规范,格式为[lang].[fontname].exp[num].tif,lang为语言名称,fontname为字体名称,num为序号。例如上图所示的:verification-code.calculation-question.exp0.tif(扩展名可以自动加,只要文件类型选对的)

在这里插入图片描述
点击确定,即可合并完成

生成box文件

在刚才tif文件生成的目录执行命令:

tesseract verification-code.calculation-question.exp0.tif verification-code.calculation-question.exp0 batch.nochop makebox

执行结果:
在这里插入图片描述

使用jTessBoxEditor工具对tif文件进行校准

依次点击Box Editor - Open 然后选择刚才生成的tif文件,选择之后他会自动关联上对应的box文件
在这里插入图片描述
在这里插入图片描述

校正

在这里插入图片描述
示例:
在这里插入图片描述
在这里插入图片描述
以此类推,把后面的字符和位置全部校正,这个过程有点枯燥

生成tr文件

在刚刚的tif文件所在目录执行命令:

tesseract verification-code.calculation-question.exp0.tif verification-code.calculation-question.exp0 nobatch box.train

执行结果:
在这里插入图片描述

生成生成字符集文件unicharset文件

同样的目录中执行命令:

unicharset_extractor verification-code.calculation-question.exp0.box

执行结果:
在这里插入图片描述

生成font_properties文件(不需要扩展名,切记;calculation-question为font)

执行命令:

echo calculation-question 0 0 0 0 0 > font_properties

执行结果:
在这里插入图片描述

生成shape文件

执行命令:

shapeclustering -F font_properties -U unicharset -O verification-code.unicharset verification-code.calculation-question.exp0.tr

执行结果:
在这里插入图片描述

生成聚字符特征文件

执行命令:

mftraining -F font_properties -U unicharset -O unicharset verification-code.calculation-question.exp0.tr

执行结果:
在这里插入图片描述

生成字符正常化特征文件

执行命令:

cntraining verification-code.calculation-question.exp0.tr

执行结果:
在这里插入图片描述

把inttemp、pffmtable、shapetable、normproto四个文件命名为[lang].xxx

分别执行下面四个重命名命令:

rename normproto verification-code.normproto

rename inttemp verification-code.inttemp

rename pffmtable verification-code.pffmtable

rename shapetable verification-code.shapetable

执行结果:
在这里插入图片描述

合并训练文件成成traineddata文件

执行命令:

combine_tessdata verification-code

执行结果:
在这里插入图片描述
自此,训练完成!

使用自定义的字库进行识别

代码:(verification-code为刚才训练所得的)

package com.beiyoufamily;

import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.io.File;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2023/6/3 15:09
 */

public class CaptchaIdentification {

    public static void main(String[] args) throws TesseractException {
        //要是别的验证码图片
        File captchaImageFile = new File("C:/Files/images/captcha/test/captcha.png");
        //创建tesseract对象
        Tesseract tesseract = new Tesseract();
        //设置traineddata文件目录
        tesseract.setDatapath("C:/Files/images/captcha/traineddata");
        //设置语言(不需要写扩展名)
        tesseract.setLanguage("verification-code");
        String result = tesseract.doOCR(captchaImageFile);
        System.out.println(result);
    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

运行结果:
在这里插入图片描述
非常完美,精确的识别出了表达式!

用脚本引擎识别计算出结果

package com.beiyoufamily;

import cn.hutool.script.ScriptUtil;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

import java.io.File;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2023/6/3 15:09
 */

public class CaptchaIdentification {

    public static void main(String[] args) throws TesseractException {
        //要是别的验证码图片
        File captchaImageFile = new File("C:/Files/images/captcha/test/captcha.png");
        //创建tesseract对象
        Tesseract tesseract = new Tesseract();
        //设置traineddata文件目录
        tesseract.setDatapath("C:/Files/images/captcha/traineddata");
        //设置语言(不需要写扩展名)
        tesseract.setLanguage("verification-code");
        String result = tesseract.doOCR(captchaImageFile);

        if (Objects.nonNull(result)) {
            //去除所有的空白字符
            result = result.replaceAll("\\s*", "").trim();

            String pattern = "\\d+[+\\-*/]\\d+=\\?";
            
            //判断识别出来的表达式是否合法
            if (Pattern.matches(pattern, result)) {
                //提取表达式
                Matcher matcher = Pattern.compile("\\d+[+\\-*/]\\d+").matcher(result);
                if (matcher.find()) {
                    String expression = matcher.group();
                    System.out.println(expression);
                    System.out.println(ScriptUtil.eval(expression));
                }
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

计算结果:
在这里插入图片描述

其他注意事项

本演示示例是在Java8环境中运行的,高版本的Java环境可能会没有脚本引擎,会报错。

训练的过程中由于命令众多,参数复杂,博主封装了一个小工具,可以直接运行,省去输入命令,下载地址:
https://download.csdn.net/download/daiyi666/87888642传送门

下载之后直接点击run.bat运行即可,根据提示操作。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/496243
推荐阅读
相关标签
  

闽ICP备14008679号