简介

  • Tess4J是一个基于Tesseract OCR引擎的Java接口,可以用来识别图像中的文本。
  • Tesseract是一个开源的光学字符识别(OCR)引擎,它可以将图像中的文字转换为计算机可读的文本。支持多种语言和书面语言,并且可以在命令行中执行。它是一个流行的开源OCR工具,可以在许多不同的操作系统上运行。

文件下载

目前我测试只用到简体中文和英文,所以只下载了两个
简体中文下载
英文下载

其它语种请按需下载

把下载后的文件统一放到一个目录下
【SpringBoot框架篇】36.整合Tess4J搭建提供图片文字识别的Web服务-LMLPHP

引入依赖

      	<dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>5.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

main函数中使用

    public static void main(String[] args) throws Exception {
        ITesseract tesseract = new Tesseract();
        // 设置训练集文件存储目录
        tesseract.setDatapath("D:/traineddata");
        
        // 设置引擎为中文简体 文件名不含后缀
        tesseract.setLanguage("chi_sim");
        String result = tesseract.doOCR(ImageIO.read(new File("D:\\test\\zh.png")));
        System.out.println(result);
        
        // 设置引擎为英文
        tesseract.setLanguage("eng");
        result = tesseract.doOCR(ImageIO.read(new File("D:\\test\\en.png")));
        System.out.println(result);
    }

识别结果如下
【SpringBoot框架篇】36.整合Tess4J搭建提供图片文字识别的Web服务-LMLPHP
【SpringBoot框架篇】36.整合Tess4J搭建提供图片文字识别的Web服务-LMLPHP

基于Springboot搭建OCR Web服务

配置traineddata路径

application.yaml中配置如下内容

server:
  port: 8036
#ocr引擎存放路径
tess4j:
  datapath: D:/traineddata

枚举用到的语种类型

/**
 * @Description 自行扩展需要的OCR引擎语种
 * @Author Dominick Li
 **/
@Getter
@AllArgsConstructor
public enum LanguageTypeEnum {

    CHINESE_SIMPLIFIED("chi_sim", "简体中文"),
    ENGLISH("eng", "英文");

    private final String value;
    private final String language;

    /**
     * 根据语种查找枚举对象
     * @param language 前端传的参数
     * @return 没找到对应的则默认使用简单中文
     */
    public static LanguageTypeEnum getLanguageByType(String language) {
        for (LanguageTypeEnum languageTypeEnum : LanguageTypeEnum.values()) {
            if (languageTypeEnum.getValue().equals(language)) {
                return languageTypeEnum;
            }
        }
        return CHINESE_SIMPLIFIED;
    }

}

定义接口响应的json数据格式

@Data
@Builder
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OcrResult {

    /**
     * 是否识别成功
     */
    public boolean success;

    /**
     * 识别时间
     */
    public long time;

    /**
     * 识别结果
     */
    public String[] texts;

    /**
     * 异常信息
     */
    public String msg;

    public static OcrResult success(String text, long time) {
        return OcrResult.builder()
                .success(true)
                .texts(text.split("\n"))
                .time(time)
                .build();
    }

    public static OcrResult fail(String msg) {
        return OcrResult.builder()
                .success(false)
                .msg(msg)
                .build();
    }

}

封装OCR服务引擎

@Slf4j
@Service
public class TesseractServer {

    @Value("${tess4j.datapath}")
    private String datapath;

    private final static Map<LanguageTypeEnum, ITesseract> SERVER_INSTANCE = new HashMap<>();

    /**
     * 根据枚举配置的语种初始化Tesseract引擎
     */
    @PostConstruct
    public void init() {
        ITesseract iTesseract;
        for (LanguageTypeEnum languageTypeEnum : LanguageTypeEnum.values()) {
            iTesseract = new Tesseract();
            //设置训练集文件存储目录
            iTesseract.setDatapath(datapath);
            //设置语种
            iTesseract.setLanguage(languageTypeEnum.getValue());
            SERVER_INSTANCE.put(languageTypeEnum, iTesseract);
            log.info("load {}  ocr model", languageTypeEnum.getLanguage());
        }
    }

    /**
     * ocr识别
     */
    private OcrResult doOCR(ITesseract iTesseract, BufferedImage bufferedImage) throws Exception {
        String result = null;
        long startTime = System.currentTimeMillis();
        result = iTesseract.doOCR(bufferedImage);
        long time = System.currentTimeMillis()-startTime;
        log.info("Time is: {} 毫秒", time);
        return OcrResult.success(result, time);
    }

