使用easyocr、PyPDF2对图像及PDF文档进行识别

news2025/3/6 19:06:57

一、概述

本 Python 脚本的主要功能是对当前目录及其子目录下的图片和 PDF 文件进行光学字符识别(OCR)处理。它使用 easyocr 库处理图片中的文字,使用 PyPDF2 库提取 PDF 文件中的文本,并将处理结果保存为文本文件。同时,脚本会记录详细的处理日志,方便用户跟踪处理过程和排查问题。

二、环境要求

  • Python 版本:建议使用 Python 3.6 及以上版本。
  • 依赖库
    • easyocr:用于图片的 OCR 识别。
    • PyPDF2:用于读取 PDF 文件并提取文本。
    • PillowPIL):虽然脚本中未直接使用,但 easyocr 处理图像时可能依赖。

你可以使用以下命令安装这些依赖库:

收起

bash

pip install easyocr PyPDF2 Pillow

三、脚本结构与功能模块

1. 导入必要的库

收起

python

import os
import time
import easyocr
from PyPDF2 import PdfReader
from PIL import Image

导入了处理文件系统、时间、OCR 识别、PDF 读取和图像处理所需的库。

2. 设置模型下载路径

收起

python

model_storage_directory = './easyocr_models'
os.makedirs(model_storage_directory, exist_ok=True)

定义了 easyocr 模型的存储目录,并确保该目录存在。

3. 检查网络连接

收起

python

def check_network():
    try:
        import urllib.request
        urllib.request.urlopen('https://www.baidu.com', timeout=5)
        return True
    except:
        return False

该函数尝试访问百度网站,以检查网络连接是否正常。如果能成功访问,则返回 True,否则返回 False

4. 初始化 EasyOCR reader

收起

python

try:
    print("Initializing EasyOCR...")
    print(f"Model storage directory: {os.path.abspath(model_storage_directory)}")
    
    if not check_network():
        print("Network connection failed. Please check your internet connection.")
        exit(1)
        
    print("Downloading models (this may take several minutes)...")
    reader = easyocr.Reader(
        ['ch_sim', 'en'],
        model_storage_directory=model_storage_directory,
        download_enabled=True,
        verbose=True
    )
    print("EasyOCR initialized successfully")
except Exception as e:
    print(f"Failed to initialize EasyOCR: {str(e)}")
    exit(1)

  • 打印初始化信息和模型存储目录的绝对路径。
  • 检查网络连接,若网络异常则输出错误信息并退出程序。
  • 下载 easyocr 所需的模型,支持中文(简体)和英文识别。
  • 若初始化成功,打印成功信息;若出现异常,打印错误信息并退出程序。

5. 处理图片文件

收起

python

def process_image(image_path):
    """处理图片文件"""
    try:
        result = reader.readtext(image_path)
        text = '\n'.join([item[1] for item in result])
        return text
    except Exception as e:
        print(f"Error processing image {image_path}: {str(e)}")
        return ""

  • 接受图片文件路径作为参数。
  • 使用 easyocr 对图片进行 OCR 识别,提取识别结果中的文本并拼接成字符串返回。
  • 若处理过程中出现异常,打印错误信息并返回空字符串。

6. 处理 PDF 文件

收起

python

def process_pdf(pdf_path):
    """处理PDF文件"""
    try:
        text = ""
        reader = PdfReader(pdf_path)
        for page in reader.pages:
            text += page.extract_text()
        return text
    except Exception as e:
        print(f"Error processing PDF {pdf_path}: {str(e)}")
        return ""

  • 接受 PDF 文件路径作为参数。
  • 使用 PyPDF2 读取 PDF 文件的每一页,并提取文本拼接成字符串返回。
  • 若处理过程中出现异常,打印错误信息并返回空字符串。

7. 保存提取的文本

收起

python

def save_text(text, output_path):
    """保存提取的文本"""
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(text)

  • 接受文本内容和输出文件路径作为参数。
  • 将文本内容以 UTF-8 编码写入指定的输出文件。

8. 主函数 main

收起

python

