PaddleOCR表格识别镜头专利并输入

在复现镜头专利时,往往会需要按照专利表格中的内容输入数据,这个过程繁琐且容易出错。本项目拟采用PaddleOCR识别专利表格信息,并利用Zemax和CodeV的API识别输入。

开源项目链接:PaddlePaddle/PaddleOCR at release/3.3

该文件工作目录禁止存在中文

部署方法

安装anaconda

如果已安装并部署好可跳过。

需要注意,anaconda和python安装一个就可以,最好不要重复安装,否则会导致部分下载路径冻结。

anaconda安装链接可参考:最新版最详细Anaconda新手安装+配置+环境创建教程_anaconda配置-CSDN博客

还需要修改pip下载路径,否则会占用大量C盘空间,方法可参考:conda环境配置、pip安装位置问题与解决_conda安装和pip安装包位置-CSDN博客

CUDA和CUDNN安装

这步如果电脑无英伟达GPU或者想使用CPU部署可以跳过。CPU跑一张图片的时间大概在十几秒。

注意如果确保兼容的情况下,要安装CUDA12.6或者CUDA11.8。

2025 CUDA 和 cuDNN 在 Windows 上如何安装配置(保姆级详细版)_windows安装cuda-CSDN博客

这里如果C盘空间够的话可以直接装在C盘,装在其他盘有的时候会出现问题。

进入虚拟环境

执行下面两行指令,创建并进入虚拟环境

1
2
conda create -n table_classification python=3.9
conda activate table_classification

然后安装Zemax与Python通信所需要的包。

1
python -m pip install pythonnet

安装paddlepaddle

开始使用_飞桨-源于产业实践的开源深度学习平台

进入上面的网页链接,由于我的电脑没有GPU,所以选择CPU模式运行。建议使用gpu否则速度会很慢,但是需要安装cuda和cudnn。

GPU版本

注意!!!!!!!一定要选择旧版本安装,安装3.2.0版本,否则后续推理会出错

image-20260317110455552

1
2
# CUDA 12.6
python -m pip install paddlepaddle-gpu==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/

CPU版本

在conda的虚拟环境里输入。

1
python -m pip install paddlepaddle==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/

验证安装情况

安装后输入python进入解释器,然后输入import paddle,在输入paddle.utils.run_check(),如果出现PaddlePaddle is installed successfully!,则说明安装成功。

在我安装后,输入import paddle出现报错:

1
No ccache found. Please be aware that recompiling all source files may be required. You can download and install ccache from: https://github.com/ccache/ccache/blob/master/doc/INSTALL.md

这个警告是说当前环境中没有找到ccache。这个工具可以加快重新编译的速度,不安装没有影响,但是如果希望提高编译速度,可以输入如下指令

1
conda install -c conda-forge ccache

警告解除。

更多警告可以参考【Mac】安装 PaddleOCR_userwarning: no ccache found. please be aware that-CSDN博客

安装Layout-Parser

1
pip3 install -U https://paddleocr.bj.bcebos.com/whl/layoutparser-0.0.0-py3-none-any.whl

安装PaddleOCR

这里是有两个包,PaddleOCR whl包(仅预测)PaddleOCR源码(预测+训练)。本项目预计只使用预测功能,因此仅安装PaddleOCR whl包

1
pip install "paddleocr==3.3.3" # 一定要使用3.3.3版本,否则版本不匹配

运行程序

命令行启动

打开Anaconda Prompt,

1
conda activate table_classification

然后切换路径到工程文件夹。注意需要先切换盘符,在使用cd切换路径

1
2
e:
cd E:\cucumberBlog

然后执行

1
python main.py

VScode启动

参考这个链接对VScode进行配置:全网最简约的Vscode配置Anaconda环境(百分百成功)-阿里云开发者社区

然后在VScode里直接运行程序就可以。

使用方法

程序界面如下

PixPin_2026-03-17_11-14-49

读取图片

对专利表格进行截图,并存放在工程文件夹下的table_pic文件夹内,可以截取多张图片。

存放好后点击读取图片按键,框选多张图片打开。

PixPin_2026-03-17_11-17-04

识别图片

读取完图片点击识别图片。这里程序可能会出现未响应,不用理会等待即可。

程序第一次运行时,会自动下载模型文件,耗时较长(大约几分钟),等得即可。