    public OcrResult ocrImage(LanguageTypeEnum languageTypeEnum, File file) throws Exception {
        return doOCR(SERVER_INSTANCE.get(languageTypeEnum), ImageIO.read(file));
    }

    public OcrResult ocrImage(LanguageTypeEnum languageTypeEnum, MultipartFile file) throws Exception {
        return ocrImage(languageTypeEnum, ImageIO.read(new ByteArrayInputStream(file.getBytes())));

    }

    public OcrResult ocrImage(LanguageTypeEnum languageTypeEnum, BufferedImage bufferedImage) throws Exception {
        return doOCR(SERVER_INSTANCE.get(languageTypeEnum), bufferedImage);
    }

}

编写web提供服务的接口

@Slf4j
@RestController
@RequestMapping("/api")
public class OcrController {

    @Resource
    private TesseractServer tesseractServer;

    /**
     * OCR识别  /ocr/chi_sim          /ocr/eng
     * @param language 使用的模型语种  chi_sim=简体中文  eng=英文
     * @param file 需要识别的图片
     */
    @PostMapping("/ocr/{language}")
    public OcrResult recognize(@PathVariable String language, MultipartFile file) {
        try {
            // 对图片进行文字识别
            return tesseractServer.ocrImage(LanguageTypeEnum.getLanguageByType(language), file);
        } catch (Exception e) {
            log.error("error:{}", e.getMessage());
            return OcrResult.fail(e.getMessage());
        }
    }

}

启动服务并且测试

http://127.0.0.1:8036/api/ocr/chi_sim 中文引擎识别
http://127.0.0.1:8036/api/ocr/eng 英文引擎识别
【SpringBoot框架篇】36.整合Tess4J搭建提供图片文字识别的Web服务-LMLPHP

到此基于Springboot框架搭建提供Ocr能力的Web服务就完成

html demo扩展

基于html + jquery 搭建的简陋的demo, 访问路径http://127.0.0.1:8036/index.html
【SpringBoot框架篇】36.整合Tess4J搭建提供图片文字识别的Web服务-LMLPHP

index.html文件源码,放到项目resources/static目录下即可

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>OCR测试页面</title>
</head>
<style type="text/css">
    #app {
        display: flex;
        margin: 50px;
        height: 1000px;
    }

    #app div {
        padding: 50px;
        width: 50%;
        border: solid 1px #000;
        height: 100%;
    }
</style>
<body>
<div id="app">
    <div id="left" class="upload-box clear">
        <input type="file" id="fileInput">
        选择OCR识别使用的语种
        <input type="radio" name="language" value="zh_sim" checked="checked"/> 简体中文
        <input type="radio" name="language" value="eng"/> 英文
        <input id="summit" type="button" value="识别">
        </br>
        <img id="previewImage" src="" alt="Preview Image" width="100%">
    </div>
    <div>
        <h2>识别结果</h2>
        <p>识别时间:<span id="time"></span>毫秒</p>
        <p id="resust"></p>
    </div>
</div>

<script src="https://cdn.staticfile.org/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
    const fileInput = document.getElementById('fileInput');
    const previewImage = document.getElementById('previewImage');
    fileInput.addEventListener('change', function () {
        const file = fileInput.files[0]; // 获取选中的文件对象
        if (file) {
            let language = $('input[name="language"]:checked').val();
            uploadOcr(file, language);
            const reader = new FileReader();

            reader.addEventListener('load', function () {
                // 当文件读取完成时触发的事件处理函数
                previewImage.src = reader.result;
            });
            reader.readAsDataURL(file);
        }
    });

    document.getElementById('summit').addEventListener('click', function () {
        const file = fileInput.files[0]; // 获取选中的文件对象
        let language = $('input[name="language"]:checked').val();
        uploadOcr(file, language);
    })

    function uploadOcr(file, language) {
        var formData = new FormData();
        formData.append('file', file);

        $.ajax({
            url: "/api/ocr/" + language, // 上传图片的后端接口地址
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function (response) {
                // 上传成功后的处理逻辑
                console.log('上传成功' + response);
                $("#time").html(response.time);
                if (response.success) {
                    $("#resust").html("");
                    for (var i = 0; i < response.texts.length; i++) {
                        $("#resust").append(response.texts[i]).append("<br/>");
                    }
                }
            },
            error: function (xhr, status, error) {
                // 上传失败后的处理逻辑
                console.log('上传失败');
            }
        });
    }
</script>
</body>
</html>

项目配套代码

gitee代码地址

创作不易,要是觉得我写的对你有点帮助的话,麻烦在gitee上帮我点下 Star

【SpringBoot框架篇】其它文章如下,后续会继续更新。

03-11 07:21