Ocr之TesseractOcr的安装及使用

news2025/1/19 7:08:11

目录

一、安装环境

二、安装内容

三、安装过程及识别测试

1. 安装过程
2. 程序编写

总结

1. 安装复杂度较低
2. 国外开源Ocr
3. 可设置识别参数
4. 工具类

一、 系统环境windows 10

linux环境也可安装, 可借鉴此篇文章>> |

二、安装内容

Tesseract exe 程序安装
exe程序下载地址, 可选择版本安装>> |

# 我们这里安装的版本是
tesseract-ocr-w64-setup-5.3.1.20230401.exe

三、安装过程及识别测试

1. 安装过程
  • 安装后的目录结构
    默认安装在C盘。可选择路径。傻瓜式安装就可以
    在这里插入图片描述
  • 添加环境变量 TESSDATA_PREFIX=<安装的tessoract-ocr.exe后文件夹根路径>/tessdata
    在这里插入图片描述
2. 程序编写
  • 使用Tesseract进行识别程序的编写
    目前使用TesseractOcr已经更换为 PaddleOcr 了。源于TesseractOcr对背景模糊的图片识别率不高,使用PaddleOcr后识别率有明显提高。
    不过使用PaddleOcr识别过程会将图片进行预处理(图片放大和模糊处理再使用paddleocr识别效果更佳:后期会做记录并将链接加到此处)

  • 使用java程序进行识别需要引用 mvn 第三方依赖

    <!--ocr图像识别-->
     <dependency>
         <groupId>net.sourceforge.tess4j</groupId>
         <artifactId>tess4j</artifactId>
         <version>5.3.0</version>
     </dependency>
    
  • 单元测试用例+执行结果
    在这里插入图片描述
    下方代码中对上方图片进行识别(图片名称:new33.jpg)

    @Test
    public void readImageByOcr() throws TesseractException {
        String imgSrc = "C:\\...\\changepic\\new33.jpg";
        File imgFile = new File(imgSrc);
        //创建tesseract对象
        Tesseract tes = new Tesseract();
        //语言包位置  根据实际环境修改替换
        tes.setDatapath("E:\\...\\Tesseract-OCR\\tessdata");
        //配置使用的语言  中文
        tes.setLanguage("eng");
        String imgText = tes.doOCR(imgFile);
        System.out.println("解析结果:" + imgText);
    }
    

    执行后
    在这里插入图片描述

  • 业务代码示例
    结合业务代码使用TesseractOcr。TesseractOcr使用时可传入不通参数。如language, variable等。
    tessedit_char_whitelist:设置白名单。下方demo限制内容为只能识别数字和字母

    /**
      * ocr识别
      * @param img
      * @param dataPath
      * @param replacedEmp 是否替换回车和空格为空, true:替换, false, 不替换(含回车和空格符)
      * @param dpi 分辨率, 默认 96
      * @param charNoLimit 识别空格: true, 不识别空格: false
      * @return
      * @throws TesseractException
      */
     private static String doOcrImpl(BufferedImage img, String dataPath, boolean replacedEmp, String dpi, boolean charNoLimit) throws TesseractException {
         // 初始化 OCR 引擎
         Tesseract tesseract = new Tesseract();
         File tessDataFolder = LoadLibs.extractTessResources("tessdata");
         tesseract.setDatapath(tessDataFolder.getAbsolutePath());
         //语言包位置  根据实际环境修改替换
         tesseract.setDatapath(dataPath);
         //配置使用的语言  中文
         tesseract.setLanguage("eng");
         if(!charNoLimit) {
             //限制只识别数字字母
             tesseract.setVariable("tessedit_char_whitelist", "0123456789CDFGMRTX");
         }
         //设置分辨率
         tesseract.setVariable("user_defined_dpi", dpi);
         String result = tesseract.doOCR(img);
         if(replacedEmp) {
             // 文字识别-过滤空白、换行符
             result = result.replace(StrUtil.SPACE, StrUtil.EMPTY).replace(StrUtil.LF, StrUtil.EMPTY);
         }
         return result;
     }
    

总结

  1. 安装复杂度较低。
    相比于paddleocr的安装要简单的多(需要安装python环境及下载paddleocr相关内容)。paddleocr安装借鉴 gitee paddleocr开源代码>> |
  2. 属于国外开源Ocr。
  3. 可设置识别参数。可设置变量与识别语言。
  4. 使用Ocr时用到的工具类。可自行测试
package util;

