picturereader-zcode 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.zcode-plugin/.zcode-plugin/plugin.json +23 -0
- package/.zcode-plugin/plugin.json +23 -0
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/mcp/mcp/server.js +593 -0
- package/mcp/server.js +593 -0
- package/package.json +48 -0
- package/scripts/preview.mjs +40 -0
- package/scripts/setup-ocr.mjs +96 -0
- package/skills/image-reading.md +96 -0
- package/src/core.js +1490 -0
- package/src/index.js +30 -0
- package/src/tool.js +548 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional install helper for the PaddleOCR engine (image_ocr engine="paddle").
|
|
3
|
+
* PaddleOCR is RECOMMENDED (far better at glowing/curved/game text) but
|
|
4
|
+
* OPTIONAL — image_ocr degrades to the Windows engine when it is missing.
|
|
5
|
+
*
|
|
6
|
+
* What this does:
|
|
7
|
+
* 1. Ensures a Python 3.12+ interpreter exists (downloads the official
|
|
8
|
+
* 3.12.10 installer from the npmmirror mirror if missing).
|
|
9
|
+
* 2. Creates/repairs the paddle_venv.
|
|
10
|
+
* 3. Installs paddlepaddle + paddleocr from the Tsinghua PyPI mirror.
|
|
11
|
+
* 4. Warms the model cache by running one recognition on a test image.
|
|
12
|
+
*
|
|
13
|
+
* Usage: node scripts/setup-ocr.mjs
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
16
|
+
import { spawnSync } from 'node:child_process';
|
|
17
|
+
import { join, dirname } from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
const PY312 = 'C:\\Users\\Administrator\\Python312\\python.exe';
|
|
21
|
+
const VENV = 'C:\\Users\\Administrator\\paddle_venv\\Scripts\\python.exe';
|
|
22
|
+
const INSTALLER = 'C:\\Users\\Administrator\\Downloads\\python-3.12.10-amd64.exe';
|
|
23
|
+
const INSTALLER_URL = 'https://registry.npmmirror.com/-/binary/python/3.12.10/python-3.12.10-amd64.exe';
|
|
24
|
+
const PYPI = 'https://pypi.tuna.tsinghua.edu.cn/simple';
|
|
25
|
+
const CACHE = join(dirname(fileURLToPath(import.meta.url)), '..', '.paddlex-cache');
|
|
26
|
+
|
|
27
|
+
function run(cmd, args, opts = {}) {
|
|
28
|
+
console.log(`> ${cmd} ${args.join(' ')}`);
|
|
29
|
+
const result = spawnSync(cmd, args, { stdio: 'inherit', ...opts });
|
|
30
|
+
if (result.status !== 0) {
|
|
31
|
+
console.error(`!! command failed (exit ${result.status})`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 1. base Python 3.12
|
|
37
|
+
if (!existsSync(PY312)) {
|
|
38
|
+
console.log('[1/4] Python 3.12 missing — downloading installer (npmmirror mirror)...');
|
|
39
|
+
run('curl.exe', ['-L', '-o', INSTALLER, INSTALLER_URL]);
|
|
40
|
+
console.log('[1/4] Installing Python 3.12 to C:\\Users\\Administrator\\Python312 (user-level, silent)...');
|
|
41
|
+
spawnSync(INSTALLER, [
|
|
42
|
+
'/quiet', 'InstallAllUsers=0', 'TargetDir=C:\\Users\\Administrator\\Python312',
|
|
43
|
+
'Include_pip=1', 'PrependPath=0', 'Include_test=0', 'Include_launcher=0'
|
|
44
|
+
], { stdio: 'inherit' });
|
|
45
|
+
if (!existsSync(PY312)) {
|
|
46
|
+
console.error('!! Python install did not produce ' + PY312);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
console.log('[1/4] Python 3.12 found at ' + PY312);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 2. venv
|
|
54
|
+
if (!existsSync(VENV)) {
|
|
55
|
+
console.log('[2/4] Creating paddle_venv...');
|
|
56
|
+
mkdirSync(dirname(VENV), { recursive: true });
|
|
57
|
+
run(PY312, ['-m', 'venv', 'C:\\Users\\Administrator\\paddle_venv']);
|
|
58
|
+
} else {
|
|
59
|
+
console.log('[2/4] paddle_venv found');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 3. paddlepaddle + paddleocr
|
|
63
|
+
const probe = spawnSync(VENV, ['-c', 'import paddleocr; print(paddleocr.__version__)'], { encoding: 'utf8' });
|
|
64
|
+
if (probe.status !== 0) {
|
|
65
|
+
console.log('[3/4] Installing paddlepaddle + paddleocr (Tsinghua mirror, ~1-3 min)...');
|
|
66
|
+
run(VENV, ['-m', 'pip', 'install', '-i', PYPI, '--upgrade', 'pip']);
|
|
67
|
+
run(VENV, ['-m', 'pip', 'install', '-i', PYPI, 'paddlepaddle==3.3.1', 'paddleocr']);
|
|
68
|
+
} else {
|
|
69
|
+
console.log(`[3/4] paddleocr already installed (${probe.stdout.trim()})`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 4. warm the model cache with one recognition
|
|
73
|
+
console.log('[4/4] Warming the model cache (first run downloads detection/recognition models)...');
|
|
74
|
+
const testImage = join(dirname(fileURLToPath(import.meta.url)), '..', 'tests', 'fixtures-out', 'ocr-test.png');
|
|
75
|
+
mkdirSync(join(CACHE), { recursive: true });
|
|
76
|
+
if (existsSync(testImage)) {
|
|
77
|
+
const warm = spawnSync(VENV, ['-c', [
|
|
78
|
+
'from paddleocr import PaddleOCR',
|
|
79
|
+
"ocr = PaddleOCR(lang='ch', use_doc_orientation_classify=False, use_doc_unwarping=False, use_textline_orientation=False, enable_mkldnn=False)",
|
|
80
|
+
`result = ocr.predict(r'${testImage.replaceAll("'", "''")}')`,
|
|
81
|
+
'print("warm-up OCR ok, lines:", sum(len(r.get("rec_texts") or []) for r in result))'
|
|
82
|
+
].join('; ')], {
|
|
83
|
+
env: { ...process.env, PADDLE_PDX_CACHE_HOME: CACHE, PYTHONIOENCODING: 'utf-8' },
|
|
84
|
+
encoding: 'utf8'
|
|
85
|
+
});
|
|
86
|
+
if (warm.status !== 0) {
|
|
87
|
+
console.error('!! warm-up failed — see output above; the engine may still work once models download');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
console.log(warm.stdout.trim());
|
|
91
|
+
} else {
|
|
92
|
+
console.log('[4/4] test image missing — skip warm-up (first image_ocr paddle call will download models)');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log('\nDone. image_ocr engine="paddle" is now available.');
|
|
96
|
+
console.log('Verify: ask the model to read an image with image_ocr(engine="paddle").');
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: image-reading
|
|
3
|
+
description: Read and understand images like a multimodal model using the picturereader tools (image_scan / image_ocr / image_sample). Applies a verified 5-step workflow (global tone → find subjects → verify text → judge material → synthesize) guided by grounded principles and cross-image insights. Use whenever you need to look at an image.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 读图方法论(image-reading)
|
|
7
|
+
|
|
8
|
+
目标:**像多模态模型一样"看"图并输出连贯描述**,每个结论可追溯、可验证。
|
|
9
|
+
本 skill 由 experience / skill / principle / insight 四层知识构成(按
|
|
10
|
+
Gogomoe 知识框架分类,教训均来自对真实图片的实测复盘)。
|
|
11
|
+
|
|
12
|
+
## 操作流程(skill)
|
|
13
|
+
|
|
14
|
+
### 1. 全局定调(第一轮扫描)
|
|
15
|
+
|
|
16
|
+
用默认参数(size=40)全图扫描,读四个字段:
|
|
17
|
+
- **`hue families`(最高优先级)**:按纯色相分族的真实占比。暗调/低饱和场景的
|
|
18
|
+
真实颜色只在这里——`colors by area` 灰白占比高不代表画面灰白。
|
|
19
|
+
- **`structure`**:平行条带/对称性(解读见 insights)。
|
|
20
|
+
- **`texture`**:rough 高=写实照片;smooth 高=扁平或水面/天空/雾(见 insights)。
|
|
21
|
+
- **`regions`**:大结构的位置/大小/颜色。
|
|
22
|
+
|
|
23
|
+
### 2. 找主体(全局→局部,主动验证)
|
|
24
|
+
|
|
25
|
+
- 对**颜色异常区、深色大块、相邻竖长色块、小色块密集区**用 `px_per_cell` 定向放大
|
|
26
|
+
(值越小越细:8-12 看轮廓,4-6 看结构,2-3 看细节;区域不够小时工具会提示实际密度,缩小 focus/region 重试)。
|
|
27
|
+
- 放大后按**形状**解读:头+肩+躯干=人物;弧线+对称明暗=圆柱/球/装置;
|
|
28
|
+
竖直细长结构=石柱/塔/杆;交替细条=面板/栅格。
|
|
29
|
+
- **主体可能与背景低对比而"隐形"**(见 insights 4)——怀疑处必须放大确认,不能因 regions 未单列就跳过。
|
|
30
|
+
|
|
31
|
+
### 3. 文字验证
|
|
32
|
+
|
|
33
|
+
- 疑似文字/标识/UI → `image_ocr`(region/focus 限定)。
|
|
34
|
+
- Windows 引擎读不出但怀疑有字 → `engine="paddle"` 重试(发光/弯曲/游戏渲染文字)。
|
|
35
|
+
- **OCR 结果优先于模型描述**(见 insights 3)。
|
|
36
|
+
|
|
37
|
+
### 4. 材质判断
|
|
38
|
+
|
|
39
|
+
`image_sample` 对小块区域 8×8 取样,看 RGB 分布与 contrast 统计
|
|
40
|
+
(平滑渐变=天空/皮肤/水面;高对比条纹=金属/木纹;暗绿 G>R>B=植物/涂装)。
|
|
41
|
+
|
|
42
|
+
### 5. 综合描述
|
|
43
|
+
|
|
44
|
+
输出连贯描述(场景/主体/环境光线/细节),**每个结论标注证据等级**:
|
|
45
|
+
实锤(有像素/OCR/取样数据)vs 推断(基于结构推测,用"看起来像")。
|
|
46
|
+
优先引用具体数字;不确定就说不确定,绝不编造。
|
|
47
|
+
|
|
48
|
+
## 行为准则(principles)
|
|
49
|
+
|
|
50
|
+
1. **证据分级**:任何结论标注"实测"或"推断";推断必须说明依据。
|
|
51
|
+
2. **数字优先**:用具体指标("蓝色调 74%""对称 80%""OCR 读出 1.00")支撑描述,不用模糊形容词代替。
|
|
52
|
+
3. **先全局后局部**:第一轮定调,第二轮定向放大验证,不跳步。
|
|
53
|
+
4. **怀疑即验证**:对任何"可能漏掉的主体",用放大/取样/OCR 验证后再下结论。
|
|
54
|
+
5. **不编造**:不确定就说明;模型(含多模态)的描述不可直接当作事实(见 insights 3)。
|
|
55
|
+
|
|
56
|
+
## 规律性洞察(insights,跨图归纳)
|
|
57
|
+
|
|
58
|
+
1. **暗调场景的真实颜色只在 hue families 里**:低饱和/暗色调(暮色、雾中、夜景)
|
|
59
|
+
会被 14 色色板压成灰黑,`colors` 的灰白占比是假象——hue families 按纯色相分族不受影响。
|
|
60
|
+
2. **高对称 ≠ 一定人造物**:水面倒影/镜像构图也高度对称。区分看:平滑大面积
|
|
61
|
+
(水面/天空 smooth 高)+ 水天分界线(上亮下暗、上下镜像)+ 竖直细长结构(石柱)
|
|
62
|
+
= 湖泊/自然镜像;纹理复杂、颜色单调、几何硬边 = 人造建筑/装置。
|
|
63
|
+
3. **小模型读小字不可靠**:多模态小模型对低分辨率文字会幻觉(全图"读出"内容、
|
|
64
|
+
裁剪后承认没有);发光/弯曲/艺术字 Windows OCR 也失效——**文字一律以 OCR 实读为准**。
|
|
65
|
+
4. **低对比主体"隐形"**:暗色物体(如深色服装人物)在暗背景中融入背景黑块,
|
|
66
|
+
粗网格和 regions 都不会标出——对深色区域主动放大是唯一可靠发现方式。
|
|
67
|
+
5. **平滑大面积 ≠ 扁平简笔画**:水面、天空、雾气、墙面都平滑(smooth 高),
|
|
68
|
+
需结合色调/结构/场景判断,不能仅凭 smooth 判定"扁平"。
|
|
69
|
+
6. **"像什么"和"是什么"要分开**:结构证据(对称/形状/色调)支撑"像什么";
|
|
70
|
+
"是什么"需要 OCR/取样/更强证据,不满足时保持推断。
|
|
71
|
+
7. **hue families 是场景类型指纹**(34 张图训练归纳):
|
|
72
|
+
- cyan 高(>60%)= 水/雾/湖泊/晨雾场景(东方水景、浓雾遗址)
|
|
73
|
+
- green 高(>40%)= 森林/竹林/草地/苔藓
|
|
74
|
+
- orange 或 red 高 = 红披风/暖色服饰人物、火光、晚霞
|
|
75
|
+
- blue 高(>70%)= 夜晚/冷色科幻场景
|
|
76
|
+
- achromatic 高 + rough 高 = 废墟/岩石/暗环境
|
|
77
|
+
- green + yellow 双高 = 翠绿能量带/发光植被/浮空仙境
|
|
78
|
+
- 对称高 + 中央竖直结构 = 中央主体(瀑布/树/大门)居中构图
|
|
79
|
+
8. **多模态模型的颜色描述对"发光/能量"不可靠**(训练中反复出现):把实测为
|
|
80
|
+
cyan/blue/green 的冷色发光(屏幕光、能量屏障、雾中光柱)系统性说成"粉红/紫色"。
|
|
81
|
+
发光元素的颜色一律以 hue 实测为准。
|
|
82
|
+
9. **人物识别信号**:orange/red 主调 + 局部暖色小块 + 对称 = 人物服饰候选;
|
|
83
|
+
游戏角色常穿红/橙(红披风、红发、暖色战斗服),识别到暖色主调时应主动放大找人物。
|
|
84
|
+
10. **品牌/游戏名/标题文字**:多模态模型会猜错("原神""崩坏3"实际是明日方舟终末地),
|
|
85
|
+
必须 PaddleOCR 实读(游戏 HUD 底部常带游戏名/参数/水印)。
|
|
86
|
+
|
|
87
|
+
## 案例参考(experience,简短)
|
|
88
|
+
|
|
89
|
+
- 湖泊仙侠图:对称 97% 被误判为"人造立面",实为水面倒影+湖中石柱+粉紫雾气
|
|
90
|
+
→ 教训沉淀为 insight 2。
|
|
91
|
+
- 游戏发光标语图:Windows OCR 12 格全空、多模态幻觉"问问答写",
|
|
92
|
+
PaddleOCR 一次读出「勇于探索叩问苍穹」→ 教训沉淀为 insight 3。
|
|
93
|
+
- 暗背景人物图:黑服人物融入背景被漏检,px_per_cell=3 放大后头肩躯干清晰
|
|
94
|
+
→ 教训沉淀为 insight 4。
|
|
95
|
+
|
|
96
|
+
(新增经验会持续按以上分类沉淀进本 skill。)
|