photo-doodle
在照片上程序化手绘马克笔涂鸦(白色/彩色、水彩/蜡笔/荧光/闪光/毛绒多种笔刷),输出静态成品图 + "一笔一笔画出来"的逐笔绘制过程视频(MP4)。当用户想给照片/自拍/人像加手绘涂鸦、贴纸感装饰、猫耳猫须变小猫、毛绒尾巴、颜文字、像素贴纸、天使光环、爱心星星、手账标注、涂鸦短视频,或提到 photo doodle、照片涂鸦、给照片画点什么、涂鸦动画时使用。设计必须从照片具体内容出发(先列名词清单→定主导元素家族→自审),严禁默认撒花撒星配 golden hour 类套话——SKILL.md 第 1-4 步是防套路硬闸,务必逐步执行。三条硬闸:每个元素必须写出依据照片什么、一版最多一句文字(英文+手写体)、笔画粗细至少 3 档且要有 W_BOLD 级粗笔。标准流程:若有生图模型(Codex 等)先生成涂鸦设计稿作布局参考,再用引擎真矢量笔迹在原图上复刻;没有则直接自行设计。渲染纯 PIL+ffmpeg 本地完成,最终照片本身不被修改(涂鸦是叠加层)。
ソース情報
- リポジトリ
- Vincentwei1021/photo-doodle
- ソースの最終更新活動
- 2026年8月25日 20:21
- 検出された SKILL.md の言語
- 中国語
- スター
- 1
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
SKILL.md を表示中
SKILL.md
ソースの指示 · 読み取り専用プレビュー- name
- photo-doodle
- description
- 在照片上程序化手绘马克笔涂鸦(白色/彩色、水彩/蜡笔/荧光/闪光/毛绒多种笔刷),输出静态成品图 + "一笔一笔画出来"的逐笔绘制过程视频(MP4)。当用户想给照片/自拍/人像加手绘涂鸦、贴纸感装饰、猫耳猫须变小猫、毛绒尾巴、颜文字、像素贴纸、天使光环、爱心星星、手账标注、涂鸦短视频,或提到 photo doodle、照片涂鸦、给照片画点什么、涂鸦动画时使用。设计必须从照片具体内容出发(先列名词清单→定主导元素家族→自审),严禁默认撒花撒星配 golden hour 类套话——SKILL.md 第 1-4 步是防套路硬闸,务必逐步执行。三条硬闸:每个元素必须写出依据照片什么、一版最多一句文字(英文+手写体)、笔画粗细至少 3 档且要有 W_BOLD 级粗笔。标准流程:若有生图模型(Codex 等)先生成涂鸦设计稿作布局参考,再用引擎真矢量笔迹在原图上复刻;没有则直接自行设计。渲染纯 PIL+ffmpeg 本地完成,最终照片本身不被修改(涂鸦是叠加层)。
# photo-doodle:照片手绘涂鸦 + 过程视频
在照片上生成像真人用马克笔画的涂鸦:抖动笔迹、圆头笔画、笔锋收细、暗色底影、柔光。每个版本同时产出静态 JPG 和逐笔绘制过程 MP4(观众能看到每一笔被画出来,文字按书写方向擦入)。
**铁律:原照片一个像素不动,所有涂鸦必须是引擎的真矢量笔迹逐笔画出。** 禁止像素揭示/图像差分显现类方案。
## 标准流程(先判断走哪条路)
1. **有生图模型可用**(Codex CLI 等)→ 先让 AI 基于目标照片生成一张涂鸦设计稿(**仅作元素布局参考**),叠网格量出各元素归一化坐标,再用引擎矢量笔迹在原图上复刻。完整步骤(生成命令、量坐标方法、并排比对质检)见 `references/design-replica.md`——**走此路径前必读**。
⚠️ **人物特写照片:生图模型几乎必然返回撒花撒星套路**(实测两次:一次回了 6 朵花 + 14 颗星 + "Sunshine girl",一次回了 14 颗星 + 3 朵花 + 笑脸云,落点还是内容无关的——花贴在衣服上、星压在头发上看不见)。这种情况下**只把它当留白地图用(哪里空、哪里可放东西),不要在它基础上做删减**——"花从 6 朵减到 3 朵、星从 14 减到 4"只会得到一个能通过所有数值检查的**稀释版套路**。设计仍要按下面第 1-4 步从零做。
**复刻流程与防套路闸冲突时,以防套路闸为准**:design-replica.md 讲的是"如何精确复刻一张设计稿",它假设那张稿子值得复刻;纪实/风景稿常常值得,人物特写稿基本不值得。
2. **没有生图模型** → 不用参考,直接按下面的工作流程自行构思设计并画。
两条路都要求:设计适配照片本身的风格与美感——色调、情绪、留白位置决定用色、元素密度与落点,不要把同一套元素硬套到所有照片上。
## 工作流程
### 1. 读照片,写"内容清单"(防套路第一道闸)
用 Read 亲眼看照片,然后把下面四项**写出来**(写进你的回复,不是心里过一遍):
- **≥3 个具体名词**:照片里真实存在、能用手指着说出名字的东西(伞骨、石阶、墨镜、麦克风、马鬃、晒衣绳、笔记本电脑、白板……)。不许写"光线""氛围""青春感"这类抽象词。**逐个标注"这个我会不会真给它画元素"**——宁可 3 个真用得上,不要凑满 5 个然后一半闲置(真实教训:为凑数写了"领口抽绳结",最终设计里根本没用到它)。
- **1 个动作或姿态**:她指着脸颊 / 他举着手机 / 她握着缰绳 / 他在讲话。
- **现场光与色**:暖金逆光 / 黄昏蓝粉渐变 / 正午高反差蓝天 / 室内白墙冷光。同时**定下配色**:取画面主色调,本版只用它的同温色系 + 白(暖调照片就 YELLOW/LEMON/PEACH/CORAL/WHITE,冷调就 SKY/BLUE/LAVENDER/MINT/WHITE)。冷暖混用会和现场光打架。
- **留白区 + 实测亮度**:哪几块是天空/墙面/地面,各自的归一化坐标范围,**以及每块的实测平均亮度**。别凭眼估——亮度值直接决定文字用什么颜色才看得清,这是白笔迹在亮背景上糊掉的唯一防线:
```python
from PIL import Image; import numpy as np
im = np.asarray(Image.open(SRC).convert('L'), dtype=float)
H, W = im.shape
for name, (x0, y0, x1, y1) in {'左下石阶': (0.05, 0.72, 0.35, 0.95), '右上墙': (0.75, 0.05, 0.98, 0.30)}.items():
patch = im[int(y0*H):int(y1*H), int(x0*W):int(x1*W)]
print(f'{name}: L={patch.mean():.0f}') # L<110 白字安全;L>150 白字必糊,改用饱和色或深色
```
这份清单是后续设计的**唯一素材来源**。头发轮廓、肩膀外缘坐标也在这一步量好(戴光环/猫耳/皇冠、画翅膀要用)。
### 2. 定"主导元素家族"(防套路第二道闸)
**已知失败模式(真实案例,必读)**:三张完全不同的女生照片(逆光巷子、黄昏自拍、草原骑马)由三次独立的 skill 调用分别设计,结果全部收敛成同一套——满屏 `flower` + `dotflower` + `sparkle` + `star4`,配一句白色草写 `golden hour`,三张成品几乎无法区分。原因很朴素:面对"女生照片画可爱涂鸦",最省力的答案永远是撒花撒星加个英文短语,不加约束就会本能滑过去。男生的三张照片因为提示里给了具体方向(手账标注/太空/科技注解),反而各具面貌——**差别不在照片,在有没有硬约束**。
所以动笔前**先从下表选定 1 个主导家族**。选择依据是第 1 步的内容清单:照片里有什么,就选能呼应它的家族。主导家族决定这一版的"讲什么",外家族元素用来补充和呼吸——**没有数量上限**。
> ⚠️ **这里曾经有过三条数量闸(外家族 ≤4、星 ≤8、文字 ≤4),已被明确移除。** 原因:点名某个具体形状"不许超过 N 个",本质还是拿具体内容当指令(只是反过来说),而且在花/星真的贴合照片时会误伤。防套路的压力全部由「每个元素必须写出依据」这一条承担——说不出依据的就是通用装饰,写得出的就不是。
>
> **唯一保留的数量硬闸是文字:一版最多一句。** 文字是最响、最能定调的元素,两句起就开始像模板了。而且这一句要求:**英文 + 手写体**(`fname='marker'/'hand'/'note'/'chalk'`)。想说的其他话改成图形表达——手画颜文字(`emo_face`)、拟声线条、爪印轨迹都比第二句文案强。
> ⚠️ **闸是防套路的,不是让你画得少。** 真实反馈:加了这些闸之后有几版只画了 5-6 个元素,用户的评价是"画的内容太少了,我需要更丰富些,更多的元素,更丰富的想象力"。**目标是"丰富且每一笔都有出处",不是"干净但空"。** 落地要求:
> - **一版画 10-18 个元素组**(留白多的风景/大场景可以到 20+,脸占满画面的特写少些但也不该低于 8)。
> - 从一件实物可以**长出一整组元素**,这才是丰富的来源:一根真晾衣杆 → 挂三件小衣服 + 两个夹子 + 一条延续的线 + 随风的抖动线;一片真叶子 → 叶脉 + 叶柄 + 两片飘落的小叶 + 落地的弹跳弧。**"每个元素都有依据"不等于"每件实物只配一个元素"。**
> - 想象力要往"这件东西接下来会怎样 / 它像什么"发挥:马鬃可以画成被风梳开的线、雨伞可以长出水滴轨迹再溅成小花、影子可以画成小怪物、发梢的光可以拉成流星尾。这些都算有依据,因为起点是实测的真实物体。
> - 元素要有**层次**:大(一两个视觉重心)+ 中(三五个呼应主体的)+ 小(一批点缀:小点、短弧、碎星、气泡)。全是同一尺寸的中等元素最显得空。
> - ⚠️ **别把数量目标堆在同一个锚点上**:为了凑数往一个 0.04 见方的小区域里塞 8 笔,出来是个黄色爪印/爆炸星(真实返工,最后整组删掉)。同类小元素**彼此至少隔 0.05**,凑不够数就少画——`宁缺` 优于挤成一团。密度目标和间距规则要一起读。
> - ⚠️ **大片空白会产生真实的填充冲动,要有意识地抵抗它。** 一个代理事后诊断自己那三条编造的风线:那块天空是全图最大的区域,逐格标准差只有 0.7-2.0(数学意义上毫无特征),**正因为没有任何可锚定的东西,它才按构图需要撒了三笔**。空白区域越大越空,这股拉力越强。**诚实的回应是让它继续空着**——留白本身是照片的一部分,不是待填的坑。
> - ⚠️ **锚在同一个真实特征上的元素会互相抢位置,而且默认是"先画的赢"而非"更该留的赢"。** 真实案例:一个代理要把风线移到发梢真正所在的区域,却发现那里已经被自己先画的几组发梢卷线占满了,三个候选位置的净距都只有 0.020-0.029(低于 0.05 下限)。**发现空间冲突时要重新比较两组元素谁更该留,而不是默认给后来的找个次优位置。**
### 2.5 笔画粗细必须分层(硬闸,`audit()` 会拦)
真实反馈:"画笔要有粗细,不要全是那种细的,现在线条有点太细了,整体加粗一点,然后还需要有更粗的"。**元素数量够了但整幅仍然显得虚,根源几乎总是粗细没拉开**——早期脚本里满屏 `w=2.0~3.2`,那是引擎的旧默认值,不是有意选的。
引擎现在提供**粗细梯子**(按 900px 短边标定,`Doodle` 自动按真实分辨率缩放,所以同一个数字在 900px 自拍和 5712px 单反上视觉一致):
| 常量 | 值 | 用途 |
|---|---|---|
| `W_HAIR` | 2.5 | 碎发、缝线、腮红、叶侧脉——细节,不承担形体 |
| `W_THIN` | 4.5 | 普通轮廓 |
| `W_MED` | 8.0 | 主要元素的默认粗细(旧脚本的"正常"其实只有这个的 1/3) |
| `W_BOLD` | 16.0 | 视觉重心:大字、主动线、贴纸轮廓 |
| `W_FAT` | 30.0 | 特粗:粗横杠、涂满的形状,一版一两笔 |
比 `W_FAT` 还粗的东西(猫尾巴、绒球、大色块)**直接传数字**,别硬套梯子——毛绒猫尾巴约占图宽 10%,在 900px 短边上就是 `w=70` 左右。
`audit()` 拦两件事:**粗细不足 3 档**、**最粗笔 < W_BOLD**。两条都是"看起来虚"的直接成因。
⚠️ **梯子是按整图短边标定的,所以给小目标画轮廓时要按目标自身的尺寸判断粗细**:同一个 `W_MED` 在 264px 的大表盘上是细线,在 48px 的镜片上占了它高度的 22%,读成游泳镜(真实返工)。经验上限:**线宽不超过目标短边的 ~10%**。文档原有的尺寸建议只覆盖了贴纸的"形状大小",没覆盖"线的粗细"。
**圈东西时更具体的判据:`圈半径 ≥ 3 倍笔宽`。** 两个代理各自撞出同一条:在 1600px 图上 `W_MED` 约 11px,而一颗镜头半径只有 16px——用和特征一样宽的笔去描它,圈被填成一坨白斑、把真镜头**盖住了**;第二轮换 `W_BOLD`(21px)去圈 114px 的摄像头模组,吃掉 18% 面积,读成一个巨大的白色 "C"。**圈不是描边越粗越清楚,笔太粗会把被圈的东西吞掉**——而圈的意义正是让人去看那个东西。
文字要醒目,**只有一个正确旋钮:`size`**。
⚠️ **别用 `stroke_w` 加粗文字。** 这里的手写体(MarkerFelt 等)本身就是粗体,描边只会把字腔(o/e/a 的孔)填死。实测在干净背景、`size=46` 下:`stroke_w=1.0` 是上限,`2.0` 已经糊住所有孔,`2.5` 把 `posed` 渲成 `poeed`、把 `nobody` 的 o 渲成实心点。**四个独立的代理都为了"让字更清楚"去调它,四个都把文案毁了**(其中一个明确说是照着本文档的例子抄的)——所以引擎现在把 `stroke_w` 硬夹在 1.0 并打印警告。
正确的对应关系记牢:
- 字**不够醒目** → 加大 `size`
- 字在**杂乱背景**上看不清 → 用 `halo=4~5`(在字后垫深色柔光)
- 字在**均匀亮背景**上看不清 → 换位置(`mean` 必须 < 110),或换成饱和色而非白色
写完文字**必须裁出来放大 3 倍 Read 一眼**,逐个字母确认还认得出。这是最容易自欺的一步:缩略图上看着挺好,放大才发现单词已经不成词了。
**但"看不清"和"不够粗"是两个不同的问题,别拿 `stroke_w` 治看不清**:树影、草地这类**斑驳**背景平均亮度看着安全(L=98)但 p90 能到 190,白字会被那些亮斑吃掉。这时候加 `stroke_w` 只是把字母撑成一团(真实返工,`posed` 渲成了 `poeed`——o/s/e 的字腔被描边糊死),正确解法是 `text(..., halo=5)`——在字后垫一层深色柔光把它和背景分开。
**判定白字能不能用,`mean` 和 `p90` 是"与"的关系,两个都要过**:
- `mean` 必须 < 110(绝对亮度够暗)
- **且** `p90 - mean` 要小(没有零散亮斑)
只看其中一个都会翻车,两种翻车我都见过:只看 mean 会被树影里的亮斑打败(要 halo);**只看离散度会被均匀的亮草地打败**(真实案例:某版量出 p90-mean=16 就判定"安全",但 mean=109 已经是亮绿草地,白字整片washed out——离散度小只说明"糊得均匀")。`mean` 过不了就换位置,`mean` 过了但离散度大就上 halo。
⚠️ **`halo` 会吃掉画在它下面的东西**:文字在 `_composite` 里是最后一层,它的深色光晕会盖在已经画好的图形上。所以文字和它的下划线/横杠若有重叠,横杠会被啃出一道暗边。要么让两者不重叠,要么该处别用 halo。
**怎么数"一个元素"**:一个视觉上独立的图形 = 1 个,不论它由几笔或几次 API 调用画成。花冠里的 5 朵花算 5 个;`crown_sketch` 内部十几笔(轮廓+圆圈+缎带)只算 1 个;`frame()` 四条边算 1 个;荧光圈的两次 `arc`(填色+描线)算 1 个;一排 4 个色点作为一组算 1 个;文字连同下划线算 1 个;箭头连同它的标注文字算 1 个。简单说:**观众会当成"一件东西"的就是 1 个**。
**怎么判一个元素属于哪个家族**:**看它依据照片的什么,不看它用哪个图元画的**。在照片里真实的抽绳结上系一个蝴蝶结,即使形状是 bow(表里归在拟物贴纸),它依据的是实测到的那个真结、换张照片就不成立,所以它属于「器物呼应」。反之,一个凭空撒在脸旁的 bow 就是拟物贴纸的通用装饰。判据统一成一句:**这个元素依赖某个实测的照片事实吗?**
**主导家族自己的文案不算外家族**——每个家族都需要配字,标题/短句算在主导家族内,否则两句话就把外家族配额用光了。
**多个家族都合适时怎么选**(下面按顺序判,前一条能决出就不看后面):
0. **先问:照片里有"正在发生的事"吗?**(起风吹乱头发、她指着什么、他在讲话、马在低头、光正打在脸上)
- **有** → 优先选能表现那件事的家族(风→天气自然,动作方向→线条动效,握着的东西→器物呼应,说话→涂鸦文字)。**这是最优解**:事件既是事实又自带情绪,内容和气质会同时对上,不用二选一。
- **没有**(静止站姿、白墙背景、纯摆拍)→ **注意此时"信息量优先"会退化成"给名词贴标签",做出博物馆展签**。这种照片走装饰性家族(拟物贴纸/星辰光)是**正当的**,别硬凑标注——但每个装饰必须钉在实测位置上(皇冠贴着头发轮廓、星落在真实高光、心画在她真正指的地方),且文案写心里话而不是物件名。
1. **数第 1 步清单里"可指认名词"的个数**:≥4 个 → 选「标注手账」或「器物呼应」,因为只有这两个家族会**消耗名词**,其余家族只会往画面里**添**东西。
**这两个家族消耗名词的方式不同,别默认选第一个**:「器物呼应」是**延续**实物(把涂鸦接到真东西上——在真晾衣杆上挂几件小衣服、在真抽绳结上系个蝴蝶结、给真叶子补叶脉),「标注手账」是**指着**实物(箭头+标签,站在画面外评论它)。
- **延续天生更柔和**,因为涂鸦是加入场景;**指向天生更硬**,因为箭头/边框/胶带本身就是硬边工具,装在朦胧柔美的照片上必然读成博物馆展签。
- 所以:照片朦胧/柔美/梦幻 → 优先「器物呼应」;照片纪实/信息型/硬朗(演讲、登顶、街拍)→「标注手账」。
- 真实教训:一张暖调逆光柔美人像按"标注手账最百搭"选了它,做出四条引线加裸名词,内容全对但气质全错;换成器物呼应重做后(衣服挂在真杆上 + 领口真结上系蝴蝶结 + 口语文案)气质立刻对了。
- ⚠️ **「延续」不等于「照着描一遍」**:把实物用同等粗细的平行线再描一次,出来是一条压在实物上的色块(真实返工:一条 W_FAT 黄色板砖横过马颈;改成对称弓形线后又变成 SKILL 自己记录过的叶片形)。**延续 = 把实物的轮廓或运动轨迹往外接出去**(绳子往画外续、鬃毛顺风梳开、车辙延伸、印花从布面飘起来),不是在原地重绘它。同等粗细的重描一律是错的。
2. 照片主体握着/穿着/用着某件有辨识度的东西 → 「器物呼应」。
3. 有明确动作方向 → 「线条动效」;天空占比大 → 「天气自然」。
4. 以上都不成立,才考虑装饰性家族——它们在平手时排最后,**但第 0 条的"静止照片"例外优先于本条**。
> 这条第 0 项来自实测对比:同样在守规则的前提下,一张"起风吹乱头发"的黄昏自拍做出了风线+夕阳+「风好大」(柔美且具体),而一张"只是站着"的逆光人像做成了四条引线标注裸名词(具体但像展签)。**差别不在代理水平,在照片里有没有事件可抓。**
| 主导家族 | 主要图形 | 适用的照片线索 |
|---|---|---|
| 星辰光 | `sparkle` `star4` `star5` `halo` 月牙、星座 `dashed` | **有闸**:夜景、暗背景、舞台光等"光本身就是主角"的照片。**"有逆光光斑"不足以选它**——顺光/柔光人像更不行。选它必须满足:暗背景占比大,且每颗星都精确落在照片里真实存在的光点/光斑上(不是撒在人脸周围) |
| 天气自然 | `sun` `rainbow` `raindrop` 云朵、飞鸟、风线 | 天空占比大的户外、雨天、日落 |
| 标注手账 | `arrow` `text` `frame` `tape` `underline` `highlight` 荧光圈 | 有可指认的实物/事件/场景信息(最百搭,男生照片和纪实场景首选)。**但照片自己已经印满字时要放弃它**——海报标题、幻灯正文、字幕、路牌已经占满了"文字"这个通道,再叠标签是噪声上叠噪声(真实判断:一张发布会演讲照最终改走器物呼应,用麦克风声波+激光笔轨迹+笔电数据流讲同一件事,不加一个标签) |
| 几何图形 | `dot` `arc` `dashed` `poly` 三角/方框/菱形/网格 | 都市、建筑、极简、硬朗、室内 |
| 拟物贴纸 | `crown_sketch` `bow` `heart` `music_note` `paw_print` `cat_ears_sticker` `fur` `emo_face` `pixel_sprite` `blob` | **有闸**:人物有明确可呼应的互动或姿态(指着某处→心画在指尖;歪头卖萌→皇冠戴在头发上;把叶子按脸上→猫须从那片叶子长出去)。**"是个笑着的特写"不足以选它**——那是所有人像的共性,不是这张的特点。**"把人变成小猫"这条线索特别好用**:猫耳锚发际线、猫须锚她手上的东西、尾巴锚身体边缘、爪印锚地面纹理,一整套元素全都有实测依据 |
| 涂鸦文字 | 大字标题、`speech_bubble` 拟声词、手绘表情脸 | 动作夸张、有对话感、可吐槽 |
| 线条动效 | 速度线、拖尾轨迹、爆发光线、`dashed` 路径 | 有动作、有方向感、运动场景 |
| 器物呼应 | 照饰照片里的实物现画(麦克风波纹、镜头光圈、齿轮、火箭、马蹄印) | 照片主体握着/穿着/用着某件有辨识度的东西 |
| 植物花草 | `flower` `dotflower` 叶片、藤蔓、发芽 | **有闸**:仅当人物与植物直接互动时才可作主导——手里拿花、坐在花丛草地上、头挨着花枝。只是背景有绿植**不算**,那种情况请另选家族 |
**硬性禁止**(这些是套路本身,不是"尽量避免"):
1. 元素与照片零关联——**每个元素都要能说出它依据照片的什么**(画在它旁边、指向它、延续它的形状、表现它正在发生的动作)。说不出的就删,这是唯一真正的防套路闸。
2. 文案使用这些烂熟短语:golden hour、little sunshine、sweet、lovely、my day、good vibes、hello、cutie、dreamy、soft、best day(照片里本身印着这些字则不算)。
3. 文案是抽象形容词或泛泛的情绪词。**文案必须落在照片的具体事实上**:地点、事件、动作、日期、心里话、对话。
- 好例子:`SUMMIT DAY` / `the way up` / `leaf = whiskers` / `gear: on` / `IoT x GenAI` / `live demo` / `hair went first` / `so windy` / `08.25`
- 坏例子:`golden hour` / `lovely day` / `so sweet` / `dreamy vibes`
4. **只写物件的名字**——具体但无趣,是另一种失败。`干砌石墙` `一块块石板` 这类读起来像建筑教科书或博物馆展签,不像人写在自己照片上的话。要写就**说出关于它的一件事**:`no cement in this wall` / `leaf = whiskers` / `so windy`。
对照上面的好例子会发现:`SUMMIT DAY`(事件)、`leaf = whiskers`(她正在做的事)、`the way up`(方向)——几乎没有一个是裸物件名。
5. **一版只许一句文字,英文 + 手写体。** 见上文 2 节的说明。中文能画(引擎自带两款手写中文字体),但英文短句在这种贴纸风里更不出戏;除非用户明确要中文,默认走英文。
**别把反套路做成反美感**:上面这些是防收敛的下限,不是"必须冷冰冰做成说明书"。禁的是**无来由的通用装饰**,不是禁可爱、禁抒情、禁装饰性。
⚠️ **气质匹配和内容匹配同等重要,冲突时不要默认牺牲气质**。真实教训:一张朦胧柔美的暖调逆光人像,被做成了四条引线加裸名词标注的"博物馆展签"——内容呼应满分,气质完全不搭。**硬禁止清单管的是词汇(不许撒花、不许套话),不是情绪**;一张照片完全可以既柔美又具体。要点:
- 文案"落在具体事实上"≠ 只能写物件名。带情绪、俏皮、口语都很好,只要它锚在这张照片的事实上——`回头看了一眼` `第一次骑马,腿软` `这条巷子走了十年` 都合格且有温度;`golden hour` `so sweet` 不合格,因为换张照片照样能用。
- 装饰性元素本身不禁——2 颗星点在真实光斑上、一颗心画在她真正指着的地方、几朵花配在她真的坐着的花丛里,都是好设计。禁的是**撒得满图都是且哪张照片都能撒**。判据仍是那一句:说得出依据吗?
- 若照片本身就柔美、俏皮、少女感,**不必强行改成硬朗手账风**。走"拟物贴纸"或"星辰光"家族完全可以,只要每个元素落点有具体理由(皇冠戴在头发上、心画在指尖旁),而不是在脸周围围一圈。
- 美感优先级高于凑数:与其为满足"≥3 个呼应"硬塞一个丑元素,不如少一个、把已有的做好,然后在自审里写明你的取舍理由。
`references/recipes.md` 里有五个成熟主题的**构图骨架**和踩坑总结(sparkle 参数翻车、underline 斜率匹配等)——**动笔前必读**,但那五个是骨架不是菜单,其中三个都偏少女向且元素池高度重叠,直接照搬正是收敛的来源。
用户要多版时(默认 3-5 版),每版换一个不同的主导家族。
### 3. 写主题脚本
每版一个函数,import 引擎库:
```python
"""涂鸦自审(第 4 步的注释块填在这里,见下文)"""
import sys; sys.path.insert(0, '<skill目录>/scripts')
from doodle_lib import *
d = Doodle('/path/photo.jpg', seed=11) # 每版换 seed,笔迹抖动不同
# 主导家族=天气自然;每个元素都注明它呼应清单里的哪一项。注意粗细分了 4 档。
d.stroke([(0.72,0.14),(0.79,0.19),(0.76,0.24)], color=WHITE, w=W_BOLD,
wob=0.6, taper='tip', n=800) # 主动线(粗):风线顺她被吹乱的发梢方向
for x0, y0 in ((0.75,0.17), (0.78,0.22)):
d.stroke([(x0,y0),(x0+0.03,y0+0.01)], color=SKY, w=W_HAIR,
wob=0.4, n=80, under=False) # 次级碎线(最细):疏密层次
d.sun(0.86, 0.52, r=0.028, color=CORAL, face_color=CORAL, under=False) # 真实夕阳位置
d.text('so windy', 0.16, 0.10, 60, fname='marker', color=WHITE) # 唯一一句(醒目靠 size,不加 stroke_w)
d.underline(0.13, 0.31, 0.13, color=CORAL, slope=0.004, w=W_FAT) # 荧光横杠(特粗)
d.audit(family='天气自然', elements=[...], portrait=True) # 见第 4 步
d.save('out/dusk.jpg')
d.save_video('out/dusk.mp4') # 默认带二次元手+铅笔叠加层
```
(这段示例本身就符合三条硬闸:零撒花、风线顺真实发丝方向、太阳落在真实夕阳上、只有一句英文手写文案、粗细跨 W_HAIR/W_BOLD/W_FAT 三档以上。**别照抄成模板**——你的照片有别的名词。)
过程视频默认显示一只握素描铅笔的**二次元少女手**(白皙纤细、粉指甲、日系上色):笔尖锚定当前绘制点,笔画间抬笔飞移(微放大模拟离纸),写字时沿擦入边缘移动,开头从画面右下飞入、结尾飞出。不想要手就 `save_video(path, hand=False)`。
`hand_sprite` 可选:`'anime'`(默认,二次元女生手+黄杆铅笔)、`'pencil'`(欧美卡通手+铅笔)、`'marker'`(粉色马克笔插画手)、`'drawn'`(程序画的卡通拳头,笔杆颜色逐笔跟随涂鸦颜色)、或自备 `(png路径, 笔尖x, 笔尖y)` 元组。`hand_scale` 控制手的大小(默认 0.20 = 手的伸展半径约为短边的 20%,嫌大改小、要醒目改 0.30)。
坐标归一化 (0..1)。**ops 顺序 = 视频绘制顺序**,按"主体装饰 → 环境点缀 → 文字收尾"排。
**引擎 API 速览**(细节读 `scripts/doodle_lib.py` 的 docstring 和方法签名):
- 基元:`stroke`(brush='marker'/'water'/'crayon'/'glitter'/'highlight'/**'fur'**,color2= 渐变,taper='tip'/'both')、`arc`、`dashed`、`dot`、`poly`(`wob=` 抖动边缘)、`text`(`halo=` 深色柔光垫底,解决看不清;`stroke_w` 已废弃、夹在 1.0,别用;中文自动切手写体)
- 图案库:`sparkle` `star5` `star4` `heart` `crown` `crown_sketch` `halo` `speech_bubble` `arrow` `rainbow` `sun` `music_note` `paw_print` `cat_ears` `cat_ears_sticker` `butterfly` `tape` `frame` `underline` `raindrop` `flower` `dotflower` `bow` `fur` `blob` `emo_face` `fish` `pixel_sprite`
- **贴纸风的五件新工具**(对标小红书/抖音那种手绘贴纸滤镜):
- `fur(pts, w=70, spread=, density=)` 毛绒笔画——猫尾巴、绒球、毛领子。`w` 要给到 40-90(细的毛笔画看不出毛)
- `blob(x, y, rx, ry, alpha=170)` 软发光团——铺在颜文字/文字底下当白雾,画在最底的 wash 层
- `emo_face(x, y, eyes='^^', mouth='w', arms='yo')` **手画**颜文字。**不要用字体写颜文字**:系统里能显示 ω ᐢ ˃ ▽ 这些字符的只有印刷黑体(实测只有 Arial Unicode / Hiragino 角ゴ 覆盖),用它会和中文黑体一样出戏;而且颜文字若算文字元素就会占掉那唯一一句的配额。手画的不算文字,还能任意组合
- `fish(x, y, s=, flip=)` 小鱼;`pixel_sprite(rows, x, y, cell, legend)` 像素贴纸(字符网格,一行里连续同色合成一个矩形,所以视频里是一行行刷出来)
- `cat_ears_sticker(lx, ly, rx, ry, w_=, h_=)` 实心三角猫耳(`cat_ears` 是描边款)
- 色板:WHITE PINK HOTPINK CORAL PEACH YELLOW LEMON MINT SKY BLUE LAVENDER RED INK;`al(c,alpha)` `dk(c,f)` 调色
- 字体 fname:'marker' 'chalk' 'hand' 'note' 'script' 'savoye' 'comic';中文手写体 'cjk-kuai'(圆润马克笔感)/ 'cjk-xing'(钢笔行书)/ 'cjk-hei'(印刷黑体,一般别用)
**单位速查**(不看这个必踩坑):
- 坐标 x/y:归一化 0..1
GitHubで見るこの SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る