def main():
    # 尝试多个可能的输出目录位置
    output_folders = [
        './output_text',  # 当前目录
        os.path.expanduser('~/ocr_output'),  # 用户主目录
        os.path.join(os.getcwd(), 'ocr_output')  # 当前工作目录
    ]
    
    output_folder = None
    for folder in output_folders:
        try:
            os.makedirs(folder, exist_ok=True)
            output_folder = folder
            print(f"Using output directory: {os.path.abspath(output_folder)}")
            break
        except Exception as e:
            print(f"Failed to create output directory {folder}: {str(e)}")
    
    if output_folder is None:
        print("Error: Could not create any output directory")
        exit(1)
    
    # 初始化日志
    log_file = os.path.join(output_folder, 'ocr_log.txt')
    # 重定向标准输出到日志文件
    import sys
    class Logger(object):
        def __init__(self, filename):
            self.terminal = sys.stdout
            self.log = open(filename, "a", encoding='utf-8')

        def write(self, message):
            self.terminal.write(message)
            self.log.write(message)

        def flush(self):
            pass
            
    sys.stdout = Logger(log_file)
    print("OCR Processing Log\n")
    print(f"Starting OCR processing at {time.strftime('%Y-%m-%d %H:%M:%S')}")

    # 支持的图片格式
    image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tiff', '.gif']
    
    # 遍历当前目录及子目录
    for root, dirs, files in os.walk('.'):
        for file in files:
            file_path = os.path.join(root, file)
            base_name, ext = os.path.splitext(file)
            
            try:
                # 处理图片文件
                if ext.lower() in image_extensions:
                    print(f"Processing image: {file_path}")
                    text = process_image(file_path)
                    output_path = os.path.join(output_folder, f"{base_name}.txt")
                    save_text(text, output_path)
                    print(f"Successfully processed image: {file_path} -> {output_path}")
                    with open(log_file, 'a') as f:
                        f.write(f"Success: {file_path} -> {output_path}\n")
                
                # 处理PDF文件
                elif ext.lower() == '.pdf':
                    print(f"Processing PDF: {file_path}")
                    text = process_pdf(file_path)
                    output_path = os.path.join(output_folder, f"{base_name}.txt")
                    save_text(text, output_path)
                    print(f"Successfully processed PDF: {file_path} -> {output_path}")
                    with open(log_file, 'a') as f:
                        f.write(f"Success: {file_path} -> {output_path}\n")
                        
            except Exception as e:
                error_msg = f"Error processing {file_path}: {str(e)}"
                print(error_msg)
                with open(log_file, 'a') as f:
                    f.write(error_msg + "\n")

  • 输出目录处理:尝试在多个预设位置创建输出目录,若创建成功则使用该目录,若所有尝试均失败则输出错误信息并退出程序。
  • 日志初始化:在输出目录下创建 ocr_log.txt 日志文件,将标准输出重定向到该日志文件,同时保留在终端的输出。记录日志头部信息和处理开始时间。
  • 文件遍历与处理:遍历当前目录及其子目录下的所有文件,对图片文件调用 process_image 函数处理,对 PDF 文件调用 process_pdf 函数处理。将处理结果保存为文本文件,并在日志中记录成功或失败信息。

9. 程序入口

收起

python

if __name__ == "__main__":
    main()

当脚本作为主程序运行时,调用 main 函数开始执行。

四、使用方法

  1. 将脚本保存为一个 Python 文件(例如 ocr_process.py)。
  2. 确保所需的依赖库已安装。
  3. 打开终端或命令提示符,进入脚本所在的目录。
  4. 运行脚本:

收起

bash

python ocr_process.py
  1. 脚本会自动处理当前目录及其子目录下的图片和 PDF 文件,并将处理结果保存到指定的输出目录中,同时生成处理日志。

五、注意事项

  • 由于 easyocr 模型下载可能需要一定时间,首次运行脚本时请确保网络连接稳定,耐心等待模型下载完成。
  • 对于 PDF 文件,PyPDF2 只能提取文本内容,若 PDF 为扫描版或加密文件,可能无法正常提取文本。
  • 若处理过程中出现错误,请查看日志文件 ocr_log.txt 以获取详细的错误信息。

完成代码

import os
import time
import easyocr
from PyPDF2 import PdfReader
from PIL import Image

# 设置模型下载路径
model_storage_directory = './easyocr_models'
os.makedirs(model_storage_directory, exist_ok=True)

# 检查网络连接
def check_network():
    try:
        import urllib.request
        urllib.request.urlopen('https://www.baidu.com', timeout=5)
        return True
    except:
        return False

# 初始化EasyOCR reader
try:
    print("Initializing EasyOCR...")
    print(f"Model storage directory: {os.path.abspath(model_storage_directory)}")
    
    if not check_network():
        print("Network connection failed. Please check your internet connection.")
        exit(1)
        
    print("Downloading models (this may take several minutes)...")
    reader = easyocr.Reader(
        ['ch_sim', 'en'],
        model_storage_directory=model_storage_directory,
        download_enabled=True,
        verbose=True
    )
    print("EasyOCR initialized successfully")
except Exception as e:
    print(f"Failed to initialize EasyOCR: {str(e)}")
    exit(1)

def process_image(image_path):
    """处理图片文件"""
    try:
        # 使用EasyOCR提取文本
        result = reader.readtext(image_path)
        # 合并所有识别结果
        text = '\n'.join([item[1] for item in result])
        return text
    except Exception as e:
        print(f"Error processing image {image_path}: {str(e)}")
        return ""

