暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

OnnxOCR_PG_ONNX:探讨在PostgreSQL中运行ONNX模型更多可能的验证性项目

原创 小满未满、 2025-11-18
527

前言

在上一篇在PostgreSQL中运行ONNX模型 —— pg_onnx文章中,我用机器学习中最简单的模型——线性回归做了测试,可能有朋友觉得就一个线性回归并证明不了什么。那么在这一篇文章,让我们来看一下在PostgreSQL中进行模型推理的更多可能。原本我打算从头开始写一个全新的项目进行验证,但是没那么多的时间让我去折腾这个事情,不过既然仅仅是验证的话,找个原本使用ONNX模型的应用,来简单处理一下就能够完美的达成我想要的目标,然后我就找到了OnnxOCR这个项目,下面简单补充一些OCR的内容。

OCR简单介绍

前一阵子DeepSeek-OCR也是非常火热,且印象中OCR也出现很久了,算不得新的技术,所以这里就简单带过一下。OCR(光学字符识别,Optical Character Recognition)是一种将图像中的印刷体或手写体文字转化为计算机可编辑、可搜索数字文本的技术,本质是 “图像转文字” 的过程,核心目标是替代手动输入以快速提取文字信息实现数字化复用,其输入可以是扫描件、照片、截图、PDF 图片页等包含文字的图像,输出则是 TXT、Word 等可编辑格式的文本,常见应用于文档数字化(如纸质合同、书籍档案扫描转电子文本)、日常工具(如截图文字提取、图片翻译、证件信息自动录入)及行业场景(如票据识别、车牌识别、营业执照信息提取)等。

OnnxOCR项目

Image
  • 脱离深度学习训练框架:可直接用于部署的通用 OCR。
  • 跨架构支持:在算力有限、精度不变的情况下,使用 PaddleOCR 转成 ONNX 模型,重新构建的可部署在 ARM 架构和 x86 架构计算机上的 OCR 模型。
  • 高性能推理:在同样性能的计算机上推理速度加速。
  • 多语言支持:单模型支持 5 种文字类型:简体中文、繁体中文、中文拼音、英文和日文。
  • 模型精度:与 PaddleOCR 模型保持一致。
  • 国产化适配:重构代码工程架构,只需简单进行推理引擎的修改,即可适配更多国产化显卡。

额外的一点就是作者写的代码很清晰明了,很容易修改成我想要的样子。

涉及到的模型

OnnxOCR中使用了三个ONNX模型配合完成任务,这三个模型分别是:

  • 文本检测模型(det) - “定位文字在哪里”
  • 文本方向分类模型(cls) - “把文字摆正”
  • 文本识别模型(rec) - “解读文字内容”

三步走

  1. det 模型检测文本区域,分析原始图像,生成文本框坐标。例:检测到发票上的 “金额”、“日期” 等文字区域。
  2. 文本块提取与方向校正,根据 det 输出的坐标,从原图中裁剪出文本块,将每个文本块送入 cls 模型判断方向,如果检测到非 0° 方向(如 180°)且置信度达标,自动旋转校正。
  3. 文本识别与结果整合,校正后的文本块送入 rec 模型识别内容,rec 输出文字结果和置信度,最终结果将文本内容与原始坐标关联,形成完整 OCR 输出(包括文字内容、位置和可信度)。

流程大概如下(AI 生成):

+----------------+      +----------------+      +----------------+
|    原始图像    |----→|    det模型     |----→|  文本框坐标   |
+----------------+      +----------------+      +-------+--------+
                                        |
                                        v
                      +----------------+
                      |  裁剪文本块    |
                      +--------+-------+
                               |
                               v
                +---------------+       +---------------+
                |   cls模型     |-------|   方向校正    |
                +---------------+       +-------+-------+
                                        |
                                        v
                        +---------------+
                        |   rec模型     |------→  文字识别结果
                        +---------------+

OnnxOCR_PG_ONNX

从名字上也不难看出,我就是将两个项目融合到了一起。