import cn.hutool.core.util.StrUtil;
import common.aspect.core.StringUtils;
import common.exception.CustomException;
import PO.RecognizeTemplate;
import service.PrintDcmOcrRecognizeService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import net.sourceforge.tess4j.util.LoadLibs;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Value;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class ReadTextFromFileRegion {
    /**
     * @Description: ocr按区域识别文件
     **/
    public static String doRecognize(File file, Rectangle rectangle, String dataPath, String formateName, String dpi)
            throws Exception {
        if (!file.exists()) {
            throw new CustomException(0, "待识别文件不存在");
        }
        // OCR 文字识别
        return doOcr(createImg(file, rectangle, formateName), dataPath, dpi);
    }
	  /**
	   * file: 图片文件
	   * rectangle: 图片中需要识别的区域。如new Rectangle(x, y, w, h), 坐标及宽高
	   * dataPath: tessData的路径(文章开头已添加到环境变量,也可传入)
	   * formateName: file文件的格式。如 JPG, PNG, DICOM等, 
	   * dpi: tesseractOcr识别时传入的参数。如:tesseract.setVariable("user_defined_dpi", dpi);
	   */
    public static String doRecognizeOrcOriginResult(File file, Rectangle rectangle, String dataPath, String formateName, String dpi)
            throws Exception {
        if (!file.exists()) {
            throw new CustomException(0, "待识别文件不存在");
        }
        // OCR 文字识别
        return doOcrImpl(createImg(file, rectangle, formateName), dataPath, false, dpi, true);
    }
	/**
	 * 截取的图像缓冲区
	 */
    private static BufferedImage createImg(File file, Rectangle rectangle, String formateName) throws Exception {
        BufferedImage img = readFile(file, rectangle, formateName);
        if(img == null) {
            log.warn("读取图像异常: img == null");
            throw new Exception("文件读取异常, 创建img为空.");
        }
        return img;
    }
    
    /**
     * @Description: 把文件转为BufferedImage对象,并截取指定区域
     **/
    private static BufferedImage readFile(File file, Rectangle region, String formateName) throws IOException {
        ImageInputStream iis = null;
        ImageReader reader = null;
        try {
            // 创建 ImageInputStream 对象
            iis = ImageIO.createImageInputStream(file);
            // 获取 指定 文件的 ImageReader 实例
            reader = ImageIO.getImageReadersByFormatName(formateName).next();
            // 设置解码器
            reader.setInput(iis);
            // 如果需要截取图像,获取完整的BufferedImage,然后截取指定区域
            BufferedImage image = reader.read(0);
            BufferedImage subImage = null;
            try{
                subImage = image.getSubimage(region.x, region.y, region.width, region.height);
            }catch (RasterFormatException e) {
                log.warn("截取图像异常: 识别区域超出边界. err.msg: {}", e.toString());
                return subImage;
            }
            // 释放完整的BufferedImage
            image.flush();
            return subImage;
        } finally {
            // 关闭资源
            if (reader != null) {
                reader.dispose();
            }
            if (iis != null) {
                iis.close();
            }
        }
    }

    /**
     * @Description: ocr按区域识别pdf文件
     **/
    public static String doPdfRecognize(File pdfFile, String dataPath) throws Exception {
        BufferedImage img = readPdfToImage(pdfFile);
        // 按自定义区域截取图像
        BufferedImage subImage = img.getSubimage(460, 170, 320, 100);
        // OCR 文字识别
        return doOcr(subImage, dataPath, "120");
    }

    /**
     * @Description: 把pdf转为图像,renderImageWithDPI方法的第二个参数dpi影响图像分辨率,经测试dpi为300,生成2k分辨率的图像
     **/
    private static BufferedImage readPdfToImage(File pdfFile) throws IOException {
        try (PDDocument document = PDDocument.load(pdfFile)) {
            PDFRenderer renderer = new PDFRenderer(document);
            return renderer.renderImageWithDPI(0, 300);
        }
    }

    /**
     * @Description: 使用Tesseract进行ocr识别
     **/
    private static String doOcr(BufferedImage img, String dataPath, String dpi) throws TesseractException {
        return doOcrImpl(img, dataPath, true, dpi, false);
    }

    /**
     * ocr识别
     * @param img
	   * dataPath: tessData的路径(文章开头已添加到环境变量,也可传入)
     * @param replacedEmp 是否替换回车和空格为空, true:替换, false, 不替换(含回车和空格符)
     * @param dpi 分辨率, 默认 96
     * @param charNoLimit 识别空格: true, 不识别空格: false
     * @return
     * @throws TesseractException
     */
    private static String doOcrImpl(BufferedImage img, String dataPath, boolean replacedEmp, String dpi, boolean charNoLimit) throws TesseractException {
        // 初始化 OCR 引擎
        Tesseract tesseract = new Tesseract();
        File tessDataFolder = LoadLibs.extractTessResources("tessdata");
        tesseract.setDatapath(tessDataFolder.getAbsolutePath());
        //语言包位置  根据实际环境修改替换
        tesseract.setDatapath(dataPath);
        //配置使用的语言  中文
        tesseract.setLanguage("eng");
        if(!charNoLimit) {
            //限制只识别数字字母
            tesseract.setVariable("tessedit_char_whitelist", "0123456789CDFGMRTX");
        }
        //设置分辨率
        tesseract.setVariable("user_defined_dpi", dpi);
        String result = tesseract.doOCR(img);
        if(replacedEmp) {
            // 文字识别-过滤空白、换行符
            result = result.replace(StrUtil.SPACE, StrUtil.EMPTY).replace(StrUtil.LF, StrUtil.EMPTY);
        }
        return result;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1447417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《金融人工智能:用python实现ai量化交易》

融合了数学、python、深度学习以及金融知识&#xff0c;是本推荐的好书。请收藏本文&#xff0c;读后再给大学总结。

React18原理: 核心包结构与两大工作循环

React核心包结构 1 ) react react基础包&#xff0c;只提供定义 react组件(ReactElement)的必要函数一般来说需要和渲染器(react-dom,react-native)一同使用在编写react应用的代码时, 大部分都是调用此包的api比如, 我们定义组件的时候&#xff0c;就是它提供的class Demo ext…

Elasticsearch:适用于 iOS 和 Android 本机应用程序的 Elastic APM

作者&#xff1a;来自 Elastic Akhilesh Pokhariyal, Cesar Munoz, Bryce Buchanan 适用于本机应用程序的 Elastic APM 提供传出 HTTP 请求和视图加载的自动检测&#xff0c;捕获自定义事件、错误和崩溃&#xff0c;并包括用于数据分析和故障排除目的的预构建仪表板。 适用于 …

LeetCode:83和82.删除排序链表中的重复元素I,II

这两题算是链表的基础题&#xff0c;就遍历删除没啥特点&#xff0c; 83甚至不需要考虑第一个结点的特殊情况&#xff0c;属实是名副其实的easy了 LeetCode&#xff1a;21.合并两个有序链表之第一次的特殊情况-CSDN博客 83. 删除排序链表中的重复元素 - 力扣&#xff08;Lee…

[NSSCTF]-Web:[SWPUCTF 2021 新生赛]easyrce解析

先看网页 代码审计&#xff1a; error_reporting(0); &#xff1a;关闭报错&#xff0c;代码的错误将不会显示 highlight_file(__FILE__); &#xff1a;将当前文件的源代码显示出来 eval($_GET[url]); &#xff1a;将url的值作为php代码执行 解题&#xff1a; 题目既然允许…

备战蓝桥杯---动态规划(入门1)

先补充一下背包问题&#xff1a; 于是&#xff0c;我们把每一组当成一个物品&#xff0c;f[k][v]表示前k组花费v的最大值。 转移方程还是max(f[k-1][v],f[k-1][v-c[i]]w[i]) 伪代码&#xff08;注意循环顺序&#xff09;&#xff1a; for 所有组&#xff1a; for vmax.....0…

wayland(xdg_wm_base) + egl + opengles 纹理贴图进阶实例(四)

文章目录 前言一、使用gstreamer 获取 pattern 图片二、代码实例1. pattern 图片作为纹理数据源的代码实例1.1 基于opengles2.0 接口的 egl_wayland_texture2_1.c1.2 基于opengles3.0 接口的 egl_wayland_texture3_1.c2. xdg-shell-client-protocol.h 和 xdg-shell-protocol.c3…

算法学习——LeetCode力扣二叉树篇8

算法学习——LeetCode力扣二叉树篇8 669. 修剪二叉搜索树 669. 修剪二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 描述 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high…

Day 44 | 动态规划 完全背包、518. 零钱兑换 II 、 377. 组合总和 Ⅳ

完全背包 题目 文章讲解 视频讲解 完全背包和0-1背包的区别在于&#xff1a;物品是否可以重复使用 思路&#xff1a;对于完全背包问题&#xff0c;内层循环的遍历方式应该是从weight[i]开始一直遍历到V&#xff0c;而不是从V到weight[i]。这样可以确保每种物品可以被选择多次…

解决Thymeleaf的地震震中距离展示[[]]双引号报错的问题

目录 前言 一、问题场景还原 1、需求场景 2、系统设计 3、功能实现 4、线数据标注展示 5、页面出错 二、解决Thymeleaf报错 1、错误说明 2、参数改造 3、问题修复 总结 前言 今天是2024年2月12日&#xff0c;农历正月初三&#xff0c;还是农历龙年春节。在这里首先…

ubuntu快速安装miniconda

ubuntu快速安装miniconda 环境 ubuntu.22.04 显卡 RTX 3050 关于选择Miniconda还是Anaconda的问题&#xff0c;Anaconda安装包比较大&#xff0c;耗时比较长&#xff0c;如果你是绝对的初学者&#xff0c;选择Anaconda会比较稳妥一些&#xff1b;否则建议你还是选择Miniconda安…

docker 1:介绍

docker 1&#xff1a;介绍 docker解决哪些问题&#xff1a; 传统APP在安装到不同电脑的时候可能会遇到依赖问题&#xff0c;比如缺少VS 20xx&#xff0c;软件无法运行”的情况。docker使用容器技术将软件 依赖​打包为image包发布&#xff0c;解决了依赖问题。docker有一个官…

考研高数(导数的定义)

总结&#xff1a; 导数的本质就是极限。 函数在某点可导就必连续&#xff0c;连续就有极限且等于该点的函数值。 例题1&#xff1a;&#xff08;归结原则的条件是函数可导&#xff09; 例题2&#xff1a; 例题3&#xff1a;

Unity下使用Sqlite

sqlite和access类似是文件形式的数据库&#xff0c;不需要安装任何服务&#xff0c;可以存储数据&#xff0c;使用起来还是挺方便的。 首先需要安装DLL 需要的DLL 我们找到下面两个文件放入Plugins目录 Mono.Data.Sqlite.dll System.Data.dll DLL文件位于Unity的安装目录下的…

controller-manager学习三部曲之三:deployment的controller启动分析

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 《controller-manager学习三部曲》完整链接 通过脚本文件寻找程序入口源码学习deployment的controller启动分析 本篇概览 本文是《controller-manager学习三…

部署JForum2过程。

居然用了两天时间&#xff0c;才把JForum2部署成功。走了一些弯路&#xff0c;主要原因是想当然&#xff0c;以为jdk和tomcat&#xff0c;应该向下兼容&#xff0c;所以就随便选的版本。 一、jdk-17、apache-tomcat-10.1.18-windows-x64&#xff0c;部署完jforum-2.8.2.war,改…

基于STM32与FreeRTOS的四轴机械臂项目

目录 一、项目介绍 二、前期准备 1.硬件准备 2.开发环境 3.CubeMX配置 三、裸机各种模块测试 1.舵机模块 2.蓝牙模块 3.按键摇杆传感器模块和旋钮电位器模块 4.OLED模块 5.W25Q128模块 四、裸机三种控制测试 1.摇杆控制 2.示教器控制 3.蓝牙控制 五、裸机与Free…

linux应用 进程间通信之共享内存(POSIX)

1、前言 1.1 定义 POSIX共享内存是一种在UNIX和类UNIX系统上可用的进程间通信机制。它允许多个进程共享同一块内存区域&#xff0c;从而可以在这块共享内存上进行读写操作。 1.2 应用场景 POSIX共享内存适用于需要高效地进行大量数据交换的场景&#xff0c;比如多个进程需要…

Hive的Join连接

前言 Hive-3.1.2版本支持6种join语法。分别是&#xff1a;inner join&#xff08;内连接&#xff09;、left join&#xff08;左连接&#xff09;、right join&#xff08;右连接&#xff09;、full outer join&#xff08;全外连接&#xff09;、left semi join&#xff08;左…

C++ bfs再探迷宫游戏(五十五)【第二篇】

今天我们用bfs解决迷宫游戏。 1.再探迷宫游戏 前面我们已经接触过了迷宫游戏&#xff0c;并且学会了如何使用 DFS 来解决迷宫最短路问题。用 DFS 求解迷宫最短路有一个很大的缺点&#xff0c;需要枚举所有可能的路径&#xff0c;读入的地图一旦很大&#xff0c;可能的搜索方案…