def process_pdf(pdf_path):
    """处理PDF文件"""
    try:
        text = ""
        reader = PdfReader(pdf_path)
        for page in reader.pages:
            text += page.extract_text()
        return text
    except Exception as e:
        print(f"Error processing PDF {pdf_path}: {str(e)}")
        return ""

def save_text(text, output_path):
    """保存提取的文本"""
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(text)

def main():
    # 尝试多个可能的输出目录位置
    output_folders = [
        './output_text',  # 当前目录
        os.path.expanduser('~/ocr_output'),  # 用户主目录
        os.path.join(os.getcwd(), 'ocr_output')  # 当前工作目录
    ]
    
    output_folder = None
    for folder in output_folders:
        try:
            os.makedirs(folder, exist_ok=True)
            output_folder = folder
            print(f"Using output directory: {os.path.abspath(output_folder)}")
            break
        except Exception as e:
            print(f"Failed to create output directory {folder}: {str(e)}")
    
    if output_folder is None:
        print("Error: Could not create any output directory")
        exit(1)
    
    # 初始化日志
    log_file = os.path.join(output_folder, 'ocr_log.txt')
    # 重定向标准输出到日志文件
    import sys
    class Logger(object):
        def __init__(self, filename):
            self.terminal = sys.stdout
            self.log = open(filename, "a", encoding='utf-8')

        def write(self, message):
            self.terminal.write(message)
            self.log.write(message)

        def flush(self):
            pass
            
    sys.stdout = Logger(log_file)
    print("OCR Processing Log\n")
    print(f"Starting OCR processing at {time.strftime('%Y-%m-%d %H:%M:%S')}")

    # 支持的图片格式
    image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tiff', '.gif']
    
    # 遍历当前目录及子目录
    for root, dirs, files in os.walk('.'):
        for file in files:
            file_path = os.path.join(root, file)
            base_name, ext = os.path.splitext(file)
            
            try:
                # 处理图片文件
                if ext.lower() in image_extensions:
                    print(f"Processing image: {file_path}")
                    text = process_image(file_path)
                    output_path = os.path.join(output_folder, f"{base_name}.txt")
                    save_text(text, output_path)
                    print(f"Successfully processed image: {file_path} -> {output_path}")
                    with open(log_file, 'a') as f:
                        f.write(f"Success: {file_path} -> {output_path}\n")
                
                # 处理PDF文件
                elif ext.lower() == '.pdf':
                    print(f"Processing PDF: {file_path}")
                    text = process_pdf(file_path)
                    output_path = os.path.join(output_folder, f"{base_name}.txt")
                    save_text(text, output_path)
                    print(f"Successfully processed PDF: {file_path} -> {output_path}")
                    with open(log_file, 'a') as f:
                        f.write(f"Success: {file_path} -> {output_path}\n")
                        
            except Exception as e:
                error_msg = f"Error processing {file_path}: {str(e)}"
                print(error_msg)
                with open(log_file, 'a') as f:
                    f.write(error_msg + "\n")

if __name__ == "__main__":
    main()

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

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

相关文章