源码修改

在了解了上面的一系列知识之后,就可以来尝试着修改代码了。而修改源码,其实就是封装和替换了一些接口,然后将原本调用模型的接口换成了执行PostgreSQL中pg_onnx提供的函数接口,当然还需要考虑数据转换以及数据库连接之类的。对源码部分修改感兴趣的朋友开源看一下这一次的commit

环境要求

在环境准备这一块,python环境同OnnxOCR一致,同时需要PostgreSQL安装好pg_onnx插件

python>=3.6  

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt  

将模型导入数据库

CUDA和代码路径需要自行设置

SELECT pg_onnx_import_model(
               'cls',
               'v1', 
               PG_READ_BINARY_FILE('你的代码路径/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/cls/cls.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               '相关描述'
       );

SELECT pg_onnx_import_model(
               'det',
               'v1', 
               PG_READ_BINARY_FILE('你的代码路径/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/det/det.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               '相关描述'
       );

SELECT pg_onnx_import_model(
               'rec',
               'v1', 
               PG_READ_BINARY_FILE('你的代码路径/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/rec/rec.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               '相关描述'
       );

其余配置

仅需要关心数据库的基本配置,按照实际修改config.py

DB_CONFIG = {
    "dbname": "test",
    "user": "postgres",
    "password": "postgres",
    "host": "127.0.0.1",
    "port": "5432"
}

运行

运行命令也非常简单

python test_ocr.py  

以奥巴马的身份证照片为例,来自另一个项目的测试图片

Image

最终结果

(onnx-env) postgres@zxm-VMware-Virtual-Platform:~/OnnxOCR_PG_ONNX$ python test_ocr.py
total time: 29.654
[[[92.0, 198.0], [742.0, 175.0], [747.0, 305.0], [97.0, 328.0]], ('姓名奥巴马', 0.9977725505828857)]
[[[90.0, 415.0], [1328.0, 396.0], [1331.0, 538.0], [92.0, 556.0]], ('性别男民族肯尼亚', 0.9989805296063423)]
[[[90.0, 646.0], [1397.0, 637.0], [1397.0, 758.0], [91.0, 767.0]], ('出生1961年8月4日', 0.9986594644459811)]
[[[98.0, 885.0], [375.0, 892.0], [372.0, 994.0], [96.0, 986.0]], ('住址', 0.9953028857707977)]
[[[377.0, 892.0], [1522.0, 883.0], [1523.0, 1001.0], [378.0, 1011.0]], ('华盛顿特区宜宾法尼亚', 0.9969237744808197)]
[[[392.0, 1083.0], [1207.0, 1083.0], [1207.0, 1210.0], [392.0, 1210.0]], ('大道1600号白宫', 0.9857945972018771)]
[[[83.0, 1467.0], [752.0, 1474.0], [750.0, 1595.0], [81.0, 1589.0]], ('公民身份号码', 0.9998583197593689)]
[[[923.0, 1483.0], [2384.0, 1461.0], [2386.0, 1592.0], [925.0, 1613.0]], ('123456196108047890', 0.996591372622384)]

完整测试

(onnx-env) postgres@zxm-VMware-Virtual-Platform:~$ git clone https://github.com/Z-Xiao-M/OnnxOCR_PG_ONNX.git
Cloning into 'OnnxOCR_PG_ONNX'...
remote: Enumerating objects: 308, done.
remote: Counting objects: 100% (93/93), done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 308 (delta 47), reused 42 (delta 42), pack-reused 215 (from 1)
Receiving objects: 100% (308/308), 90.25 MiB | 10.60 MiB/s, done.
Resolving deltas: 100% (108/108), done.
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~$ pwd
/home/postgres
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~$ psql
psql (19devel)
Type "help" for help.

postgres=# SELECT pg_onnx_import_model(
               'cls',
               'v1', 
               PG_READ_BINARY_FILE('/home/postgres/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/cls/cls.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               'cls'
       );
LOG:  Waiting for background worker to start
 pg_onnx_import_model 
----------------------
 t
(1 row)

postgres=# SELECT pg_onnx_import_model(
               'det',
               'v1', 
               PG_READ_BINARY_FILE('/home/postgres/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/det/det.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               'det'
       );
 pg_onnx_import_model 
----------------------
 t
(1 row)

postgres=# SELECT pg_onnx_import_model(
               'rec',
               'v1', 
               PG_READ_BINARY_FILE('/home/postgres/OnnxOCR_PG_ONNX/onnxocr/models/ppocrv5/rec/rec.onnx')::bytea,
               '{"cuda": false}'::jsonb, 
               'rec'
       );
 pg_onnx_import_model 
----------------------
 t
(1 row)

postgres=# \q
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~$ cd OnnxOCR_PG_ONNX
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~/OnnxOCR_PG_ONNX$ ls
app-service.py  config.py  db  Dockerfile  draw_ocr.jpg  LICENSE  onnxocr  Readme.md  requirements.txt  result_img  static  templates  test.jpg  test_ocr.py  webui.py
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~/OnnxOCR_PG_ONNX$ vim config.py 
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~/OnnxOCR_PG_ONNX$ python test_ocr.py  
total time: 26.511
[[[92.0, 198.0], [742.0, 175.0], [747.0, 305.0], [97.0, 328.0]], ('姓名奥巴马', 0.9977725505828857)]
[[[90.0, 415.0], [1328.0, 396.0], [1331.0, 538.0], [92.0, 556.0]], ('性别男民族肯尼亚', 0.9989805296063423)]
[[[90.0, 646.0], [1397.0, 637.0], [1397.0, 758.0], [91.0, 767.0]], ('出生1961年8月4日', 0.9986594644459811)]
[[[98.0, 885.0], [375.0, 892.0], [372.0, 994.0], [96.0, 986.0]], ('住址', 0.9953028857707977)]
[[[377.0, 892.0], [1522.0, 883.0], [1523.0, 1001.0], [378.0, 1011.0]], ('华盛顿特区宜宾法尼亚', 0.9969237744808197)]
[[[392.0, 1083.0], [1207.0, 1083.0], [1207.0, 1210.0], [392.0, 1210.0]], ('大道1600号白宫', 0.9857945972018771)]
[[[83.0, 1467.0], [752.0, 1474.0], [750.0, 1595.0], [81.0, 1589.0]], ('公民身份号码', 0.9998583197593689)]
[[[923.0, 1483.0], [2384.0, 1461.0], [2386.0, 1592.0], [925.0, 1613.0]], ('123456196108047890', 0.996591372622384)]
(onnx-env) postgres@zxm-VMware-Virtual-Platform:~/OnnxOCR_PG_ONNX$ cat config.py
DB_CONFIG = {
    "dbname": "postgres",
    "user": "postgres",
    "password": "postgres",
    "host": "127.0.0.1",
    "port": "5432"
}

MODEL_DET = ("det", "v1")
MODEL_CLS = ("cls", "v1")
MODEL_REC = ("rec", "v1")

OUTPUT_KEY_DET = "fetch_name_0"
OUTPUT_KEY_CLS = "softmax_0.tmp_0"
OUTPUT_KEY_REC = "fetch_name_0"

声明

相对原项目OnnxOCR,OnnxOCR_PG_ONNX的执行速度变慢是正常的,因为将模型推理的接口换成了数据库内执行,这中间存在数次模型推理的调用,每次调用都需要通过网络进行通信且数据量非常庞大。所以事实上OnnxOCR并不会在这种简单改造中受益,因为原项目本就和PostgreSQL数据库没有交集。但是我的目的仅仅是验证在PostgreSQL库中进行机器学习推理能做到何种程度,通过实际的现象来看,没啥太大的问题,这里的三个模型也运行正常。至于可行性,在上一篇文章中线性回归就以及验证过了。

最后修改时间:2025-11-18 10:35:15
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论