cursor-rig
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCursor rig
光标绑定
A character who looks at you is the strongest hero a page can have. Building one in 3D means modelling, rigging and matching a painting's style, and the result never quite looks like the painting. This skill keeps the painting. It renders the head in every direction once, as a grid of poses, and at runtime shows the pose that faces the cursor. With 19 yaw steps and 8 pitch rows, the turn reads as continuous.
一个会看着你的角色,是页面上最亮眼的主角。在 3D 中构建这样的角色,需要建模、绑定并匹配画作风格,但最终效果始终无法真正还原原画。本 skill 保留画作风格:预先将各个方向的头部渲染为姿态网格,运行时再展示朝向光标的姿态。通过 19 个 yaw(偏航)步进和 8 个 pitch(俯仰)行,转头看起来连续自然。
Tools
工具
| File | What it does |
|---|---|
| Turns head-turn clips into |
| Loads the rig, places a canvas over the head, follows the pointer with a spring, blinks, glances about when idle |
Needs Python 3.9+, , ffmpeg, an image-editing model and an image-to-video model that accepts start and end frames (see ).
pip install numpy opencv-python-headlessmotion-assets| 文件 | 作用 |
|---|---|
| 将转头片段转换为 |
| 加载绑定数据,在头部上方放置 canvas,以弹簧效果跟随指针,支持眨眼,并在空闲时四处张望 |
需要 Python 3.9+、、ffmpeg,以及一个图像编辑模型和一个接受起始帧与结束帧的图生视频模型(参见 )。
pip install numpy opencv-python-headlessmotion-assetsPipeline
流程
1. The plate
1. 基准图
The plate is the character facing forward: the one image every pose is built on. Upscale the source illustration to at least 1440 px tall. If the hero needs to be wider than the character, outpaint the sides for the page, but build the rig on the square or portrait crop around the character. Outpainting models re-render the whole image, so paste the original pixels back over the middle afterwards.
基准图(plate)是角色正面朝向的图像,也是所有姿态的构建基础。将源插图放大到至少 1440 px 高。如果页面中的主视觉需要比角色更宽,可以对两侧进行 outpaint(外扩),但应在角色周围的方形或纵向裁切区域上构建 rig。Outpainting 模型会重新渲染整张图,因此完成后需要将原始像素重新覆盖回中央区域。
2. Keyframes
2. 关键帧
With an image-editing model, make the head turned to each extreme from the plate: left, right, up, down, and the four diagonals. The prompt must pin everything except the head:
Same character, same painting, same framing and crop. Only the head turns to look toward the left edge of the image, about 40 degrees. Hair, face, skin, shirt, hands, body pose, background and brush style stay exactly the same. No new objects.
Flick between the plate and each keyframe at full size. Only the head may change. Models that hold framing almost pixel-exact are worth paying for here; a keyframe with a shifted shoulder costs a whole row.
使用图像编辑模型,基于基准图生成头部转向各个极限方向的图像:左、右、上、下以及四个对角方向。提示词必须固定除头部以外的所有内容:
同一角色、同一画作、相同构图和裁切。只有头部转动,望向图像左边缘,约 40 度。头发、面部、皮肤、衬衫、双手、身体姿势、背景和笔触风格必须完全一致。不要添加任何新物体。
以原始尺寸在基准图与每个关键帧之间切换查看。只有头部可以改变。能够将构图保持到近乎像素级一致的模型值得付费使用;一个肩膀发生偏移的关键帧就会毁掉整整一行。
3. Head-turn clips
3. 转头片段
Image-to-video, start frame = the plate, end frame = a keyframe, 5 seconds, camera locked off:
Locked-off camera. The character slowly turns only his head and neck from facing forward to [the end pose]. The body, shirt, arms and background stay perfectly still. Smooth, even motion, no blinking, no talking.
Name the clips by row and side: and for the level row (required), / (up), / (half down), / (down). Eight clips make a full rig. Two make a rig that only turns left and right.
L.mp4R.mp4ULURHLHRDLDRIf two rows differ a lot (the model redrew the hair in the down keyframes, say), do not rely on morphing between them: generate a real middle row instead.
图生视频:起始帧 = 基准图,结束帧 = 关键帧,时长 5 秒,固定镜头:
固定镜头。角色从正面开始,仅缓慢转动头部和颈部,直至到达[结束姿态]。身体、衬衫、手臂和背景保持完全静止。动作平滑均匀,不眨眼,不说话。
按行和方向命名片段:水平行使用 和 (必需),/(向上),/(半向下),/(向下)。8 个片段构成完整 rig;2 个则构成仅能左右转头的 rig。
L.mp4R.mp4ULURHLHRDLDR如果两行差异很大(例如模型在向下关键帧中重绘了头发),不要依赖行间的 morphing,而应生成一行真正的中间姿态。
4. Build
4. 构建
bash
python3 scripts/build_rig.py clips/ site/rig --box 300,40,840,800 --track dots --debug work/rig-cells- (plate pixels): everything the head ever covers, hair included, with a little neck.
--box x,y,w,h - for cartoon dot eyes: finds the two dark round eyes in every frame, and records their positions so blinks can be painted live.
--track dotsand--eye-band y0,y1tune it.--dark - for any other face: follows a patch around a point you give (the bridge of the nose works) from frame to frame. No blinks are painted with this mode.
--track template --point x,y - sets the head mask polygon if the default oval cuts the hair or includes the collar.
--poly
What the script does, and why:
- Aligns every clip on the body (ECC, rows below ). Video models drift the whole frame a few pixels; without alignment the shirt jitters as the head turns. It prints the drift per clip; above 6 px, the clip was not locked off.
--body-y - Picks columns by measured head position, not by time. Models ease in and out, so evenly spaced timestamps give uneven steps. Even steps of the measure give an even turn.
- Blends each head onto the one plate body through a feathered mask, after matching brightness to the plate, so only the head ever changes.
- Fills missing pitch rows with optical-flow in-betweens of the neighbouring rows.
Open the cells as a contact sheet and look down every column and across every row: no jumps in head size, no hair popping, no collar seams.
--debugbash
python3 scripts/build_rig.py clips/ site/rig --box 300,40,840,800 --track dots --debug work/rig-cells- (基准图像素坐标):头部可能覆盖的全部区域,包括头发,并稍微包含一点颈部。
--box x,y,w,h - 用于卡通圆点眼睛:在每一帧中找出两个深色圆眼睛并记录位置,从而可以实时绘制眨眼。
--track dots和--eye-band y0,y1用于调整。--dark - 适用于其他面部风格:逐帧跟踪指定点周围的小区域,例如鼻梁。此模式不会绘制眨眼。
--track template --point x,y - 如果默认的椭圆形蒙版切断头发或包含衣领,可使用 设置头部蒙版多边形。
--poly
脚本的工作原理及原因如下:
- 使用 ECC 将每个片段与身体对齐(对齐 以下的行)。视频模型会让整个画面漂移几个像素;如果不对齐,转头时衬衫会抖动。脚本会打印每个片段的漂移量;超过 6 px,说明片段的镜头并未完全固定。
--body-y - 依据实测头部位置而非时间选取列。 模型会产生缓入缓出的运动,因此等间隔时间戳会带来不均匀的步进;让测量值保持等步进,即可获得均匀的转头效果。
- 将每个头部混合到同一基准图的身体上。 先将亮度与基准图匹配,再通过羽化蒙版进行混合,确保始终只有头部发生变化。
- 使用相邻行的 optical flow 中间帧填补缺失的 pitch 行。
将 生成的单元图作为 contact sheet(联系表)打开,逐列纵向、逐行横向检查:头部大小不能跳变,头发不能闪现,衣领处不能有接缝。
--debug5. Page
5. 页面
html
<figure class="hero-rig" style="position: relative; margin: 0">
<img src="rig/plate.webp" alt="A painted shopkeeper in a loud shirt, looking at you">
<canvas></canvas>
</figure>
<script type="module">
import { loadRig, HeadRig, animate } from "./rig.js";
const head = new HeadRig(document.querySelector(".hero-rig"), await loadRig("rig/"));
animate([head]);
</script>If the page shows a wider artwork than the plate, pass where the plate sits in it, in artwork pixels: .
new HeadRig(el, data, { art: { w: 3898, h: 1440, plateX: 1229, plateY: 0 } })The player:
- loads the level row first (the head can turn left and right at once), then the rows above and below;
- aims with of the pointer's offset from the eyes, so far corners do not snap the head to its limit;
tanh - moves through a slightly under-damped spring (a small settle at the end of each turn reads as alive);
- cuts between neighbouring poses instead of cross-fading (a cross-fade shows two pairs of eyes);
- paints blinks, double blinks and winks over the eyes using the eye positions and skin tones in (dot tracking only);
rig.json - glances about by itself when the pointer has been still for 3.5 s, and on touch devices;
- pauses when off screen.
html
<figure class="hero-rig" style="position: relative; margin: 0">
<img src="rig/plate.webp" alt="A painted shopkeeper in a loud shirt, looking at you">
<canvas></canvas>
</figure>
<script type="module">
import { loadRig, HeadRig, animate } from "./rig.js";
const head = new HeadRig(document.querySelector(".hero-rig"), await loadRig("rig/"));
animate([head]);
</script>如果页面显示的画作比基准图更宽,请传入基准图在画作中的位置,单位为画作像素:。
new HeadRig(el, data, { art: { w: 3898, h: 1440, plateX: 1229, plateY: 0 } })播放器具备以下行为:
- 首先加载水平行(头部可以立即左右转动),然后加载上方和下方各行;
- 使用指针相对眼睛的偏移量经过 计算瞄准角度,避免头部在远离角落时突然达到极限;
tanh - 通过略微欠阻尼的弹簧移动(每次转头结束时轻微回弹会显得有生气);
- 在相邻姿态间直接切换而非交叉淡化(交叉淡化会同时显示两双眼睛);
- 使用 中的眼睛位置和肤色,在眼睛上绘制眨眼、double blink(双次眨眼)和 wink(单眼眨眼),仅支持圆点跟踪;
rig.json - 当指针静止 3.5 秒后,以及在触摸设备上,会自行四处张望;
- 离开屏幕可见区域时暂停。
Budget
成本
Eight clips is the full cost; at typical image-to-video prices that is a few dollars. The finished rig (152 poses at 0.6 scale) is about 2 MB of WebP.
完整配置的成本是 8 个片段;按常见的图生视频价格计算只需几美元。完成后的 rig(0.6 倍缩放,共 152 个姿态)约为 2 MB,格式为 WebP。
Accessibility
无障碍
- The plate carries the alt text; the canvas is decoration.
<img> - With , the head still answers the pointer (the visitor is causing it) but critically damped, with no idle glancing and no blinks.
prefers-reduced-motion - Nothing depends on the rig: it is a portrait that happens to look at you.
- 基准图的 承载替代文本;canvas 仅作装饰。
<img> - 启用 时,头部仍会响应指针(因为这是访客主动操作),但采用临界阻尼,且不进行空闲张望和眨眼。
prefers-reduced-motion - 没有任何内容依赖 rig 才能显示;它本质上是一幅恰好会看着你的肖像。