image-20260317112029588

识别完成后,在output文件夹会生成xlsx表格文件,里面就是识别内容。

写入模板

考虑到不同专利的格式不一致,因此要求用户合适数据无误后,手动粘贴信息到模板中。

PixPin_2026-03-17_11-31-47

面数 曲率半径 厚度 nd vd 光阑面(光阑填1,非光阑不用填) 表面类型(非球面填1,球面不用填) 圆锥系数 A4 A6 A8 A10 A12 A14

模板格式如上表所示,直接填写就行,目前程序只能执行最基本的写入表格内的信息,无法实现复杂情况(如系统数据,变焦、偏心、倾斜),这部分内容比较少用户可以手动输入。

写入Zemax

打开一个新的zemax文件(因为程序在写入时会清空zemax里的所有数据),然后点击编程–交互扩展。然后点击将模板输入Zemax等待程序运行完成即可。

image-20260317113617151

写入CodeV

打开codev,我的版本是2023.1

在导航栏点击工具–自定义–状态栏。把用户界面进程ID放到选定项目里。

image-20260317113812237

然后就可以在右下角看到PID。(图片里的PID是31788)

image-20260317113845202

点击将模板输入Codev,在弹出的窗口里输入PID,等待执行完成即可。

开发记录

安装anaconda

这一步不做赘述。

需要注意需要修改anaconda路径和pip下载路径,否则会侵占大量C盘空间。

我使用的python版本为3.9版本。

可以执行

1
2
conda create -n table_classification python=3.9
conda activate table_classification

然后安装Zemax与Python通信所需要的包。

1
python -m pip install pythonnet

安装paddlepaddle

开始使用_飞桨-源于产业实践的开源深度学习平台

进入上面的网页链接,由于我的电脑没有GPU,所以选择CPU模式运行。建议使用gpu否则速度会很慢,但是需要安装cuda和cudnn。

注意!!!!!!!一定要选择旧版本安装,安装3.2.0版本,否则后续推理会出错

PixPin_2026-03-16_13-21-11

在conda的虚拟环境里输入。

1
python -m pip install paddlepaddle==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/

安装后输入python进入解释器,然后输入import paddle,在输入paddle.utils.run_check(),如果出现PaddlePaddle is installed successfully!,则说明安装成功。

在我安装后,输入import paddle出现报错:

1
No ccache found. Please be aware that recompiling all source files may be required. You can download and install ccache from: https://github.com/ccache/ccache/blob/master/doc/INSTALL.md

这个警告是说当前环境中没有找到ccache。这个工具可以加快重新编译的速度,不安装没有影响,但是如果希望提高编译速度,可以输入如下指令

1
conda install -c conda-forge ccache

警告解除。

更多警告可以参考【Mac】安装 PaddleOCR_userwarning: no ccache found. please be aware that-CSDN博客

安装Layout-Parser

1
pip3 install -U https://paddleocr.bj.bcebos.com/whl/layoutparser-0.0.0-py3-none-any.whl

安装PaddleOCR

这里是有两个包,PaddleOCR whl包(仅预测)PaddleOCR源码(预测+训练)。本项目预计只使用预测功能,因此仅安装PaddleOCR whl包

1
pip install "paddleocr==3.3.3" # 一定要使用3.3.3版本,否则版本不匹配

运行代码进行表格识别

这部分内容仅为了记录开发过程,如果需要查看最终代码请跳转到“完整代码”章节查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os
os.environ["PADDLE_PDX_CACHE_HOME"] = os.path.dirname(os.path.abspath(__file__))

from paddlex import create_pipeline

pipeline = create_pipeline(pipeline="table_recognition",device='cpu')

output = pipeline.predict(
input=r"E:\table_classification\PixPin_2026-03-16_13-35-36.png",
use_doc_orientation_classify=False,
use_doc_unwarping=False,
use_table_cells_ocr_results=False,
)

for res in output:
res.print()
res.save_to_img("./output/")
res.save_to_xlsx("./output/")

其中os.environ["PADDLE_PDX_CACHE_HOME"] = os.path.dirname(os.path.abspath(__file__))是为了修改下载模型的路径到当前文件夹下,防止下载到C盘中。

识别情况:PixPin_2026-03-16_13-35-36

识别框:PixPin_2026-03-16_13-35-36_table_cell_img

