LEGO 套装查找器
用户拍摄积木堆中具有辨识度的零件:人仔、动物、印刷砖、车辆、异形件。每个零件从照片中裁剪出来,由 Brickognize(免费图像识别服务)识别,并离线查询 Rebrickable 的公开目录。套装根据有多少个独立的特征零件指向它进行排序。普通砖和板难以区分套装,因此不拍摄也不作为证据。
所有命令都由一个脚本完成。每一步都在一个运行文件夹(下文用 RUN 表示,例如 ./lego-run)中读写文件:
python3 ${CLAUDE_SKILL_DIR}/scripts/lsf.py <步骤> RUN ...
下文用 lsf.py 代表该完整命令。lsf.py <步骤> -h 列出所有选项。如果找不到 python3(常见于 Windows,未经测试),则用 py 代替。文件格式、评分方法以及常见问题的修复方式参见 reference.md;当某一步出错或需要手动编辑文件时,请先阅读该文件。
1. 与用户确认任务
在一次消息中询问:
- 得宝还是标准乐高?(本技能仅在得宝上测试过。如果用户回答标准乐高,请如实告知。)
- 照片在哪里?如果还没有照片,请提供下方的拍照技巧。
- 是否允许技能将每张裁剪出的单个零件图片发送给 Brickognize(免费的第三方识别服务)?只有裁剪出的图片会离开计算机,原始照片不会,且这些图片不携带任何元数据(无相机、时间或位置信息)。Brickognize 的条款赋予其永久、免版税的使用上传图片的许可,包括用于训练机器学习模型;用户可以要求 Brickognize 删除它们。如果用户不同意,则在此停止。
- 用户是否已经怀疑某些套装(有盒子、说明书、订单记录)?这些有助于检查结果,但不能替代证据。
拍照技巧(请原样告知):
- 只挑出具有辨识度的零件:人仔、动物、印刷砖、车辆、异形件。普通砖和板对区分套装没有用。
- 将尽可能多的零件平铺在一张大白色床单上,每个零件之间留出约 2 厘米的间距,印刷面朝上。间距比数量更重要:贴在一起的零件会被裁剪成一个。如果积木数量较多,可以拍多张照片;技能会在一次运行中大约超过 300 个零件时询问是否继续。白色、灰色和透明零件在深色床单上更显眼。
- 在光线充足的环境下从正上方拍摄,确保整张床单都在画面内。
- 对于标准乐高(较小的零件),每张照片放少一些,并拍得更近。
- 人仔和印刷件承载了大部分证据。
- JPEG 或 PNG 照片可以直接使用。HEIC 照片(iPhone)需要 pillow-heif 包,或者将其导出为 JPEG。
当你知道零件类型、照片文件,并且用户同意使用 Brickognize 时,此步骤完成。
2. 安装检查与目录
lsf.py selftest # 离线,几秒钟;必须以“0 failed”结尾
lsf.py data --info # 退出码 0:目录已安装,进入步骤 3
如果缺少 Pillow,脚本会提示如何安装。
用户需要手动下载 Rebrickable 目录(仅一次):Rebrickable 的条款禁止自动下载,因此你本人或任何工具都不得自动获取这些文件。运行 lsf.py data:它会打印下载页面和所需的具体文件(它会故意以退出码 1 结束)。将文件列表告知用户,让他们将文件保存到一个文件夹中(下载文件夹即可),并等待他们告知已完成。然后执行:
lsf.py data --from ~/Downloads # 或者用户使用的其他文件夹;会提示仍然缺失的文件
当 lsf.py data --info 退出码为 0 时,此步骤完成。下载文件约 17 MB;索引占用 ~/.cache/lego-set-finder(或 $LEGO_SET_FINDER_DATA)约 115 MB。后续若要刷新目录,用户需重新下载文件,然后再次运行 data --from。
3. 找到零件
lsf.py detect RUN <照片或文件夹>
该命令会生成 RUN/overview/<photo>.jpg:每张照片上带有编号框和每 100 像素的网格标签。打开每张总览图,判断每个框:
- 保留只包含一个完整辨识零件的框;
- 去掉包含普通砖和板、背景、阴影、纸张边缘以及零件碎片的框;
- 替换包含两个紧贴零件的框,为每个零件单独创建一个框;
- 为每个没有框的辨识零件添加一个框(浅色零件放在浅色底板上经常被漏检)。
lsf.py boxes RUN <photo> --only 3,7,12 # 只保留这些自动框,删除其余
lsf.py boxes RUN <photo> --drop 9 --add 405,225,515,385:figure --add 395,380,500,500
坐标单位为总览图像素 (x0,y0,x1,y1),可从网格上读取。每次调用都会重新绘制总览图,只显示保留的框:自动框为洋红色,你的框为青色。每次修正后再次检查。当零件较小或排列紧密时,使用 lsf.py zoom RUN <photo> x0,y0,x1,y1 将该区域放大两倍显示,坐标不变,网格每 50 像素;从放大图中读取框的角点坐标。
当每张总览图上每个辨识零件都恰好在保留的框内,且每个保留的框只包含该零件时,此步骤完成。
4. 裁剪并检查裁剪图
lsf.py crop RUN
打开每张 RUN/sheets/crops_<photo>.jpg。每张裁剪图必须显示一个完整的零件。如果不符合,使用 lsf.py boxes 调整框,然后再次裁剪,直到所有裁剪图都满足要求。
5. 识别
lsf.py identify RUN
将每张裁剪图发送给 Brickognize,默认每次 3 张(--workers 参数,最多 4)。答案会按图片和端点缓存,因此对已发送过的裁剪图重复运行不会产生额外费用。当新调用达到 300 次时会停止(退出码 2):询问用户是否允许使用更高的 --max-calls 值重新运行。
没有答案的裁剪图会被列出。Brickognize 对大型或柔软零件(车体、车厢、布料)经常找不到结果。可尝试使用 --endpoint predict/parts/ --only <crops> 再次识别。仍然失败的零件,你将在步骤 6 中自行命名。
6. 映射并检查每个零件
lsf.py match RUN --kind duplo # 或 --kind lego
该命令生成 RUN/pieces.tsv,每行对应一个裁剪图:Brickognize 的答案、映射到的 Rebrickable 零件或人仔编号(rb,不确定时列出多个)、颜色和置信度。它会先打印所有行供检查,其中每行的人仔匹配结果会保留可能明显错误的候选(例如将女孩识别为男孩)。打开每张 RUN/sheets/review_<photo>.jpg(裁剪图、置信度、Brickognize 识别名称、Rebrickable 编号和颜色),将裁剪图与其说明进行比较。
使用目录辅助工具修正错误:
lsf.py lookup yellow truck flatbed grille --duplo --colour Yellow # 按名称或零件号搜索
lsf.py fix RUN p10-m1 --rb 15454pr0006 --colour Yellow
lsf.py fix RUN p08-27 --colour "Neon Yellow" # 你的眼睛比 Brickognize 更准
lsf.py fix RUN p08-m3 --use n # 无法识别:排除该零件
lsf.py set 10931 # 查看套装的零件清单,用于验证猜测
lsf.py sets-of 14094 --colour "Medium Azure" # 查看哪些套装包含指定颜色的零件
对于 Brickognize 未能识别的零件,根据你的观察确定其名称,然后使用 lookup 搜索;选择名称和颜色匹配的候选。当两个或三个候选同样匹配时,全部列出(--rb a;b;c):排名算法处理多候选比处理错误猜测更好。如果一个得宝积木堆被识别为非得宝零件,通常就是错误的。
当每行中 use = y 的条目都有你确认的 rb 和颜色,且你无法担保的条目都有 use = n 时,此步骤完成。
7. 套装排名
lsf.py rank RUN
阅读 RUN/sets.md。对于每个套装,显示其等级(很可能、可能、微弱)、排名分数、指向该套装的零件数量、其中其他套装没有的零件数量、在该套装自己的辨识零件中照片里出现的比例,以及逐项的证据。
将“很可能”的套装以表格形式展示给用户(套装编号、名称、年份、零件数、独占零件数、出现在照片中的占比),然后“可能”的套装每行一个。特别指出:
- 标注为“与...共享证据”的套装:它们竞争相同的零件,因此询问用户实际拥有哪个;
- 在多个共享零件上得分但自身辨识零件出现比例低的大型套装:这些通常是误报;
- 没有被任何列出套装解释的辨识零件:可能还有其他套装在积木堆中。
询问用户他们认识或想要列入核对清单的套装。核对清单中的 Rebrickable 链接会显示该套装的盒装图片。
8. 生成核对清单页面
lsf.py page RUN --sets 10906,10931,10963 [--confirmed] [--title "我们的得宝"]
如果不加 --sets,则使用“很可能”等级的套装。--confirmed 将每个套装标记为已确认(在用户检查后使用)。生成的 RUN/checklist.html 是一个文件,从磁盘打开即可使用。告知用户如何使用:选择一个套装或切换到“按颜色分类”,点击零件计数以标记已找到的零件,“隐藏已找到”查看还缺少什么,“缺失零件列表”复制仍缺失的零件,“保存或重置勾选”可将勾选状态保存在文件中。勾选信息仅保存在当前浏览器中。零件图片从 Rebrickable 的图片服务器加载,因此需要网络连接。
9. 列出缺失零件
在用户整理之前,告知他们每个选定套装的哪些辨识零件没有出现在照片中:
lsf.py missing RUN --sets 10906,10931
明确说明“未出现在照片中”不等于“缺失”:因为只拍摄了辨识零件。如果之前标记为 use = n 的裁剪图恰好匹配某个缺失零件,请重新查看该裁剪图,如果匹配则用 lsf.py fix RUN <裁剪图> --use y 恢复它;然后重新排名。整理完成后,使用页面复制的列表或页面保存的勾选文件(lsf.py missing RUN --sets ... --ticks <文件>),输出每个套装的缺失零件清单。
需要告知用户的限制
- 本技能仅在一个混合得宝收藏(12 个套装)上使用 macOS 测试过。标准乐高和 Windows 未测试。
- Brickognize 是免费的第三方服务;零件裁剪图会上传至该服务,其可能保留并使用这些图片(步骤 1)。其 predict 端点在 API 描述中标记为“遗留”(legacy),因此可能变更或停止。
- Rebrickable 目录需要手动一次性下载(11 个文件,约 17 MB;索引占用约 115 MB),且会逐渐过时;要刷新,需重新下载文件并再次运行
lsf.py data --from。 - Rebrickable 和 BrickLink 对某些零件的编号不同,得宝人仔尤其明显。映射后的人仔和印刷件带有置信度;请通过目视检查可疑项。