Files
PACS/UPP列表处理/通用图片表格识别工作流模板.md
2026-05-25 12:33:24 +08:00

618 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 通用图片表格识别工作流模板
本文档用于把一个空白目录整理成“图片列表 / 图片表格 OCR 识别 -> 结构化归档 -> 人工复核 -> 合并 -> 可选入库”的通用工作流模板。
模板抽象自 `~/Desktop/HIS数据处理/患者列表处理` 的成熟流程,但这里不绑定 HIS、患者列表、UPP 或任何具体业务字段。后续遇到类似“多张图片中包含规则表格,需要批量识别成结构化记录”的任务时,可先复制本模板,再人工补充腾讯云 API、Gitea、PostgreSQL、字段清洗规则和业务校验规则。
## 1. 适用场景
适合:
- 输入是一批或多批图片,图片中包含列表、目录、清单、统计表、检查单、排班表等规则表格。
- 需要保留每条结构化记录的来源图片、图片内行号、批次名等追溯信息。
- OCR 结果需要自动校验,也允许人工复核和人工修正。
- 最终结果既要保存在本地 JSON / CSV也可能同步到 PostgreSQL 或其他数据库。
- 工作流需要可提交到 Gitea但不能提交密钥、图片原件、OCR 缓存和识别结果。
不适合直接套用:
- 图片完全无表格结构,需要复杂版面理解。
- 每张图片字段位置差异极大,无法用统一列名和统一清洗规则描述。
- 任务要求实时在线处理,而不是批量离线归档。
## 2. 模板使用方式
新任务开始时,先人工填写本节占位信息。
```text
项目名称:[填写,例如 PACS UPP 列表处理]
记录对象:[填写,例如 UPP 列表记录 / 检查记录 / 患者记录]
输入图片根目录:[填写,例如 待处理-xxx图片集群/批次文件夹名]
输出结果根目录:[填写,例如 数据处理结果区/已处理-xxx图片集群/批次文件夹名-列表归档结果]
主唯一键:[填写,例如 住院号 / 检查号 / accession_no / 影像号 / 组合键]
业务分类维度:[填写,例如 大科室、子科室;或 设备、项目类型;可为空]
目标数据库表:[填写,例如 "Generic_Image_Table_Records"]
Gitea 仓库:[填写,例如 https://gitea.example.com/team/repo.git]
```
字段定义表:
| 序号 | 字段名 | 是否必填 | 清洗规则 | 校验规则 | 备注 |
| --- | --- | --- | --- | --- | --- |
| 1 | `[字段1]` | 是 / 否 | `[去空格、日期规范化等]` | `[不能为空、格式等]` | `[说明]` |
| 2 | `[字段2]` | 是 / 否 | `[待补充]` | `[待补充]` | `[说明]` |
| 3 | `[字段3]` | 是 / 否 | `[待补充]` | `[待补充]` | `[说明]` |
建议先明确字段顺序。图片表格 OCR 的后续清洗、CSV 导出、数据库列顺序、人工复核页面都会依赖这个顺序。
## 3. 推荐目录结构
```text
.
├── README.md
├── 工作流_本地使用版.md
├── 工作流_Gitea版.md
├── 通用图片表格识别工作流模板.md
├── 待处理-[任务名]图片集群/
│ └── [批次文件夹名]/
├── 已处理-[任务名]图片集群/
├── 数据处理工作区/
│ ├── 01_任务配置.template.json
│ ├── 01_任务配置.json
│ ├── 02_图片表格OCR归档.py
│ ├── 03_人工复核修正.template.json
│ ├── 03_人工复核修正.json
│ ├── 04_合并批次结果.py
│ ├── 05_同步PostgreSQL单表.py
│ ├── 06_PostgreSQL建表结构.template.sql
│ ├── 06_PostgreSQL建表结构.sql
│ ├── 07_处理程序说明.md
│ └── 08_本地运行流程.template.sh
├── 数据处理结果区/
│ ├── 已处理-[任务名]图片集群/
│ └── 信息记录/
└── 人工复核网页端/
```
目录职责:
- `待处理-[任务名]图片集群/`:新下载、尚未处理的原始图片批次。
- `已处理-[任务名]图片集群/`:确认完成归档后的原始图片批次。
- `数据处理工作区/`:任务配置、处理脚本、人工修正模板、数据库结构、说明和本地运行流程模板。
- `数据处理结果区/已处理-[任务名]图片集群/`:每个批次的 OCR 缓存、拼接图、结构化 JSON、CSV、复核报告。
- `数据处理结果区/信息记录/`:全局汇总、批次汇总、重复键报告、缺失键报告。
- `人工复核网页端/`:可选,用于可视化查看来源图片、修正字段、抽查和同步数据库。
提交到 Gitea 时,只提交程序、模板、空 README、SQL 结构和说明文档。不要提交图片、OCR 缓存、识别结果、人工修正实数据、`.env`、数据库导出文件。
## 4. 配置占位
### 4.1 腾讯云 OCR
推荐使用环境变量,不要写入脚本或文档。
```bash
export TENCENTCLOUD_SECRET_ID='填入腾讯云 SecretId'
export TENCENTCLOUD_SECRET_KEY='填入腾讯云 SecretKey'
export TENCENTCLOUD_REGION='ap-shanghai'
```
建议脚本支持:
```text
OCR 引擎:[table-v3 / general-accurate / 其他]
默认接口RecognizeTableAccurateOCR
默认地域ap-shanghai
单次超时60-120 秒
失败重试0-2 次
调用间隔0.2-1 秒
```
### 4.2 PostgreSQL
数据库是可选模块。没有确认字段和表名之前,先只产出本地 JSON / CSV。
```bash
export WORKFLOW_DB_HOST='数据库主机'
export WORKFLOW_DB_PORT='5432'
export WORKFLOW_DB_NAME='数据库名'
export WORKFLOW_DB_USER='数据库用户'
export WORKFLOW_DB_PASSWORD='数据库密码'
```
待人工补充:
```text
正式表名:[填写]
主键策略:[bigserial / uuid / 来源字段组合]
唯一约束:[填写主唯一键或组合唯一键]
允许为空字段:[填写]
必须人工复核才允许入库的异常:[填写]
索引字段:[填写常用查询字段]
```
### 4.3 Gitea
```text
仓库地址:[填写]
默认分支:[main / master / 其他]
提交范围程序、模板、说明、SQL、示例配置
排除范围密钥、图片、OCR 缓存、处理结果、人工修正实数据、数据库密码
```
建议 `.gitignore` 至少包含:
```gitignore
.env
*.env
__pycache__/
*.pyc
待处理-*图片集群/
已处理-*图片集群/
数据处理结果区/
数据处理工作区/03_人工复核修正.json
人工复核网页端/instance/
```
## 5. 批处理脚本能力清单
`02_图片表格OCR归档.py` 建议具备以下能力:
1. 扫描输入目录,识别 `.png``.jpg``.jpeg``.bmp`
2. 按自然序排序图片,例如 `第2页.png` 应排在 `第10页.png` 前面。
3. 可按第一层文件夹做业务分类,例如科室、设备、项目、来源系统。
4. 将多张图片纵向拼接,降低 OCR 调用次数。
5. 拼接时支持上下白边,例如 `--image-padding-y 24`,减少贴边表格行漏识别。
6. 调用 OCR 接口,响应写入 `raw_ocr/` 缓存。
7. 从 OCR 响应解析表格行和列,生成统一字段顺序的记录。
8. 将每条记录绑定来源图片、图片名、图片内行号、拼接组、OCR 请求 ID。
9. 对字段做清洗,例如空格归一、日期规范化、编号纠错、列错位修正。
10. 对记录做自动校验,输出 `自动复核通过``需人工复核`
11. 支持读取 `03_人工复核修正.json` 后用缓存重建结果。
12. 支持主唯一键去重,输出重复键报告。
13. 输出结构化 JSON、JSONL、CSV、复核报告、汇总信息。
推荐命令参数:
```bash
python3 数据处理工作区/02_图片表格OCR归档.py \
--config "数据处理工作区/01_任务配置.json" \
--input "待处理-[任务名]图片集群/[批次文件夹名]" \
--output "数据处理结果区/已处理-[任务名]图片集群/[批次文件夹名]-列表归档结果" \
--corrections "数据处理工作区/03_人工复核修正.json" \
--ocr-engine table-v3 \
--batch-size 6 \
--image-padding-y 24 \
--workers 1 \
--folder-workers 2 \
--timeout 90 \
--max-retries 1
```
只用已有 OCR 缓存重建:
```bash
python3 数据处理工作区/02_图片表格OCR归档.py \
--config "数据处理工作区/01_任务配置.json" \
--input "待处理-[任务名]图片集群/[批次文件夹名]" \
--output "数据处理结果区/已处理-[任务名]图片集群/[批次文件夹名]-列表归档结果" \
--ocr-engine table-v3 \
--batch-size 6 \
--image-padding-y 24 \
--rebuild-from-cache
```
## 6. OCR 策略模板
建议默认策略:
- 图片预处理:保持原图,不裁切;必要时统一 RGB拼接图背景使用白色。
- 拼接策略:先按 `batch-size=6` 纵向拼接;如果漏行、超时或接口失败,自动降到 `4/3/2/单张`
- 白边策略:上下各加 `24px` 白边作为初始值;如果图片行距很小或边缘文字贴边,可增加到 `32px``40px`
- 缓存策略:每个拼接图对应一个 OCR JSON 缓存;默认命中缓存不重新请求;加 `--force` 才重新识别。
- 行数校验按图片高度、已知行数或模板行高估算预期行数OCR 返回行数偏少时触发降档。
- 失败处理:单个拼接组失败时记录错误,不让整个批次无声失败;正式任务结束后必须检查错误列表。
输出目录建议:
```text
[批次]-列表归档结果/
├── merged_images/
│ └── [来源文件夹]/
├── raw_ocr/
│ └── [来源文件夹]/
├── 列表_分类归档.json
├── 图片表格_结构化.json
├── 图片表格_记录.jsonl
├── 图片表格_记录.csv
├── 复核报告.json
├── 重复主键报告.json
└── 信息记录/
├── 汇总.json
└── 分类汇总.csv
```
## 7. 结构化记录模板
建议每条记录采用分层结构,便于同时支持业务展示、复核和数据库同步。
```json
{
"处理批次": "[批次名]",
"业务分类1": "[例如大科室,可为空]",
"业务分类2": "[例如子科室,可为空]",
"来源文件夹": "[原始文件夹名]",
"记录信息": {
"[字段1]": "[值]",
"[字段2]": "[值]",
"[字段3]": "[值]"
},
"图片信息": {
"图片路径": "[原始图片路径]",
"图片名": "[原始图片名]",
"图片序号": "[自然排序序号或页码]",
"图片内行号": 1,
"拼接组序号": 1,
"拼接图片路径": "[merged_images 路径]",
"OCR缓存路径": "[raw_ocr 路径]",
"OCR请求ID": "[接口返回 RequestId]"
},
"复核": {
"状态": "自动复核通过",
"提示": [],
"人工修正": false,
"人工备注": ""
}
}
```
复核状态建议统一:
- `自动复核通过`:字段清洗和规则校验后没有发现明显问题。
- `需人工复核`:缺必填项、格式异常、行数可疑、主键缺失、时间逻辑异常等。
- `人工复核通过`:命中人工修正配置,修正后通过校验。
- `AI修改-待确认`:可作为网页端草稿状态,不应直接入库为人工确认结果。
## 8. 字段清洗和校验模板
每个任务都需要人工补充清洗规则,不建议把某个业务的规则硬套到新任务。
基础清洗:
- 全角转半角。
- 去除多余空格、换行、不可见字符。
- 统一日期格式,例如 `YYYY-MM-DD HH:MM:SS`
- 统一编号格式,例如去空格、统一大小写、修正常见 OCR 误识别。
- 处理列错位,例如长文本吞入下一列、时间字段左移、数字字段被识别到备注列。
基础校验:
- 主唯一键不能为空。
- 必填字段不能为空。
- 数字字段必须可转成整数或小数。
- 日期字段必须符合目标格式。
- 起止时间不能倒置;如果倒置,应标记为 `需人工复核`
- 同批次或全局主唯一键重复时,必须输出重复报告。
任务专用校验占位:
```text
[规则1]
[规则2]
[规则3]
```
去重策略占位:
```text
主唯一键:[填写]
重复时保留:[后出现记录 / 字段更完整记录 / 人工复核通过记录 / 其他]
缺少主唯一键:[剔除 / 保留但需人工复核 / 禁止入库]
重复报告文件名:[填写]
```
## 9. 人工复核模板
人工修正文件建议只在本地存在,仓库只保留 `.template.json`
`数据处理工作区/03_人工复核修正.template.json`
```json
[
{
"图片路径": "待处理-[任务名]图片集群/[批次]/[图片名].png",
"图片内行号": 1,
"记录信息": {
"[字段1]": "[人工确认值]",
"[字段2]": "[人工确认值]"
},
"复核选项": {},
"复核备注": "[可选]"
}
]
```
人工复核顺序:
1. 打开批次结果中的 `复核报告.json`
2. 根据 `图片路径``图片名``图片内行号` 回看原图或网页端裁剪图。
3. 将确认值写入 `03_人工复核修正.json`
4. 使用 `--rebuild-from-cache` 重建,不重复调用 OCR。
5. 检查 `复核报告.json` 中需复核数量是否下降。
6. 重新合并全局结果。
如果使用网页端,建议它至少支持:
- 批次列表和汇总。
- 按复核状态过滤记录。
- 原图裁剪定位到图片内行。
- 编辑字段并保存到人工修正 JSON。
- 数据库可用时同步单条记录;数据库不可用时保留待同步状态。
- 抽查功能可选AI 输出只作为辅助,不直接覆盖人工确认结果。
## 10. 合并批次模板
`04_合并批次结果.py` 建议扫描 `数据处理结果区/` 下所有 `*-列表归档结果`,合并每个批次的结构化结果。
推荐输出:
```text
数据处理结果区/
├── 合并_图片表格_结构化.json
├── 合并_图片表格_记录.jsonl
├── 合并_图片表格_记录.csv
└── 信息记录/
├── 全局汇总.json
├── 批次汇总.csv
├── 重复主键报告.json
└── 缺少主键报告.json
```
合并时建议重新执行全局去重,因为不同批次之间也可能出现重复主键。
运行:
```bash
python3 数据处理工作区/04_合并批次结果.py --config "数据处理工作区/01_任务配置.json"
```
合并后检查:
```text
批次数
总图片数
合并前记录数
合并后记录数
需人工复核记录数
人工修正记录数
重复主键剔除记录数
缺少主键剔除记录数
```
## 11. PostgreSQL 入库模板
`05_同步PostgreSQL单表.py` 建议只读取合并后的 JSON生成临时 CSV再用 `psql \copy` 导入正式表。
入库原则:
- 数据库只放正式查看和追溯需要的字段。
- OCR 请求号、OCR 缓存路径、拼接图路径、拼接组细节等中间态字段默认留在本地结果目录,不进入正式表,除非业务明确需要。
- 主唯一键应有唯一约束。
- 必填主键应有非空约束。
- 重要时间逻辑、状态逻辑可放入数据库 CHECK 约束。
建表示例骨架:
```sql
CREATE TABLE IF NOT EXISTS "[目标表名]" (
record_id bigserial PRIMARY KEY,
batch_name text NOT NULL,
source_folder text NOT NULL,
image_path text NOT NULL,
image_name text NOT NULL,
image_row_no integer NOT NULL,
unique_key text NOT NULL,
field_1 text,
field_2 text,
field_3 text,
review_status text NOT NULL,
review_notes text,
manual_corrected boolean NOT NULL DEFAULT false,
imported_at timestamptz NOT NULL DEFAULT now(),
audit_result text,
audit_ai_feedback text,
audit_manual_feedback text,
audit_checked_by text,
audit_checked_at timestamptz,
CONSTRAINT uq_target_unique_key UNIQUE (unique_key),
CONSTRAINT ck_target_unique_key_present CHECK (btrim(unique_key) <> '')
);
CREATE INDEX IF NOT EXISTS idx_target_batch_name ON "[目标表名]"(batch_name);
CREATE INDEX IF NOT EXISTS idx_target_source_folder ON "[目标表名]"(source_folder);
CREATE INDEX IF NOT EXISTS idx_target_review_status ON "[目标表名]"(review_status);
```
同步命令:
```bash
export WORKFLOW_DB_HOST='数据库主机'
export WORKFLOW_DB_PORT='5432'
export WORKFLOW_DB_NAME='数据库名'
export WORKFLOW_DB_USER='数据库用户'
export WORKFLOW_DB_PASSWORD='数据库密码'
python3 数据处理工作区/05_同步PostgreSQL单表.py \
--input "数据处理结果区/合并_图片表格_结构化.json" \
--schema "数据处理工作区/06_PostgreSQL建表结构.sql" \
--table '"[目标表名]"'
```
入库后核对:
```sql
SELECT count(*) FROM "[目标表名]";
SELECT review_status, manual_corrected, count(*)
FROM "[目标表名]"
GROUP BY review_status, manual_corrected;
SELECT unique_key
FROM "[目标表名]"
GROUP BY unique_key
HAVING count(*) > 1;
```
## 12. 本地完整流程
处理一个新批次:
```bash
# 1. 设置 OCR 密钥
export TENCENTCLOUD_SECRET_ID='填入腾讯云 SecretId'
export TENCENTCLOUD_SECRET_KEY='填入腾讯云 SecretKey'
# 2. 运行 OCR 归档
python3 数据处理工作区/02_图片表格OCR归档.py \
--config "数据处理工作区/01_任务配置.json" \
--input "待处理-[任务名]图片集群/[批次文件夹名]" \
--output "数据处理结果区/已处理-[任务名]图片集群/[批次文件夹名]-列表归档结果" \
--ocr-engine table-v3 \
--batch-size 6 \
--image-padding-y 24 \
--workers 1 \
--folder-workers 2 \
--timeout 90 \
--max-retries 1
# 3. 检查复核报告和重复报告
# 4. 必要时填写 03_人工复核修正.json
# 5. 用缓存重建
python3 数据处理工作区/02_图片表格OCR归档.py \
--config "数据处理工作区/01_任务配置.json" \
--input "待处理-[任务名]图片集群/[批次文件夹名]" \
--output "数据处理结果区/已处理-[任务名]图片集群/[批次文件夹名]-列表归档结果" \
--ocr-engine table-v3 \
--batch-size 6 \
--image-padding-y 24 \
--rebuild-from-cache
# 6. 合并所有批次
python3 数据处理工作区/04_合并批次结果.py --config "数据处理工作区/01_任务配置.json"
# 7. 可选:同步数据库
python3 数据处理工作区/05_同步PostgreSQL单表.py
```
确认无误后移动原始图片批次:
```bash
mv "待处理-[任务名]图片集群/[批次文件夹名]" "已处理-[任务名]图片集群/"
```
## 13. Gitea 提交流程
提交前检查:
```bash
git status --short --ignored
git diff --cached --name-only
rg -n "Secret|PASSWORD|密码|密钥|TENCENTCLOUD_SECRET|DB_PASSWORD" README.md 工作流*.md 数据处理工作区 人工复核网页端
```
推荐只提交:
```bash
git add \
.gitignore \
README.md \
工作流_本地使用版.md \
工作流_Gitea版.md \
通用图片表格识别工作流模板.md \
数据处理工作区/01_任务配置.template.json \
数据处理工作区/02_图片表格OCR归档.py \
数据处理工作区/03_人工复核修正.template.json \
数据处理工作区/04_合并批次结果.py \
数据处理工作区/05_同步PostgreSQL单表.py \
数据处理工作区/06_PostgreSQL建表结构.template.sql \
数据处理工作区/07_处理程序说明.md \
数据处理工作区/08_本地运行流程.template.sh \
人工复核网页端
git commit -m "Add generic image table OCR workflow"
git push origin main
```
不要提交:
```text
.env
数据处理工作区/03_人工复核修正.json
待处理-*图片集群/
已处理-*图片集群/
数据处理结果区/
raw_ocr/
merged_images/
*.csv
*.jsonl
包含真实业务数据的 *.json
```
## 14. 迁移到新任务时的改造清单
必须改:
- `[任务名]`、输入目录、输出目录。
- 字段顺序和字段名。
- OCR 行列解析逻辑。
- 字段清洗规则。
- 必填字段和复核规则。
- 主唯一键和去重策略。
- CSV 表头。
- PostgreSQL 表名、列名、约束和索引。
通常要改:
- 分类规则,例如科室、设备、项目类型、来源系统。
- 行数估算规则,例如每张图片有多少数据行。
- 拼接白边和默认 batch-size。
- 人工复核网页端展示字段。
- 抽查提示词和 AI 校验标准。
通常不用改:
- 环境变量读取方式。
- OCR 缓存机制。
- `--rebuild-from-cache` 重建方式。
- 批次合并流程。
- Gitea 排除真实数据和密钥的原则。
## 15. 完成标准
一个批次可以认为处理完成,需要同时满足:
- OCR 脚本运行结束,没有未处理的接口错误。
- `图片表格_结构化.json``图片表格_记录.csv` 已生成。
- `复核报告.json` 已检查,需人工复核项已处理或明确保留。
- 主唯一键缺失和重复报告已检查。
- 合并脚本已运行,全局汇总符合预期。
- 如果启用 PostgreSQL入库记录数与合并结果一致。
- 原始图片批次已从 `待处理` 移到 `已处理`
- Gitea 仓库没有密钥、图片、OCR 缓存、真实处理结果。
## 16. 给未来智能体的执行提示
遇到一个新图片表格任务时,先不要直接写死业务规则。建议按以下顺序推进:
1. 读取本模板和当前目录结构。
2. 盘点待处理图片批次、图片数量、图片命名规律。
3. 抽样查看 3-5 张图片,确认表格字段、行高、是否有表头、是否跨页。
4. 让用户确认字段顺序、主唯一键、是否需要数据库。
5. 基于模板生成或改造处理脚本。
6. 先小批量试跑,检查 OCR 响应、行数和列错位。
7. 固化清洗规则和复核规则。
8. 全批次运行,输出报告。
9. 人工复核后用缓存重建。
10. 合并、可选入库、归档。
本模板只定义工作流骨架。腾讯云 API 密钥、Gitea 地址、PostgreSQL 连接、目标表结构、业务字段、人工修正规则,都应在具体任务中由人工确认后再补充。