fix:修复批量处理导致的电脑死机、程序未响应问题
This commit is contained in:
parent
d7ff077dd6
commit
7f804d285e
116
README.md
116
README.md
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
本地 CPU 部署 [PaddlePaddle/PaddleOCR-VL-1.6](https://github.com/PaddlePaddle/PaddleOCR) 的 OCR 识别项目,包含完整的性能 Benchmark 和多级优化方案。
|
||||
|
||||
> 在线 Demo: [HuggingFace Space](https://huggingface.co/spaces/PaddlePaddle/PaddleOCR-VL-1.6_Online_Demo) · 模型权重: [HuggingFace](https://huggingface.co/PaddlePaddle/PaddleOCR-VL-1.6)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
|
|
@ -16,13 +18,13 @@ ocr-VL1.6/
|
|||
|
||||
## 技术栈
|
||||
|
||||
| 组件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Python | 3.13 | |
|
||||
| PaddlePaddle | 3.2.1 | CPU 版(无 CUDA),已编译 oneDNN/MKL-DNN |
|
||||
| PaddleOCR | 3.7.0 | 带 `doc-parser` extra |
|
||||
| PaddleOCR-VL-1.6 | 0.9B | 主 OCR 视觉语言模型(~1.8GB) |
|
||||
| PP-DocLayoutV3 | - | 版面检测模型(~126MB) |
|
||||
| 组件 | 版本 | 说明 |
|
||||
| ---------------- | ----- | ---------------------------------------- |
|
||||
| Python | 3.13 | |
|
||||
| PaddlePaddle | 3.2.1 | CPU 版(无 CUDA),已编译 oneDNN/MKL-DNN |
|
||||
| PaddleOCR | 3.7.0 | 带 `doc-parser` extra |
|
||||
| PaddleOCR-VL-1.6 | 0.9B | 主 OCR 视觉语言模型(~1.8GB) |
|
||||
| PP-DocLayoutV3 | - | 版面检测模型(~126MB) |
|
||||
|
||||
模型缓存目录:`~/.paddlex/official_models/`
|
||||
|
||||
|
|
@ -45,8 +47,8 @@ uv sync
|
|||
# 单张图片 OCR(自动使用全部 CPU 核心)
|
||||
uv run python main.py
|
||||
|
||||
# 批量 OCR(多进程并行)
|
||||
uv run python batch_ocr.py images/ --workers 4
|
||||
# 批量 OCR(多进程并行,安全默认值)
|
||||
uv run python batch_ocr.py images/
|
||||
```
|
||||
|
||||
首次运行会自动从 ModelScope 下载模型文件(约 2GB),后续使用缓存。
|
||||
|
|
@ -65,12 +67,12 @@ uv run python batch_ocr.py images/ --workers 4
|
|||
|
||||
### 输出结构
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `layout_det_res.boxes` | list[dict] | 版面文本区域(cls_id, label, score, coordinate, polygon_points) |
|
||||
| `parsing_res_list` | list[PaddleOCRVLBlock] | 识别文本块($.label, $.bbox, $.content, $.polygon_points) |
|
||||
| `model_settings` | dict | 推理配置开关(版面检测/图表/印章等) |
|
||||
| `width` / `height` | int | 图片尺寸 |
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ---------------------- | ---------------------- | ------------------------------------------------------------ |
|
||||
| `layout_det_res.boxes` | list[dict] | 版面文本区域(cls_id, label, score, coordinate, polygon_points) |
|
||||
| `parsing_res_list` | list[PaddleOCRVLBlock] | 识别文本块($.label, $.bbox, $.content, $.polygon_points) |
|
||||
| `model_settings` | dict | 推理配置开关(版面检测/图表/印章等) |
|
||||
| `width` / `height` | int | 图片尺寸 |
|
||||
|
||||
## 性能优化迭代
|
||||
|
||||
|
|
@ -80,40 +82,40 @@ uv run python batch_ocr.py images/ --workers 4
|
|||
|
||||
直接调用 `pipeline.predict()`,未设置任何线程参数。
|
||||
|
||||
| 阶段 | 耗时 |
|
||||
|------|------|
|
||||
| 模型初始化(加载权重) | ~60s |
|
||||
| 首次推理(含 JIT 编译) | ~285s |
|
||||
| 后续推理 | ~238s(~4 min) |
|
||||
| 阶段 | 耗时 |
|
||||
| ----------------------- | --------------- |
|
||||
| 模型初始化(加载权重) | ~60s |
|
||||
| 首次推理(含 JIT 编译) | ~285s |
|
||||
| 后续推理 | ~238s(~4 min) |
|
||||
|
||||
### 迭代 1:算子级并行 — `core.set_num_threads()`
|
||||
|
||||
**探索过程:**
|
||||
|
||||
| 尝试 | 方法 | 结果 |
|
||||
|------|------|------|
|
||||
| ❌ | `paddle.set_num_threads()` | Paddle 3.x 已移除该 API |
|
||||
| ❌ | 环境变量 `OMP_NUM_THREADS` / `MKL_NUM_THREADS` | Paddle 3.x 内部使用 oneDNN,不读取这些变量 |
|
||||
| ✅ | `from paddle import core; core.set_num_threads(N)` | **有效!** oneDNN 底层算子(matmul 等)受该 API 控制 |
|
||||
| 尝试 | 方法 | 结果 |
|
||||
| ---- | -------------------------------------------------- | ---------------------------------------------------- |
|
||||
| ❌ | `paddle.set_num_threads()` | Paddle 3.x 已移除该 API |
|
||||
| ❌ | 环境变量 `OMP_NUM_THREADS` / `MKL_NUM_THREADS` | Paddle 3.x 内部使用 oneDNN,不读取这些变量 |
|
||||
| ✅ | `from paddle import core; core.set_num_threads(N)` | **有效!** oneDNN 底层算子(matmul 等)受该 API 控制 |
|
||||
|
||||
**矩阵乘法微基准测试(4000×4000):**
|
||||
|
||||
| 线程数 | 耗时 (matmul) | 加速比 |
|
||||
|--------|--------------|--------|
|
||||
| 1 | 0.952s | 1.0x |
|
||||
| 4 | 0.419s | 2.3x |
|
||||
| 8 | 0.323s | 2.9x |
|
||||
| 16 | 0.240s | 4.0x |
|
||||
| **20** | **0.223s** | **4.3x** |
|
||||
| 线程数 | 耗时 (matmul) | 加速比 |
|
||||
| ------ | ------------- | -------- |
|
||||
| 1 | 0.952s | 1.0x |
|
||||
| 4 | 0.419s | 2.3x |
|
||||
| 8 | 0.323s | 2.9x |
|
||||
| 16 | 0.240s | 4.0x |
|
||||
| **20** | **0.223s** | **4.3x** |
|
||||
|
||||
**应用到 OCR 后的实际效果:**
|
||||
|
||||
设置 `core.set_num_threads(20)` 后重新评测:
|
||||
|
||||
| 阶段 | 优化前 | 优化后 | 提速 |
|
||||
|------|--------|--------|------|
|
||||
| 模型初始化 | ~60s | ~40s | 1.5x |
|
||||
| 推理 | ~238s | **~162s(~2.7 min)** | **1.5x** |
|
||||
| 阶段 | 优化前 | 优化后 | 提速 |
|
||||
| ---------- | ------ | --------------------- | -------- |
|
||||
| 模型初始化 | ~60s | ~40s | 1.5x |
|
||||
| 推理 | ~238s | **~162s(~2.7 min)** | **1.5x** |
|
||||
|
||||
**为什么不是 4.3x?** 矩阵乘法只是 OCR pipeline 的一部分。自回归解码(逐 token 生成)天然串行、I/O 等待、版面检测中的非矩阵运算等不受线程数影响。
|
||||
|
||||
|
|
@ -123,21 +125,35 @@ uv run python batch_ocr.py images/ --workers 4
|
|||
|
||||
**思路:** 多张图片时,用 `multiprocessing.Pool` 启动多个独立进程,每个进程加载一份 pipeline 实例,同时处理不同图片。
|
||||
|
||||
**遇到的问题 & 修复(迭代 2.1):**
|
||||
|
||||
| 问题 | 原因 | 修复 |
|
||||
|------|------|------|
|
||||
| 系统卡顿/黑屏/无响应 | `Pool.starmap` 同时启动 N 个进程,同步加载 N×2GB 模型,CPU + 内存瞬间打满 | ① 进程错峰启动(随机延迟 0~15s)② `psutil` 降低进程优先级 ③ 预留 1 核给 OS ④ `imap_unordered` 替代 `starmap` |
|
||||
|
||||
**策略:**
|
||||
- 每个子进程独立调用 `core.set_num_threads(总核心 / 进程数)`,避免线程争抢
|
||||
- 例如 4 进程 × 5 线程 = 20 核心全部利用
|
||||
- 每个子进程独立调用 `core.set_num_threads((总核心-1) / 进程数)`,预留核心给 OS
|
||||
- 例如 2 进程 × 9 线程 = 18 核,留 2 核给系统
|
||||
- `--stagger` 控制错峰窗口,默认 15s
|
||||
|
||||
```bash
|
||||
# 4 进程并行
|
||||
# 2 进程并行(安全默认值)
|
||||
uv run python batch_ocr.py images/
|
||||
|
||||
# 4 进程并行(需 32GB+ RAM)
|
||||
uv run python batch_ocr.py images/ --workers 4
|
||||
|
||||
# 自定义错峰窗口(值越大内存峰值越低,但总耗时增加)
|
||||
uv run python batch_ocr.py images/ --workers 4 --stagger 30
|
||||
```
|
||||
|
||||
| 配置 | 适用场景 | 理论加速比 | 内存开销 | 实际限制 |
|
||||
|------|---------|-----------|---------|---------|
|
||||
| `set_num_threads(N)` | 单张图片 | ~1.5x | 无额外开销 | 自回归解码瓶颈 |
|
||||
| `batch_ocr.py` | 批量多图 | ~Nx(N=进程数) | N × 2GB | 内存/内存带宽 |
|
||||
| 配置 | 适用场景 | 理论加速比 | 内存开销 | 实际限制 |
|
||||
| -------------------- | -------- | --------------- | ---------- | -------------- |
|
||||
| `set_num_threads(N)` | 单张图片 | ~1.5x | 无额外开销 | 自回归解码瓶颈 |
|
||||
| `batch_ocr.py` | 批量多图 | ~Nx(N=进程数) | N × 2GB | 内存/内存带宽,需错峰避免打满系统 |
|
||||
|
||||
> ⚠️ 每个进程独立加载模型(~2GB),32GB RAM 建议 `--workers ≤ 4`。
|
||||
> 默认 `--workers 2` 为安全值,不会导致系统卡顿。
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -155,10 +171,10 @@ uv run python batch_ocr.py images/ --workers 4
|
|||
|
||||
## 已知局限
|
||||
|
||||
| 问题 | 影响 | 说明 |
|
||||
|------|------|------|
|
||||
| CPU 推理极慢 | 单图 ~2.7 min(优化后) | 0.9B VL 模型不适合 CPU 实时场景 |
|
||||
| 自回归解码串行 | 无法更细粒度并行 | 生成阶段逐 token 依赖,多线程收益有限 |
|
||||
| 内存占用大 | 每进程需 ~2GB | 限制了 `batch_ocr.py` 并行度 |
|
||||
| Windows 控制台乱码 | 中文输出显示为乱码 | GBK 编码问题,文件写入/pipe 正常 |
|
||||
| ccache 警告 | 无实际影响 | 仅影响首次编译加速,可忽略 |
|
||||
| 问题 | 影响 | 说明 |
|
||||
| ------------------ | ----------------------- | ------------------------------------- |
|
||||
| CPU 推理极慢 | 单图 ~2.7 min(优化后) | 0.9B VL 模型不适合 CPU 实时场景 |
|
||||
| 自回归解码串行 | 无法更细粒度并行 | 生成阶段逐 token 依赖,多线程收益有限 |
|
||||
| 内存占用大 | 每进程需 ~2GB | 限制了 `batch_ocr.py` 并行度 |
|
||||
| Windows 控制台乱码 | 中文输出显示为乱码 | GBK 编码问题,文件写入/pipe 正常 |
|
||||
| ccache 警告 | 无实际影响 | 仅影响首次编译加速,可忽略 |
|
||||
|
|
|
|||
173
batch_ocr.py
173
batch_ocr.py
|
|
@ -1,37 +1,78 @@
|
|||
"""
|
||||
批量 OCR 识别 — 多进程并行加速
|
||||
批量 OCR 识别 — 多进程并行加速(系统友好版)
|
||||
|
||||
原理:每个进程独立加载一份 pipeline 实例,同时处理不同图片。
|
||||
适用场景:一次处理多张图片(如文件夹批量 OCR)。
|
||||
修复要点:
|
||||
1. 进程错峰启动(随机延迟),避免同时加载 N 个模型导致内存/CUP 打满
|
||||
2. 降低子进程优先级,保证系统 UI 正常响应
|
||||
3. 预留 1-2 个核心给 OS,避免 CPU 完全饱和
|
||||
4. 用 imap_unordered 逐任务分发,而非一次性灌满
|
||||
|
||||
用法:
|
||||
python batch_ocr.py <图片目录> [--workers 4] [--threads 10]
|
||||
python batch_ocr.py <图片目录> [--workers 4] [--threads 5]
|
||||
|
||||
安全建议:
|
||||
- 32GB RAM 建议 --workers <= 4
|
||||
- 16GB RAM 建议 --workers <= 2
|
||||
- 不确定时先用 --workers 1 测试
|
||||
"""
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
import argparse
|
||||
from multiprocessing import Pool, cpu_count
|
||||
from pathlib import Path
|
||||
|
||||
# ── Worker 初始化(在子进程中执行) ──
|
||||
|
||||
def ocr_single(image_path: str, threads: int) -> dict:
|
||||
"""单张图片 OCR(在子进程中执行)"""
|
||||
def _init_worker(threads: int, stagger_max: float):
|
||||
"""
|
||||
每个 Worker 启动时:随机延迟 → 设线程数 → 降优先级 → 加载模型。
|
||||
|
||||
随机延迟是关键:避免 N 个进程同时读磁盘/分配内存,
|
||||
将 4×2GB=8GB 的内存峰值分散到 0~15s 的时间窗口中。
|
||||
"""
|
||||
delay = random.uniform(0, stagger_max)
|
||||
time.sleep(delay)
|
||||
|
||||
# 算子级线程数
|
||||
from paddle import core
|
||||
core.set_num_threads(threads)
|
||||
|
||||
# 降低进程优先级(不影响计算吞吐,但让 OS 调度更公平)
|
||||
try:
|
||||
import psutil
|
||||
p = psutil.Process()
|
||||
if sys.platform == "win32":
|
||||
p.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS)
|
||||
else:
|
||||
p.nice(10)
|
||||
except ImportError:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 加载 pipeline(~2GB,耗时 ~40s)
|
||||
from paddleocr import PaddleOCRVL
|
||||
global _pipeline
|
||||
_pipeline = PaddleOCRVL(pipeline_version="v1.6")
|
||||
|
||||
pipeline = PaddleOCRVL(pipeline_version="v1.6")
|
||||
|
||||
def _ocr_task(image_path: str) -> dict:
|
||||
"""单张图片 OCR(使用全局 pipeline)"""
|
||||
global _pipeline
|
||||
t0 = time.perf_counter()
|
||||
result = pipeline.predict(image_path)
|
||||
result = _pipeline.predict(image_path)
|
||||
elapsed = time.perf_counter() - t0
|
||||
|
||||
blocks = []
|
||||
for block in result[0]["parsing_res_list"]:
|
||||
if block.content.strip():
|
||||
blocks.append({"label": block.label, "bbox": block.bbox, "content": block.content})
|
||||
blocks.append({
|
||||
"label": block.label,
|
||||
"bbox": block.bbox,
|
||||
"content": block.content,
|
||||
})
|
||||
|
||||
return {
|
||||
"path": str(image_path),
|
||||
|
|
@ -40,53 +81,127 @@ def ocr_single(image_path: str, threads: int) -> dict:
|
|||
}
|
||||
|
||||
|
||||
# ── 主流程 ──
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Batch OCR with multiprocessing")
|
||||
total_cores = cpu_count()
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="批量 OCR — 多进程并行(系统友好版)",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
python batch_ocr.py images/ # 默认 2 进程
|
||||
python batch_ocr.py images/ --workers 4 # 4 进程(需 32GB RAM)
|
||||
python batch_ocr.py images/ --workers 2 --threads 8 # 指定每进程线程数
|
||||
""",
|
||||
)
|
||||
parser.add_argument("dir", type=str, help="图片目录")
|
||||
parser.add_argument("--workers", type=int, default=4, help="并行进程数 (默认 4)")
|
||||
parser.add_argument("--threads", type=int, default=None, help="每进程线程数 (默认: 总核心/workers)")
|
||||
parser.add_argument(
|
||||
"--workers", type=int, default=2,
|
||||
help="并行进程数 (默认 2,安全值;最大建议不超过 RAM_GB/2)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--threads", type=int, default=None,
|
||||
help=f"每进程线程数 (默认: (总核心-1)/workers,保证 OS 有 1 核可用)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--stagger", type=float, default=15.0,
|
||||
help="进程启动错峰窗口秒数 (默认 15s,值越大内存峰值越低)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# ── 扫描图片 ──
|
||||
image_dir = Path(args.dir)
|
||||
if not image_dir.is_dir():
|
||||
print(f"[ERROR] 目录不存在: {args.dir}")
|
||||
sys.exit(1)
|
||||
|
||||
images = list(image_dir.glob("*.png")) + list(image_dir.glob("*.jpg")) + list(image_dir.glob("*.jpeg"))
|
||||
extensions = ("*.png", "*.jpg", "*.jpeg", "*.bmp", "*.tiff", "*.tif", "*.webp")
|
||||
images = []
|
||||
for ext in extensions:
|
||||
images.extend(image_dir.glob(ext))
|
||||
images = sorted(images)
|
||||
|
||||
if not images:
|
||||
print(f"[ERROR] 目录中没有图片: {args.dir}")
|
||||
sys.exit(1)
|
||||
|
||||
# ── 资源规划 ──
|
||||
workers = min(args.workers, len(images))
|
||||
threads = args.threads or max(1, cpu_count() // workers)
|
||||
reserved_for_os = 1 # 至少给 OS 留 1 个逻辑核心
|
||||
if args.threads:
|
||||
threads = args.threads
|
||||
else:
|
||||
threads = max(1, (total_cores - reserved_for_os) // workers)
|
||||
|
||||
print(f"图片数量: {len(images)}")
|
||||
print(f"并行进程: {workers}")
|
||||
print(f"每进程线程: {threads}")
|
||||
print(f"总核心利用: {workers * threads} / {cpu_count()}")
|
||||
total_cpu_used = workers * threads
|
||||
stagger = args.stagger
|
||||
|
||||
# 内存估算
|
||||
model_mem_per_worker = 2.0 # GB, 模型 ~1.8GB + 运行时开销
|
||||
estimated_mem = workers * model_mem_per_worker + 2 # +2GB for OS
|
||||
|
||||
try:
|
||||
import psutil
|
||||
avail_gb = psutil.virtual_memory().available / (1024**3)
|
||||
mem_ok = avail_gb > estimated_mem
|
||||
except ImportError:
|
||||
avail_gb = None
|
||||
mem_ok = True # 无法检测,假定 OK
|
||||
|
||||
# ── 打印配置 ──
|
||||
print("=" * 60)
|
||||
print(f" 图片数量: {len(images)}")
|
||||
print(f" 并行进程: {workers}")
|
||||
print(f" 每进程线程: {threads}")
|
||||
print(f" CPU 占用: {total_cpu_used} / {total_cores} 核 (保留 {total_cores - total_cpu_used} 给 OS)")
|
||||
print(f" 错峰窗口: {stagger}s")
|
||||
print(f" 预估内存: ~{estimated_mem:.0f}GB (可用: {avail_gb:.0f}GB)" if avail_gb else f" 预估内存: ~{estimated_mem:.0f}GB")
|
||||
if not mem_ok:
|
||||
print(f" [WARNING] 可用内存不足!建议降低 --workers 到 {max(1, int((avail_gb - 2) / model_mem_per_worker))}")
|
||||
print("=" * 60)
|
||||
|
||||
if not mem_ok:
|
||||
resp = input("内存不足,是否继续?[y/N] ").strip().lower()
|
||||
if resp != "y":
|
||||
print("已取消。")
|
||||
sys.exit(0)
|
||||
|
||||
# ── 执行 ──
|
||||
t0 = time.perf_counter()
|
||||
|
||||
# 每个子进程独立加载模型 + 推理
|
||||
with Pool(workers) as pool:
|
||||
tasks = [(str(img), threads) for img in images]
|
||||
results = pool.starmap(ocr_single, tasks)
|
||||
with Pool(
|
||||
processes=workers,
|
||||
initializer=_init_worker,
|
||||
initargs=(threads, stagger),
|
||||
) as pool:
|
||||
# imap_unordered: 逐任务分发,先完成的先返回
|
||||
# chunk 大 → 吞吐高但内存峰值高;chunk=1 → 最平滑
|
||||
image_paths = [str(img) for img in images]
|
||||
results = list(pool.imap_unordered(_ocr_task, image_paths, chunksize=1))
|
||||
|
||||
total_elapsed = time.perf_counter() - t0
|
||||
|
||||
# 输出结果
|
||||
# ── 输出 ──
|
||||
print("\n" + "=" * 60)
|
||||
for r in results:
|
||||
for r in sorted(results, key=lambda x: x["path"]):
|
||||
print(f"\n[文件] {r['path']} ({r['elapsed']:.1f}s)")
|
||||
for block in r["blocks"]:
|
||||
print(f" [{block['label']}] {block['content'][:60]}{'...' if len(block['content']) > 60 else ''}")
|
||||
preview = block["content"].replace("\n", "\\n")
|
||||
if len(preview) > 80:
|
||||
preview = preview[:80] + "..."
|
||||
print(f" [{block['label']}] {preview}")
|
||||
|
||||
total_per_image = sum(r["elapsed"] for r in results)
|
||||
print("\n" + "=" * 60)
|
||||
print(f"总图片: {len(images)} | 总耗时: {total_elapsed:.1f}s")
|
||||
print(f"平均每图: {total_elapsed / len(images):.1f}s")
|
||||
print(f"单进程串行预计: {sum(r['elapsed'] for r in results):.1f}s")
|
||||
print(f"并行加速比: {sum(r['elapsed'] for r in results) / total_elapsed:.2f}x")
|
||||
print(f" 总图片: {len(images)}")
|
||||
print(f" 总耗时: {total_elapsed:.1f}s ({total_elapsed/60:.1f}min)")
|
||||
print(f" 平均每图: {total_elapsed / len(images):.1f}s")
|
||||
print(f" 串行预计: {total_per_image:.1f}s")
|
||||
if total_elapsed > 0:
|
||||
print(f" 加速比: {total_per_image / total_elapsed:.2f}x")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
|
|
@ -0,0 +1,85 @@
|
|||
PS D:\Dev\ocr-VL1.6> uv run python .\main.py
|
||||
信息: 用提供的模式无法找到文件。
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\cpp_extension\extension_utils.py:718: UserWarning: 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
|
||||
warnings.warn(warning_message)
|
||||
[Threads] oneDNN compiled, using 20 threads (CPU cores: 20)
|
||||
============================================================
|
||||
初始化模型...
|
||||
Creating model: ('PP-DocLayoutV3', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PP-DocLayoutV3`.
|
||||
Creating model: ('PaddleOCR-VL-1.6-0.9B', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6`.
|
||||
Bucketed engine_config has no entry for resolved engine 'paddle_dynamic'; using an empty config for that engine.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\config.json
|
||||
Loading weights file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\model.safetensors
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.split.html first.
|
||||
warnings.warn(
|
||||
Loaded weights file from disk, setting weights to model.
|
||||
All model checkpoint weights were used when initializing PaddleOCRVLForConditionalGeneration.
|
||||
|
||||
All the weights of PaddleOCRVLForConditionalGeneration were initialized from the model checkpoint at C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6.
|
||||
If your task is similar to the task the model of the checkpoint was trained on, you can already use PaddleOCRVLForConditionalGeneration for predictions without further training.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\generation_config.json
|
||||
[OK] 模型初始化耗时: 40.03s
|
||||
============================================================
|
||||
|
||||
开始 OCR 识别: images/名片01.jpg
|
||||
预热 0 轮 + 正式测试 1 轮
|
||||
|
||||
推理 1/1... D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\tensor\creation.py:1088: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach(), rather than paddle.to_tensor(sourceTensor).
|
||||
return tensor(
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.max.html first.
|
||||
warnings.warn(
|
||||
81.30s
|
||||
|
||||
============================================================
|
||||
[Benchmark]
|
||||
图片尺寸: 591 x 360
|
||||
检测文本块: 7 个
|
||||
识别文本块: 6 个
|
||||
推理次数: 1
|
||||
最快: 81.30s
|
||||
最慢: 81.30s
|
||||
平均: 81.30s
|
||||
============================================================
|
||||
|
||||
[识别结果]
|
||||
|
||||
[text] ([397, 17, 549, 38])
|
||||
材质:250g黄彩石纹
|
||||
|
||||
[header_image] ([39, 65, 184, 106])
|
||||
|
||||
|
||||
[image] ([433, 100, 529, 152])
|
||||
|
||||
|
||||
[paragraph_title] ([30, 188, 306, 244])
|
||||
太原承方科技有限公司
|
||||
山西承方印刷物资有限公司
|
||||
|
||||
[text] ([30, 282, 302, 306])
|
||||
地址:太原市南十方街东中环口西南角
|
||||
|
||||
[text] ([32, 302, 471, 332])
|
||||
Q Q: 800806277 手机: 13703585513 网址: www.cfprint.cn
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
PS D:\Dev\ocr-VL1.6> uv run python .\main.py
|
||||
信息: 用提供的模式无法找到文件。
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\cpp_extension\extension_utils.py:718: UserWarning: 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
|
||||
warnings.warn(warning_message)
|
||||
[Threads] oneDNN compiled, using 20 threads (CPU cores: 20)
|
||||
============================================================
|
||||
初始化模型...
|
||||
Creating model: ('PP-DocLayoutV3', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PP-DocLayoutV3`.
|
||||
Creating model: ('PaddleOCR-VL-1.6-0.9B', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6`.
|
||||
Bucketed engine_config has no entry for resolved engine 'paddle_dynamic'; using an empty config for that engine.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\config.json
|
||||
Loading weights file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\model.safetensors
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.split.html first.
|
||||
warnings.warn(
|
||||
Loaded weights file from disk, setting weights to model.
|
||||
All model checkpoint weights were used when initializing PaddleOCRVLForConditionalGeneration.
|
||||
|
||||
All the weights of PaddleOCRVLForConditionalGeneration were initialized from the model checkpoint at C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6.
|
||||
If your task is similar to the task the model of the checkpoint was trained on, you can already use PaddleOCRVLForConditionalGeneration for predictions without further training.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\generation_config.json
|
||||
[OK] 模型初始化耗时: 51.99s
|
||||
============================================================
|
||||
|
||||
开始 OCR 识别: images/名片02.jpg
|
||||
预热 0 轮 + 正式测试 1 轮
|
||||
|
||||
推理 1/1... D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\tensor\creation.py:1088: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach(), rather than paddle.to_tensor(sourceTensor).
|
||||
return tensor(
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.max.html first.
|
||||
warnings.warn(
|
||||
111.56s
|
||||
|
||||
============================================================
|
||||
[Benchmark]
|
||||
图片尺寸: 1440 x 864
|
||||
检测文本块: 6 个
|
||||
识别文本块: 6 个
|
||||
推理次数: 1
|
||||
最快: 111.56s
|
||||
最慢: 111.56s
|
||||
平均: 111.56s
|
||||
============================================================
|
||||
|
||||
[识别结果]
|
||||
|
||||
[paragraph_title] ([87, 59, 333, 130])
|
||||
白滑影
|
||||
|
||||
[paragraph_title] ([713, 176, 1006, 300])
|
||||
姜美丽
|
||||
13388866888
|
||||
|
||||
[paragraph_title] ([312, 423, 655, 720])
|
||||
夏佳人
|
||||
|
||||
[paragraph_title] ([710, 494, 1346, 563])
|
||||
女子时尚瘦身健美馆
|
||||
|
||||
[text] ([713, 572, 1342, 615])
|
||||
地址:上海市湘江大街88号滨江大厦
|
||||
|
||||
[text] ([714, 619, 1208, 660])
|
||||
电话:83566666 83588888
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
PS D:\Dev\ocr-VL1.6> uv run python batch_ocr.py images/
|
||||
============================================================
|
||||
图片数量: 3
|
||||
并行进程: 2
|
||||
每进程线程: 9
|
||||
CPU 占用: 18 / 20 核 (保留 2 给 OS)
|
||||
错峰窗口: 15.0s
|
||||
预估内存: ~6GB (可用: 17GB)
|
||||
============================================================
|
||||
信息: 用提供的模式无法找到文件。
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\cpp_extension\extension_utils.py:718: UserWarning: 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
|
||||
warnings.warn(warning_message)
|
||||
Creating model: ('PP-DocLayoutV3', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PP-DocLayoutV3`.
|
||||
信息: 用提供的模式无法找到文件。
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\cpp_extension\extension_utils.py:718: UserWarning: 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
|
||||
warnings.warn(warning_message)
|
||||
Creating model: ('PaddleOCR-VL-1.6-0.9B', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6`.
|
||||
Bucketed engine_config has no entry for resolved engine 'paddle_dynamic'; using an empty config for that engine.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\config.json
|
||||
Loading weights file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\model.safetensors
|
||||
Creating model: ('PP-DocLayoutV3', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PP-DocLayoutV3`.
|
||||
Creating model: ('PaddleOCR-VL-1.6-0.9B', None, None)
|
||||
Model files already exist. Using cached files. To redownload, please delete the directory manually: `C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6`.
|
||||
Bucketed engine_config has no entry for resolved engine 'paddle_dynamic'; using an empty config for that engine.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\config.json
|
||||
Loading weights file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\model.safetensors
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
use GQA - num_heads: 16- num_key_value_heads: 2
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.split.html first.
|
||||
warnings.warn(
|
||||
Loaded weights file from disk, setting weights to model.
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.split.html first.
|
||||
warnings.warn(
|
||||
Loaded weights file from disk, setting weights to model.
|
||||
All model checkpoint weights were used when initializing PaddleOCRVLForConditionalGeneration.
|
||||
|
||||
All the weights of PaddleOCRVLForConditionalGeneration were initialized from the model checkpoint at C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6.
|
||||
If your task is similar to the task the model of the checkpoint was trained on, you can already use PaddleOCRVLForConditionalGeneration for predictions without further training.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\generation_config.json
|
||||
All model checkpoint weights were used when initializing PaddleOCRVLForConditionalGeneration.
|
||||
|
||||
All the weights of PaddleOCRVLForConditionalGeneration were initialized from the model checkpoint at C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6.
|
||||
If your task is similar to the task the model of the checkpoint was trained on, you can already use PaddleOCRVLForConditionalGeneration for predictions without further training.
|
||||
Loading configuration file C:\Users\kuuhaku_0\.paddlex\official_models\PaddleOCR-VL-1.6\generation_config.json
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\tensor\creation.py:1088: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach(), rather than paddle.to_tensor(sourceTensor).
|
||||
return tensor(
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.max.html first.
|
||||
warnings.warn(
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\tensor\creation.py:1088: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach(), rather than paddle.to_tensor(sourceTensor).
|
||||
return tensor(
|
||||
D:\Dev\ocr-VL1.6\.venv\Lib\site-packages\paddle\utils\decorator_utils.py:420: Warning:
|
||||
Non compatible API. Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/guides/model_convert/convert_from_pytorch/api_difference/torch/torch.max.html first.
|
||||
warnings.warn(
|
||||
|
||||
============================================================
|
||||
|
||||
[文件] images\名片01.jpg (65.1s)
|
||||
[text] 材质:250g黄彩石纹
|
||||
[paragraph_title] 太原承方科技有限公司\n山西承方印刷物资有限公司
|
||||
[text] 地址:太原市南十方街东中环口西南角
|
||||
[text] Q Q: 800806277 手机: 13703585513 网址: www.cfprint.cn
|
||||
|
||||
[文件] images\名片02.jpg (83.2s)
|
||||
[paragraph_title] 白滑影
|
||||
[paragraph_title] 姜美丽\n13388866888
|
||||
[paragraph_title] 夏佳人
|
||||
[paragraph_title] 女子时尚瘦身健美馆
|
||||
[text] 地址:上海市湘江大街88号滨江大厦
|
||||
[text] 电话:83566666 83588888
|
||||
|
||||
[文件] images\手写01.png (156.6s)
|
||||
[text] 最优质的草场。但是这两年由于旱獭和草原黄鼠的逐年\n保护,人们的行为需要矫正。\n部分。末日的时刻。\n佛巴林卡塔尔等海
|
||||
[text] 很多消费者没有认识到医学验光的重要性,导致诸多后果。\n特许商品的销售便逐渐升温。文化软实力作出重要贡献。
|
||||
|
||||
============================================================
|
||||
总图片: 3
|
||||
总耗时: 275.6s (4.6min)
|
||||
平均每图: 91.9s
|
||||
串行预计: 304.9s
|
||||
加速比: 1.11x
|
||||
============================================================
|
||||
Loading…
Reference in New Issue