MAUI(C#)安卓开发起步

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

PPT小黑第26套

对应大猫28 层次级别是错的,看着是十页,导入ppt之后四十多页 选中所有 红色蓝色黑色 文本选择标题:选择 -格式相似文本(检查有没有漏选 漏选的话 按住ctrl 点下一个) 要求新建幻灯片中不包含原素材中的任何格式&…

【Linux-网络】HTTP的清风与HTTPS的密语

🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚 引言 📚 一、HTTP 📖 1.概述 📖 2.URL &#x1f5…

解决docker认证问题 failed to authorize: failed to fetch oauth token

报错信息[bash1]解决方案 全局代理打开“buildkit”: false ,见[图1] [bash1] >docker build -t ffpg . [] Building 71.8s (3/3) FINISHED docker:desktop-linux> [internal] load bui…

无人机应用探索:玻纤增强复合材料的疲劳性能研究

随着无人机技术的快速发展,轻量化已成为其结构设计的核心需求。玻纤增强复合材料凭借高强度、低密度和优异的耐环境性能,成为无人机机身、旋翼支架等关键部件的理想选择。然而,无人机在服役过程中需应对复杂多变的环境:高空飞行时…

Visual Studio工具

高亮显示匹配的标签(小括号,中括号,大括号)

STM32Cubemx配置E22-xxxT22D lora模块实现定点传输

文章目录 一、STM32Cubemx配置二、定点传输**什么是定点传输?****定点传输的特点****定点传输的工作方式****E22 模块定点传输配置****如何启用定点传输?****示例** **应用场景****总结** **配置 1:C0 00 07 00 02 04 62 00 17 40****解析** …

WPF+WebView 基础

1、基于.NET8&#xff0c;通过NuGet添加Microsoft.Web.WebView2。 2、MainWindow.xaml代码如下。 <Window x:Class"Demo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/win…

蓝桥杯算法——铠甲合体

问题描述 暗影大帝又开始搞事情了&#xff01;这次他派出了 MM 个战斗力爆表的暗影护法&#xff0c;准备一举摧毁 ERP 研究院&#xff01;MM 个暗影护法的战斗力可分别用 B1,⋯,BMB1​,⋯,BM​ 表示。 ERP 研究院紧急召唤了 NN 位铠甲勇士前来迎战&#xff01;每位铠甲勇士都…

docker:Dockerfile案例之自定义centos7镜像

1 案例需求 自定义centos7镜像。要求&#xff1a; 默认登录路径为 /usr可以使用vim 2 实施步骤 编写dockerfile脚本 vim centos_dockerfile 内容如下&#xff1a; #定义父镜像 FROM centos:7#定义作者信息 MAINTAINER handsome <handsomehandsome.com># 设置阿里云…

学习笔记:IC存储总结(ROM,RAM, EEPROM, Flash, SRAM, DRAM, DDL)

一&#xff0c;概述 半导体存储器是一种可以存储大量二值信息的半导体器件。在电子计算机及一些其他的数字系统的工作过程中&#xff0c;需要对大量的数据进行储存。由于数据处理的数据量和运算速度的要求&#xff0c;因此把存储量和存取速度作为衡量存储器的重要指标。 在电子…

Scala:统计每个单词出现的个数并打印

目录 问题拆解&#xff1a; 解题步骤&#xff1a; 1. 拆分所有字符串为单词 2. 遍历所有单词并统计 3. 打印结果 基础版代码实现&#xff1a; 代码解释&#xff1a; 输出结果&#xff1a; 为什么这样设计&#xff1f; 继承的APP是个啥&#xff1f; 使用高阶函数式编…

C++前缀和

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好&#xff0c;今天我们来了解一下C的一个重要概念&#xff1a;前缀和 目录 1.什么是前缀和 2.前缀和的用法 1.前缀和的定义 2.预处理前缀和数组 3.查询区间和 4.数组中某个区间的和是否为特定…

图解MOE大模型的7个核心问题并探讨DeepSeekMoE的专家机制创新

原文地址:https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-mixture-of-experts #mermaid-svg-FU7YUSIfuXO6EVHa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-FU7YUSIfuXO6EVHa .error-icon{fill…

SpringBoot项目集成ElasticSearch

1. 项目背景 处于失业找工作的阶段&#xff0c;随便写写吧~ 没啥背景&#xff0c;没啥意义&#xff0c;Java后端越来越卷了。第一学历不是本科&#xff0c;感觉真的是没有一点路可走。 如果有路过的小伙伴&#xff0c;如果身边还有坑位&#xff0c;不限第一学历的话&#xff0…

DeepSeek大模型深度解析:架构、技术与应用全景

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 一、大模型时代与DeepSeek的定位1.1 大模型发展历程回顾大模型发展历程时间轴&#xff08;20…

Dubbo+Zookeeper

Apache ZooKeeper 通过当前页面下载Zookeeper 在这里启动zookeeper 可以根据这个页面简单学习一下&#xff0c;但是没有集成mysql&#xff0c;也会出现一些报错&#xff0c;且在这之后我们要使用的管理页面是vue的dubbo-admin dubbo学习三&#xff1a;springboot整合dubbozo…

从厨电模范到数字先锋,看永洪科技如何助力方太集团开启数字新征程

在数字化洪流席卷全球的宏大背景下&#xff0c;企业转型升级的紧迫性与重要性日益凸显&#xff0c;成为驱动行业进步的关键引擎。在这一波澜壮阔的转型浪潮中&#xff0c;方太集团——厨电领域的璀璨明珠&#xff0c;以其前瞻性的战略视野和不懈的创新精神&#xff0c;携手数据…

前端基础之组件自定义事件

我们可以通过使用给组件绑定事件&#xff0c;当组件触发该事件时&#xff0c;就能进行值得返回 我们可以使用v-on属性来给子组件绑定自定义事件&#xff0c;此时该事件就会存在vc中&#xff0c;然后通过this.$emit来触发绑定的事件&#xff0c; 这样就能实现不需要app.vue来给子…

基于DeepSeek(本地部署)和RAGFlow构建个人知识库

总结自视频&#xff08;很强的小姐姐视频&#xff0c;讲解清晰明了&#xff09;&#xff1a;【知识科普】【纯本地化搭建】【不本地也行】DeepSeek RAGFlow 构建个人知识库_哔哩哔哩_bilibili 1. 背景 deepseek官方网页版也虽然很强&#xff0c;能够满足绝大部分需求&#xf…