表格输出:PixPin_2026-03-16_17-21-15

表格修正

可以看出,生成的表格存在一定的空格,因此后续对表格进行删除空格操作。

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
import os
os.environ["PADDLE_PDX_CACHE_HOME"] = os.path.dirname(os.path.abspath(__file__))

from openpyxl import load_workbook
from paddlex import create_pipeline


def remove_spaces_from_xlsx_files(output_dir):
if not os.path.isdir(output_dir):
return

for filename in os.listdir(output_dir):
if not filename.lower().endswith(".xlsx"):
continue

file_path = os.path.join(output_dir, filename)
workbook = load_workbook(file_path)
changed = False

for sheet in workbook.worksheets:
for row in sheet.iter_rows():
for cell in row:
if isinstance(cell.value, str):
new_value = cell.value.replace(" ", "")
if new_value != cell.value:
cell.value = new_value
changed = True

if changed:
workbook.save(file_path)

pipeline = create_pipeline(pipeline="table_recognition",device='cpu')

output = pipeline.predict(
input=r"E:\table_classification\PixPin_2026-03-16_17-26-50.png",
use_doc_orientation_classify=False,
use_doc_unwarping=False,
use_table_cells_ocr_results=False,
)

for res in output:
res.print()
res.save_to_img("./output/")
res.save_to_xlsx("./output/")

remove_spaces_from_xlsx_files("./output/")

单列表格无法生成xlsx

发现单列表格无法生成xlsx文件,所以加入了输出json文件辅助生成表格。

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def has_generated_table_xlsx(output_dir, input_path):
base_name = os.path.splitext(os.path.basename(input_path))[0]
if not os.path.isdir(output_dir):
return False

for filename in os.listdir(output_dir):
if not filename.lower().endswith(".xlsx"):
continue
if not filename.startswith(base_name):
continue
if filename.endswith("_ocr_fallback.xlsx"):
continue
if filename.endswith("_table.xlsx") or "_table_" in filename:
return True
return False


def create_fallback_xlsx(output_dir, input_path, rec_texts):
os.makedirs(output_dir, exist_ok=True)
base_name = os.path.splitext(os.path.basename(input_path))[0]
file_path = os.path.join(output_dir, f"{base_name}_ocr_fallback.xlsx")

workbook = Workbook()
sheet = workbook.active
sheet.title = "OCR_Texts"

if rec_texts:
for txt in rec_texts:
sheet.append([str(txt)])
else:
sheet.append([""])

workbook.save(file_path)


def read_rec_texts_from_json(output_dir, input_path):
base_name = os.path.splitext(os.path.basename(input_path))[0]
json_path = os.path.join(output_dir, f"{base_name}_res.json")
if not os.path.exists(json_path):
return []

try:
with open(json_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data.get("overall_ocr_res", {}).get("rec_texts", [])
except Exception:
return []


def extract_payload(result_obj):
raw = getattr(result_obj, "res", None)
if isinstance(raw, dict):
payload = raw.get("res", raw)
else:
payload = raw

if isinstance(payload, dict):
return payload

if hasattr(payload, "to_dict"):
try:
data = payload.to_dict()
if isinstance(data, dict):
return data
except Exception:
pass

if hasattr(payload, "__dict__"):
try:
data = vars(payload)
if isinstance(data, dict):
return data
except Exception:
pass

return {}

for res in output:
rec_texts = []
res.print()
res.save_to_img("./output/")
res.save_to_xlsx("./output/")
res.save_to_json("./output/")
try:
payload = extract_payload(res)
input_path = payload.get("input_path", input_path)
rec_texts = read_rec_texts_from_json("./output/", input_path)
if not rec_texts:
rec_texts = payload.get("overall_ocr_res", {}).get("rec_texts", [])
except Exception:
input_path = input_path
rec_texts = []

if not has_generated_table_xlsx("./output/", input_path):
create_fallback_xlsx("./output/", input_path, rec_texts)

创建表格模板

由于不同专利里表格结构不一致,因此需要将识别出来的表格手动填入模板中。

面数 曲率半径 厚度 nd vd 光阑面(光阑填1,非光阑不用填) 表面类型(非球面填1,球面不用填) 圆锥系数 A4 A6 A8 A10 A12 A14

模板如上。

Python与Zemax通信

使用交互式方法。

Python与CodeV通信

使用交互式方法。