关于 thicken
thicken 将实物照片转换为按真实尺寸构建的 GLB 模型及 JSON 元数据,面向需要数字化书籍、卡片等物品的用户。它通过对象配置文件确定几何形状和记录字段,而非使用摄影测量。
主要功能
- 01照片生成真实尺寸 GLB 模型
- 02输出描述对象的 JSON 元数据
- 03通过条码、二维码或视觉识别类型
- 04支持书籍、卡片、徽章及盒状物
- 05可添加自定义对象配置文件
适用场景
- 01为书籍封面和书脊生成 3D 模型
- 02记录评级卡片及其标签信息
- 03将徽章图稿转换为挤出模型
MCP 相关
thicken 可作为 MCP 服务运行,供 MCP 客户端调用照片生成模型和元数据;也提供 Agent Skill,说明何时及如何使用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y thickenTHICKEN_VISION_URLAn OpenAI-compatible vision endpoint (optional): photos needn't be croppedTHICKEN_VISION_KEY密钥The vision endpoint's keyTHICKEN_VISION_MODELSThe endpoint's model names, comma-separated, primary firstGOOGLE_BOOKS_API_KEY密钥Your own Google Books quota, for book sizes本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
2收录的工具列表 · 更新于 3 天前
此工具无需参数。
详细介绍
输入照片,输出物体:它的 3D 模型及元数据。
thicken 可将真实物体的照片转换成按实际尺寸制作的 GLB 模型, 并生成以 JSON 格式保存的元数据:视觉模型从物体上读取信息, 再通过公开目录进行查询。每种物体的相关知识都保存在一个 配置档案中:thicken 自带几个配置档案,你也可以添加自己的配置档案。
每组都展示了输入的照片,以及输出的模型和元数据,如下方所示。上方的标志也是 thicken 模型,由其字母配置档案制作:thicken lettering thicken。
另一部分:元数据。 以下是第一组内容的一部分,即一张经鉴定的 Giannis Antetokounmpo 卡片:
{
"profile": "slab",
"holder": "cgc",
"grader": "cgc",
"cert": "6072896005",
"widthMm": 80.5, "heightMm": 135, "depthMm": 7.5,
"read": {
"grade": "9", "gradeName": "MINT",
"autoGrade": "10", "autoGradeName": "AUTO",
"signed": "G. ANTETOKOUNMPO, 8/2/25",
"name": "Giannis Antetokounmpo", "year": "2024-25", "maker": "Panini",
"set": "Court Kings Basketball", "number": "#5", "variant": "Blank Slate"
},
"readBy": { "grade": "agreed", "autoGrade": "agreed", "set": "disputed" },
"inside": {
"card": { "widthMm": 63.5, "heightMm": 88.9, "corners": "square", "foil": "none" },
"label": { "widthMm": 66.4, "heightMm": 26.9 }
}
}
鉴定机构和证书编号取自标签上的 QR 码;视觉模型会从卡壳上读取其余信息。每种配置档案会记录哪些内容,请参阅配置档案表;每个字段的说明见 USAGE.md。
目录
- 试用 · 通过 AI Agent 使用 · 工作原理 · thicken 对象 · 生成内容
- 详细说明(USAGE.md):批处理 · 照片 · 视觉识别 · 视频 · 训练模式 · 审核 · sidecar 文件 · 预览 · 输入 · 尺寸
- 哪些内容会离开你的设备 · 添加配置档案 · 安全性 · 基于哪些项目构建 · 开发 · 许可证
试用
npm install -g thicken # Node 22.18 or later; or npx thicken …
thicken photo.jpg # it works out what it is: a code on it, or the vision models
thicken book cover.heic back.heic spine.heic
thicken --isbn 9780061120084 # no photo: the cover and size from Open Library
thicken slab front.jpg back.jpg
thicken card front.jpg back.jpg --pt 130 # a thick patch card
thicken badge badge.png --width 50 # cut-out artwork, extruded
thicken lettering thicken # the logo
thicken batch ~/Pictures/books --preview # a model per photo, PDF, video or folder
每次运行都会在第一张照片所在目录写入 <name>.glb 和 <name>.json;使用
--preview 时,还会生成一张展示正反两面的图片。正对物体拍摄并裁剪好的照片可直接使用;未裁剪的照片、倾斜拍摄的照片和视频则需要配置视觉模型服务清单,并使用任意兼容 OpenAI 的端点(视觉识别)。作为库使用时:先执行 import { thicken } from 'thicken',再调用 thicken(files, options),即可获取 GLB 字节数据和 sidecar 文件。
通过 AI Agent 使用
thicken 也是一个 MCP 服务(thicken mcp),并提供了一个 Agent Skill,告诉 Agent 何时以及如何使用它:只要要求生成你桌上那本书的模型,Agent 就会制作出来。在 Claude Code 中:
/plugin marketplace add bikemeardsley/thicken
/plugin install thicken@thicken
或者,对于任意 MCP 客户端,可通过 stdio 运行 npx -y thicken mcp。Codex、Copilot、
Cursor、Antigravity、Gemini CLI 等其他工具的说明见 USAGE.md。
工作原理
thicken 对某类物品的了解都存放在它的档案中:如何识别该物品、它有哪些面、要读取哪些内容,以及如何按实际尺寸构建它。物品上的代码会选出对应档案(ISBN 条形码、评级机构的 QR 码),或者由视觉模型判断物品类型。thicken 不是摄影测量工具:它处理的物品都近似于盒子或平面轮廓,因此会根据已知尺寸构建几何体,并将你的照片映射到几何体上。
thicken 物体
thicken 生成的不只是一个 3D 形状。每次运行都会写入一个thicken 物体:模型(按物品实际尺寸、以毫米为单位的 GLB 文件),以及与之配套的元数据(JSON 伴随文件),其中记录了该物品是什么,并使用其档案中的术语描述。以 thicken 自带的档案为例:
- **一本书:**其 ISBN、目录记录(标题、作者、出版商、日期、主题、杜威分类和美国国会图书馆分类、页数),以及通过标题找到匹配项时的匹配置信度。
- **一张评级卡砖:**评级机构、证书编号和验证链接、卡砖,以及其中的卡片和标签,并分别记录尺寸和位置。使用视觉模型时,会读取标签内容:卡片的评级(数字和文字,“9 MINT”、任何附加评级和子评级)、标签对签名单独评级而非对卡片评级时签名的评级(“AUTO 10”)、签名者及签名日期,以及评级机构对卡片的命名。
- **一张未封装的卡片:**尺寸、厚卡的厚度(以 points 为单位)、边角和箔面。使用视觉模型时,还会读取卡片上的印刷内容:球员或角色、球队、年份、制造商、系列、编号、平行版。
- **一个盒子:**使用视觉模型时,会读取其名称、品牌、版本、评级和年份。
- **一枚徽章:**使用视觉模型时,会读取其名称、颁发方、级别、主题、日期、凭证编号(如有)以及上面的所有其他文字。
- **每种物品:**视觉模型读取的内容及置信度;哪些面来自你的照片、哪些是替代图;每条信息的来源;还值得拍摄哪些内容;以及每个视觉模型的回答。
应用会显示模型并读取伴随文件:可以查看书籍的图书馆书架,也可以查看评级卡砖的收藏库。字段详见伴随文件记录的内容。
它能生成什么
thicken 负责生成 3D 物体;它对各类物品的了解存放在档案中,每个档案都是 src/profiles 下的一个文件。任何人都可以添加档案(CONTRIBUTING.md)。目前已有的档案包括:
| 配置文件 | 含义 | 来源 | 生成效果 | 通过视觉识别读取的内容 |
|---|---|---|---|---|
badge | 镂空数字艺术品:认证徽章、徽标或贴纸设计 | 带透明背景的艺术图(--width、--depth,单位为 mm) | 沿艺术图自身轮廓挤出:正面呈现图案,侧面和背面呈现边缘颜色 | 名称、颁发者、等级、主题、日期、ID、文本 |
book | 一本书,精装或平装 | 封面、封底、书脊和书页侧面,顺序不限且可任意组合;或仅提供 ISBN | 根据 ISBN 的目录记录按实际尺寸生成:平装书边角略圆,精装书的封面板略微超出书页 | 书名、副标题、作者、丛书、出版社、版次 |
card | 一张单独的集换式卡牌,不含塑料保护壳 | 正面和背面 | 一块薄片,尺寸为 63.5 × 88.9 mm(除非指定 --size),厚度为 0.35 mm(除非通过 --pt 指定厚卡牌的磅数);根据视觉模型识别结果切出圆角并呈现闪亮的烫箔效果 | 名称、队伍、年份、制造商、系列、编号、变体 |
lettering | 由文字组成的蓬松 3D 气泡字 | 文字,像放置图片一样输入(宽度为 --width mm,厚度为 --depth mm) | 使用 Titan One 字体生成蓬松的金色气泡字,截面呈气球般的圆形 | – |
slab | 密封在透明塑料评级卡壳中的评级集换式卡牌,带有标签 | 正面和背面 | 按评级机构的尺寸生成透明塑料保护壳,卡牌和评级标签位于壳内,分别从照片中切出 | 评级机构、评级、评级名称、限定词、子评级、自动评级、自动评级名称、签名、已签名、认证编号、名称、队伍、年份、制造商、系列、编号、变体 |
box | 盒状物品(游戏盒、手机、卡牌套牌、包装) | 正面,以及任意背面和侧面;其尺寸(--size),或由视觉模型估算 | 生成边角略圆的盒子,照片位于各个面上 | 标题、品牌、版本、评级、年份 |
每种配置在其旁边的 sidecar 中记录的内容,以及所有模型共有的信息(尺寸和来源、各个面及其图片、代码、视觉模型读取的内容及置信度、值得再次查看的内容:详见 USAGE.md):
badge:edge、regions
| 字段 | 内容 |
|---|---|
edge | 紧贴轮廓内侧的颜色,用于侧面和背面(#rrggbb) |
regions | 艺术图包含的独立形状数量(奖章和它的缎带算两个) |
book:isbn、catalog、match、pages、binding、bindingBy、measuredBy、depthEstimates、coverUrl、sticker、lookups
| 字段 | 内容 |
|---|---|
isbn | 其 ISBN:用户提供的、从条形码读取的,或通过仅匹配到一个版本的书名获得的 |
catalog | Open Library 中该版本及其作品的记录:书名、作者、出版商、日期、版次、格式、丛书、语言、主题、杜威分类和 LC 分类、目录、所有 ID、链接、封面 |
match | 根据书上读取的书名查找时记录的内容:读取结果、匹配置信度、作品及其各个版本 |
pages | 页数 |
binding | 精装或平装 |
bindingBy | 书籍装帧类型的判断依据:视觉识别、目录或假定 |
measuredBy | 各项尺寸的来源:实测、openlibrary、loc、googlebooks、pages、photos、cover 或 trim |
depthEstimates | 所有厚度估算值:根据照片估算的和根据页数估算的 |
coverUrl | 当正面未拍摄时用作替代的 Open Library 封面 |
sticker | 封面上烫箔封印或贴纸的位置 |
lookups | 每次目录请求的信息:主机、路径、状态和时间 |
card:corners、cornersBy、foil、foilBy、pictureBox、pictureBoxBy、pt、measuredBy
| 字段 | 内容 |
| --- | --- |
| `corners` | 角的切角方式:方形、轻微切角或圆角 |
| `cornersBy` | 判定方式:视觉识别或假定 |
| `foil` | 箔膜类型:无、全息(图案会闪亮)、反向(除图案外的部分)或全覆盖 |
| `foilBy` | 判定方式:视觉识别或假定 |
| `pictureBox` | 对于全息和反向箔膜,图案框的位置,以正面尺寸的比例表示 |
| `pictureBoxBy` | 判定方式:视觉识别或标准布局 |
| `pt` | 厚卡片的厚度,单位为磅(如有提供) |
| `measuredBy` | 尺寸来源:标准值或提供值;厚度来源:标准值、提供值或 `pt` |
lettering:text、font、fontLicense、color、measuredBy
| 字段 | 内容 |
|---|---|
text | 字样的文字 |
font | 绘制文字所用的字体 |
fontLicense | 字体许可证(OFL-1.1) |
color | 字体颜色 |
measuredBy | 宽度和深度的来源:提供值、默认值或截面圆整值 |
slab:grader、cert、verifyUrl、holder、inside、measuredBy
| 字段 | 内容 |
|---|---|
grader | 评级机构:psa、bgs、cgc、sgc 或 tag,根据其 QR 码或标签识别 |
cert | 认证编号 |
verifyUrl | 评级机构用于查询此认证编号的页面,取自其 QR 码 |
holder | 制作时所用的卡壳(psa、cgc-tall…) |
inside | 内部的卡片和标签:各自的尺寸、中心位置及固定方式;卡片的角和箔膜;标签全息图的位置 |
measuredBy | 尺寸来源:卡壳表格或实测值 |
box:barcode、measuredBy
| 字段 | 内容 |
|---|---|
barcode | 产品条码(UPC 或 EAN)及其类型(照片中可见时) |
measuredBy | 各项尺寸的来源:实测值或视觉模型的估算值 |
指定配置文件名称;若省略,则由 thicken 选择:
- 任意图片中出现 ISBN 条码,或使用
--isbn,表示这是一本书籍。 - QR 码指向评级机构网站(psacard.com、beckett.com、
cgccards.com、gosgc.com、taggrading.com),表示这是一个评级卡壳,并可识别所属机构。
sidecar 会保留评级机构、链接中的认证编号以及链接本身(
verifyUrl)。 - 旧标签上的 Code 128 认证条码也可以识别,但仅限照片呈卡壳形状的情况。此时,评级机构由视觉模型读取标签得出;若没有视觉识别,则假定使用 PSA 尺寸的卡壳,并发出警告。
- 形状周围带有透明区域,且形状并非单纯矩形的图稿,表示这是一个徽章。
- 其他情况下,如果启用了视觉识别,系统会向模型展示这些配置文件,让它们判断类型和大致尺寸:与人脸识别一样,由两个模型一致判定;
box则接收其他配置文件未涵盖的盒状物体。 - 仍无法识别的对象会被拒绝,并要求指定配置文件。其他条码不算:书籍也会有 UPC、QR 码和图书馆贴纸。
sidecar 的 identifiedBy.profile 会说明配置文件的选择方式:given(指定)、recognized(通过代码或图稿识别)或 vision(视觉识别)。
添加配置文件只需在 src/profiles 中添加一个文件,无需修改其他内容:为它命名;用几句话描述它是什么,以及每个面的特征(视觉模型只会看到这些信息);指定要读取的内容(越多越好:应用可以从 sidecar 中挑选所需信息);可选地说明如何在没有辅助的情况下通过代码或图片识别它;以及如何根据放置在各面的照片构建它。通用配置文件按其构建的形状命名(如 box,之后可能会有 flat 或 cylinder),而不是命名为“unknown”:对于 thicken 无法构建的形状,会直接拒绝,而不会强行套用其他形状。欢迎贡献:CONTRIBUTING.md 说明了具体方法。
图片会根据所展示的内容放在相应的面上(参见
照片)。如果没有正面,就用 Open Library 的封面代替,并标记为待审核,因此只需一张背面照片就可以开始制作一本书。
哪些内容会离开你的设备
设置 THICKEN_VISION_URL 后,照片本身(会重新编码,因此不含 EXIF)会发送到该主机。由你控制的局域网服务仍会将每张照片转发给模型提供方;托管端点则会看到每张照片。其他对外调用仅用于查询书籍目录(Open Library、Library of Congress、Google Books),发送的是书籍的 ISBN,或模型从照片中读取的书名和作者;绝不会发送照片。
不会向任何地方发送其他内容,运行时也不会获取任何内容,除了这些目录查询:预览使用从你自己的磁盘加载的 model-viewer 渲染。
添加配置文件
配置文件是一个独立文件,其中包含对象是什么、它有哪些面、需要从中读取什么,以及如何构建它。你可以在使用 thicken 时创建自己的配置文件,或改进现有配置文件,然后提交回来:
thicken profile new vinyl # from the template, in ~/.thicken/profiles: used at once
thicken profile check vinyl # what thicken's CI will check
thicken profile contribute vinyl # forks, branches, checks and opens the pull request
模板 templates/profile.ts 开箱即用(按你给定的尺寸创建一个盒子),并在每个字段中说明应填写什么,包括它写入的记录。CONTRIBUTING.md 介绍了其余内容。上面的表格由这些配置文件生成。
安全
请按照 SECURITY.md 中的说明私下报告漏洞。该文件还列出了 thicken 会接触的内容:文件、网络和它运行的程序。
构建于
| 部分 | 方式 | 选择 |
|---|---|---|
| 徽章轮廓三角剖分 | 依赖项 | mapbox/earcut(ISC) |
| 写入 GLB | 依赖项 | donmccurdy/glTF-Transform(MIT) |
| 解码 HEIC | 依赖项 | catdad-experiments/libheif-js(LGPL-3.0,未经修改直接使用)。sharp 的二进制文件不包含 HEVC。 |
| 读取条形码 | 依赖项 | Sec-ant/zxing-wasm(MIT)。其 .wasm 从 node_modules 加载,而非默认 CDN。 |
| 从扫描版 PDF 获取图片 | 依赖项 | unjs/unpdf(MIT,内部包含 pdf.js) |
| 从视频提取帧 | 外部程序 | FFmpeg,从 PATH 运行,绝不打包:它采用 GPL,会使 MIT 许可更严格。eugeneware/ffmpeg-static(GPL-3.0)会在每次安装中都放入 GPL 二进制文件,无论是否使用视频;ffmpegwasm/ffmpeg.wasm 是为浏览器构建的。帧的选择由我们完成。 |
| 读取相机信息(EXIF) | 依赖项 | devongovett/exif-reader(MIT):解析 sharp 返回的 EXIF 块 |
| 绘制预览 | 依赖项 | google/model-viewer(Apache-2.0):为 GLB 添加帧和灯光;内部使用 three.js |
| 运行预览浏览器 | 依赖项 | microsoft/playwright(playwright-core,Apache-2.0):驱动已安装的 Chrome 或 Edge,不下载浏览器 |
| MCP 服务 | 依赖项 | modelcontextprotocol/typescript-sdk(MIT),官方 SDK;使用 colinhacks/zod(MIT)处理其工具的输入 |
| 图书尺寸来源 | 自行编写 | 参考 palmerabollo/node-isbn 的提供方回退逻辑。我们按尺寸分别处理,而非采用首个提供方的结果。美国国会图书馆的单个字段(MARC 300)用正则表达式读取,而非使用 MARC 库。 |
| 精装书 | 自行编写 | 由 src/glb.ts 创建四个圆角方盒;装订方式则由视觉模型像判断卡片圆角那样询问得出。 |
| 全息箔 | 自行编写 | 各类箔材的反光区域参考 simeydotme/pokemon-cards-css(GPL-3.0:仅读取事实,未复制内容);薄膜参数采用 KHR_materials_iridescence 的默认值,与 KhronosGroup/glTF-Sample-Assets 的用法相同;扩展由已是依赖项的 glTF-Transform 写入。 |
| 配置文件、方盒、分类器、CLI | 自行编写 | |
| 卡砖、卡片和标签 | 自行编写 | 透明卡砖使用 glTF-Transform 的材质(已是依赖项);卡片和标签板、它们的位置以及组装方式均由我们实现。透明材质参考了 Khronos 的 glTF-Sample-Assets。 |
| 在照片中寻找面部 | 自行编写 | 通过任意兼容 OpenAI 的端点调用视觉模型,包含主模型和同级模型(src/vision.ts):每个模型各发起一次 POST,不使用 SDK。 |
| 校正面部透视 | 改编,不依赖 | jlouthan/perspective-transform(MIT):采用其 4 点单应变换;在 sharp 像素上进行重采样的部分由我们实现。sharp 不支持透视变形,而 OpenCV.js 为此需要数 MB。 |
| 将角点吸附到边缘 | 自行编写 | src/image.ts 中的 snap 会将模型检测的角点(约有 1% 的偏差)移到真实边缘上。它沿每条边采样亮度变化,找出最接近模型边缘且受这些采样点支持的直线,再用最小二乘法拟合,每张面约需 70 ms。我们参考了 puffinsoft/jscanify 的角点排序;在模型角点附近拟合直线已足够。 |
| 字体字样 | 依赖项 | 使用 opentypejs/opentype.js(MIT)读取字体:获取经过字距调整的文字轮廓。字体为 Rodrigo Fuenzalida 创作的 Titan One,以 SIL Open Font License 1.1 原样发布(fonts/OFL.txt;“Titan”为其保留字体名称)。 |
| 字母膨胀 | 改编,不依赖 | 每个像素到轮廓的距离采用 mapbox/tiny-sdf(BSD-2-Clause)的精确距离变换,并移植后用于将轮廓定位到小于一个像素的精度。凸起部分由我们实现:√u,其中 ∇²u = −2,作用于字母内部,沿任意笔画的横截面呈圆形。 |
对于查看器中的折射和全息效果,simeydotme/pokemon-cards-css 仅供参考。它采用 GPL-3.0 许可证,请阅读其内容,但不要复制。 |
开发
使用 Node 22.18+ 上的 TypeScript,并使用 sharp 处理图像。从克隆的仓库中可以直接运行(Node 会剥离类型)。npm 包是构建到 dist 中的 JavaScript(通过 npm run build 构建,由 npm pack 和 npm publish 运行),因为 Node 不会剥离 node_modules 中的类型。每次推送都会在 Windows、macOS 和 Linux 上安装打包后的软件包并运行它。
从克隆的仓库开始:运行 npm install,然后用 node src/cli.ts … 代替
thicken …;修改配置文件后,运行 npm test、npm run check 和 npm run readme。
许可证
MIT。请参阅 LICENSE。
字母字体 Titan One 采用 SIL Open Font License 1.1 许可证 (fonts/OFL.txt)。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。