教材知识闪卡制作
目的
把纸质教材里「图形语言、符号语言、文字语言」抽成风格统一的闪卡,学生看到正面即可回忆背后的知识点;成品必须能脱离网络、脱离 Anki,双击一个 HTML 文件就能刷。本技能固化一套已在真实教材上反复验证的流程,使换任何一本书都不必重新摸索。
不可动摇的标准(质量红线)
- 教材原图裁切,不用 AI/SVG 重绘。风格统一靠卡面模板、色带与留白实现,不靠修改图内颜色。
- 教材截图本体一个像素未改。只在四周加模板装饰;禁止给内嵌区域画描边或缩放后二次锐化。
- 正面不得泄题。正面含结论符号、答案字样或题号的,换用空白图或重新裁切;背面题号统一替换为「问题」标签。
- 统一规格。所有卡面统一宽度(默认 1400 px),统一「第 N / TOTAL 关」角标、色带与页脚。
- 离线可用。零外链、零 CDN、零接口请求;图片以 data URL 内嵌进单文件 HTML。
- 先样张、后批量。新书或新卡型先做 2~4 张样张交用户确认,再铺开整章;用户说「可以,按这个标准」后才批量。
详细的卡片类型定义与用户偏好见 references/01_制作标准与卡片类型.md。
工作流决策树
- 用户给了新教材 PDF → 从「阶段 0」开始,先确认卡型并做样张。
- 用户给了纯文字表格 / 图片名单 → 从「阶段 0」判定为卡型 C,OCR 校对后走
scripts/build_text_cards.py简化路径。 - 用户说「按这个标准把某章做完」 → 跳过阶段 0,从「阶段 1」开始,沿用上一章配置。
- 用户只要求把已有卡片上传网页 → 直接跳到「阶段 5」。
- 用户反馈「图不对 / 串行了 / 字被切了」 → 回到「阶段 2」重新定位墨迹带,不要靠猜坐标微调。
阶段 0 · 确认卡片标准
先判定本章用哪种卡型,再向用户确认一次:
| 卡型 | 正面 | 背面 | 适用 |
|---|---|---|---|
| A 概念型 | 教材里带图的知识点 / 定义 / 符号 | 教材原题(题号换成「问题」)或符号、文字语言 | 概念密集的章节 |
| B 例题型 | 课本例题题干(含教材插图) | 教材标准「解 / 证明」,不含「分析」 | 概念少、以解题为主的章节 |
| C 文字对照型 | 别称、俗称、名词、线索文字 | 官方全名、定义或对应条目清单 | 纯文字表格、名单、名词对照,没有可裁的图形 |
同一章可混用,但须在登记表里逐张标注卡型。做 2~4 张样张,附预览页交用户确认。
纯文字资料走另一条线:若资料是图片表格或名单(无教材插图可裁),先用 OCR 逐行读出并人工校对,整理成 deck_text.example.json 的结构,再用 scripts/build_text_cards.py 直接生成文字卡面。此时跳过阶段 2 的墨迹带裁切,阶段 4 也不做逐像素保真,改为 OCR 比对背面条目是否齐全、正面是否泄题、卡组图片是否完整。详见 references/01_制作标准与卡片类型.md。
阶段 1 · 解析教材
- 用 PyMuPDF 打开 PDF,先取
page.get_text()判断是否存在文本层;扫描版为空时改用 RapidOCR。 - 读目录页,人工确认各小节起止页;无书签时不要依赖
get_toc()。 - 建立页码映射(常见形式
教材页 = PDF页 - offset),把 offset 写进配置,后续所有出处按教材页标注。 - 导出目录范围内原文与逐行
get_text("dict")坐标到工作区文件,作为定位依据。
完整命令与扫描版 OCR 做法见 references/02_教材解析与墨迹带裁切.md。
阶段 2 · 墨迹带定位(最容易出错,必须做)
关键事实:PDF 文本行 bbox 的上沿通常比真实字形上沿高约 9 pt。直接按 bbox 裁切必然串入上一行(分析、相邻例题、页眉)或切掉分式与根号的下半部分。
- 对目标页区间以 6 倍分辨率渲染,逐行统计灰度墨迹像素,输出连续「墨迹带」的真实上下边界。使用
scripts/ink_bands.py。 - 逐带与导出的行坐标文字对照,确定每张卡正面题干、背面解答各自覆盖哪些带。
- 裁切框的上下边界取两条墨迹带之间的空白处:前不带分析,后不带下一题,同时完整包住分式、根号与插图。
- 把结果写进
deck_config.json的front/back矩形列表;跨页解答用多个矩形按顺序拼接。
阶段 3 · 生成卡片
- 按
deck_config.example.json(skill 根目录)或references/03_卡面模板规范.md的字段说明编写章节配置。 - 运行
scripts/build_cards.py --config <配置文件>,一次产出:
-裁切图/22 面教材原图裁切;
-成品卡面/22 面统一风格成品;
-卡片登记表.csv;
-<章节>_完整卡组.json(math-flash-drawer-v1格式);
-<章节>_总览.html(base64 自包含,可放大看长解答)。 - 卡面模板固定:正面蓝色
#2563EB、背面橙色#EA580C,顶部色带、右上关卡角标、底部出处与难度;正面与背面角标文字按卡型区分。
- 卡型 C 改跑scripts/build_text_cards.py --data <文字数据JSON> [--out 输出目录],输出格式与上面一致;无需 PDF、无需墨迹带。
阶段 4 · 质量校验(不可跳过)
运行 scripts/qc_cards.py --config <配置文件>,三项都必须通过:
- OCR 内容复核:每张裁切图识别出的文字必须与教材原文对应;检查串入相邻段落、题干/解答末行被截断、页眉页码混入、空白图。对单行短图、分式与根号,加白边放大 2 倍后再识别一次。
- 逐像素保真:成品卡面中内嵌教材区域与裁切图逐像素一致(忽略四角圆角与每行首尾 30 px)。
- 数据完整:卡组 JSON 每张卡正反面均为合法 data URL,ID 唯一,章节字段正确。
任一项失败 → 回到阶段 2 调整矩形,重跑阶段 3、4,不得手工修图蒙混过关。
阶段 5 · 内嵌离线抽卡器并交付
- 运行
scripts/inject_deck.py --drawer <抽卡器HTML> --deck <章节卡组JSON> --chapter <章节名> --out <输出HTML>,把卡片并入网页内置卡组;脚本会自动更新卡数文案、章节入口状态与卡组名。
- 若引入的是预设章节之外的新章节(如「院校别名」),追加--add-chapter <新章节名>,脚本会把它补进PRESET入口(可重复传参);不覆盖原网页,--out指向新的独立 HTML 副本即可。
-check_offline_html.py会逐章验证每个有卡章节:入口存在、卡数匹配、连续 60 次发卡零越界、导出 HTML 仍保留全部章节。2. 章节行为约定:按章节归档,发卡时先选章节,只在该章节内随机;选择写入 localStorage 下次记住;保留「全部章节混合」为可选次级模式。详见references/04_离线抽卡器接口.md。 - 运行
scripts/check_offline_html.py --html <输出HTML>做静态结构、JS 语法与断网浏览器交互自检。 - 复制一份到桌面并命名「可直接双击」,与项目内文件校验 MD5 一致。
- 交付时同时给出:网页、章节总览页、卡组 JSON、登记表;说明默认进入哪一章、如何切换、如何上传后续章节。
完整校验清单见 references/05_质量校验清单.md。
资源索引
| 文件 | 用途 |
|---|---|
references/01_制作标准与卡片类型.md |
三种语言、三种卡型(含 C 文字对照型数据 schema)、用户偏好与已确认要求 |
references/02_教材解析与墨迹带裁切.md |
PyMuPDF/OCR、页码映射、墨迹带算法、坐标规范、踩坑记录 |
references/03_卡面模板规范.md |
配色、尺寸、字体、字段、卡片配置 schema |
references/04_离线抽卡器接口.md |
卡组 JSON、章节入口、发卡逻辑、内嵌与再导出 |
references/05_质量校验清单.md |
OCR、像素保真、网页自检、Chrome 断网参数 |
deck_config.example.json |
教材裁切卡配置样例(覆盖单页、样张、跨页三种情形);pdf / out_dir 为占位符,使用前替换成本地路径 |
deck_text.example.json |
文字对照卡数据样例(别称 → 官方全名,含分组) |
scripts/ink_bands.py |
打印指定页区间的真实墨迹带 |
scripts/build_cards.py |
配置驱动的教材裁切、拼版、卡面与卡组生成 |
scripts/build_text_cards.py |
生成纯文字「线索 → 答案」卡片,无需 PDF 裁切 |
scripts/qc_cards.py |
OCR 复核、逐像素保真、数据完整性 |
scripts/inject_deck.py |
把新章节卡组并入单文件离线抽卡器 |
scripts/check_offline_html.py |
单文件网页静态 + 断网交互自检 |
环境依赖
脚本依赖 pymupdf、Pillow、numpy、rapidocr_onnxruntime(仅 OCR 复核需要),以及本机 Chrome/Edge 与 Node.js(仅网页自检需要)。脚本不会自动安装任何依赖;缺失时先向用户说明并确认,再使用固定版本安装。所有处理均在本地完成,不发起任何网络请求。