Split an image into layers
SkillMediaSplit one image into editable layers (PSD + PNG). 把一张图拆成图层(PSD + PNG)。
Use Split an image into layers in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Split an image into layers and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the Split an image into layers skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; Ahel provides instructions and does not run this skill.
No other account needed.
Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
What this skill tells your AI
The instructions your AI receives, as published by lemomo-ai/lemo-wake in skills/layers/SKILL.md and read by Ahel’s review.
You take one picture apart the way a designer would want to receive it: every element that someone might move, recolour or animate on its own layer, the background behind them clean, everything aligned to the original pixel grid. Then you pack it as a PSD, PNG layers and a layers.json.
Talk to the user in their language (Chinese or English; follow the user). These docs are in English only for you.
No image generation and no API keys: the parts come from the source pixels through small local models (cut-out, element picking, hole filling, depth).
Paths
Only the text substituted into this file counts. Never take the shell variables CLAUDE_SKILL_DIR or CLAUDE_PLUGIN_DATA (echo, env) for these paths: the Bash environment can carry values that belong to another plugin.
$L= this skill's folder:${CLAUDE_SKILL_DIR}. If that still reads literally as a${...}placeholder, it is the folder that contains this SKILL.md.$W= the wake skill's scripts, next to this skill:$L/../wake/scripts. The model tools live there (segment.py,inpaint.py,depth.py,models.py,measure.py). If that folder is missing, this skill was installed on its own; tell the user to install the lemo-wake plugin (claude plugin install lemo-wake@lemo-wake).- Models folder:
${CLAUDE_PLUGIN_DATA}. If that shows a real path that belongs to lemo-wake, prefix every model command withLEMO_WAKE_MODELS="<that path>/models"(shell variables do not survive between your commands, so write the prefix each time). If it still starts with${, set nothing; the scripts find their folder themselves ($W/models.py where). - Output goes into the current working directory, never into the folder of the user's image.
Local models and consent
The tools use up to five small ONNX models on the CPU: BiRefNet-lite (subject, 224 MB), MODNet (people, 26 MB), MobileSAM (pick elements, 44 MB), LaMa (fill the background, 208 MB), Depth Anything V2 Small (depth, 99 MB). A model already on disk just runs. If $W/models.py (no arguments) shows some missing and consent "not asked yet", ask once before you start, in one short message: what they are for, about 600 MB in all from Hugging Face, where they are stored. Only a clear yes counts; record it with $W/models.py consent yes|no. A script that stops with exit code 10 means the same question. If the user declines, you can still pack layers from masks you draw yourself (measure.py bbox, colour keys, polygons) and fill small holes with inpaint.py --engine opencv; say what that costs.
1. Find the input
- A lemo-wake project (
<slug>-alive/, or itssrc/): the parts are usually already there. List them:
It shows every image in$L/scripts/layers.py scan <project>src/assets/and what it looks like:source,cut-out(RGBA at the source's size),mask,depth,plate?, orother size(an already cropped part;buildfinds its place in the source by itself). For plates it also says how much of the picture each one changed (differs_from_source: the one with the most lifted out is usually the cleanest full background). Parts made for an animation may have been trimmed or repainted (a missing edge, a redrawn top);buildchecks the stacked layers against the source and marks the mismatch in red, so recut what does not match. Lift whatever is missing as in step 2. - An image: make a folder
<slug>-layers/in the current working directory and normalise the image there (HEIC, EXIF rotation):
It writes$L/scripts/layers.py prep <image> <slug>-layers/work<slug>-layers/work/assets/source.png; below,<a>stands for thatwork/assetsfolder. Keep every mask and cut-out in<a>too. All coordinates are pixels of<a>/source.png.
If the user said what to separate ("just the two people", "the product and the logo"), that is the brief. Otherwise decide yourself and do not ask.
2. Take the picture apart
Look at the image first: what is in it, what covers what, what a designer would want to move. Usually that means:
- each person whole, one layer per person. A person includes what they wear and hold, and their own hands even where they rest on someone else. Never cut off a head, an arm or a leg as its own layer: the cut and the hole at the joint look like a broken doll, and nobody can use a loose arm.
- One person:
--model portrait(keeps hair) merged with--model generalrun inside a box around that person (keeps the body and what they hold). General and portrait both grab nearby things (a picnic blanket, a basket), so subtract the masks of objects that will be their own layers. - People who touch or overlap: one SAM box each often comes out with missing pieces. More reliable: make one mask of all the people together (portrait + general as above, objects subtracted), put a SAM point or box on each person as a seed, and give every pixel of the joint mask to the person whose seed mask it belongs to or lies nearest. Loose fragments go to the person they touch.
- One person:
- each object that stands on its own: SAM, one box each (a box is steadier than a point; add
--negpoints to drop a neighbour; one click often gets only part of a thing, so add a point on the missing part). A container keeps its contents (the basket with its fruit, the vase with its flowers;generaltends to drop thin stems, so add SAM points on them) unless the user wants the contents separately (food lifted off its plate). - many small things of one kind (scattered berries, confetti, stars): one layer for the group, unless the user asked for each piece or each one clearly matters on its own.
- openwork shapes (a lattice tower, a fence, branches, lace): the mask also fills the gaps. Clear the gaps where the pixels match the background around them (compare with the filled background or key out the background colour inside the shape's box); where the gaps cannot be told apart, say so.
- text blocks and logos on posters and cards, as pixel layers (box select); they stay pixels, not editable text.
- the background behind all of them, filled in, so every element can be moved off it.
- a depth map, for the pack and for the user's own parallax work.
Do not split what belongs together (a cup and its saucer, a bouquet and the hands holding it), and do not cut tiny details nobody would move.
LEMO_WAKE_MODELS=... $W/depth.py <a>/source.png --out <a>/depth.png
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/person1.png --model portrait
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/person1_g.png --model general --box x0,y0,x1,y1
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/cup.png --box x0,y0,x1,y1 # sam
LEMO_WAKE_MODELS=... $W/inpaint.py <a>/source.png <a>/all.png --out <a>/plate.png --dilate 6 # all = union of every element mask
$W/measure.py grid <a>/source.png <a>/grid.png # coordinates, if you need them
$W/sheet.py <a>/../parts.png --parts <a>/.. # every mask over the image, cut-outs on a checkerboard
Masks are 8-bit grey at the source's size (white = the element); build takes masks or RGBA cut-outs directly. Combine and clean masks with NumPy / OpenCV through uv (maximum of two masks, remove one from another, feather or shrink 1-2 px where a halo of the old background shows); do not fetch other models. Look at the parts sheet before packing.
The background: inpaint the union of all element masks.
inpaint.pygrows the mask by about 1% of the diagonal by default. For clean edges (posters, illustrations, cut-outs that already include their soft edge) pass a small--dilate(4-8); keep the default for photos with hair and motion blur.--splitfills separate regions one by one at near-native resolution. When the elements join into one big region it cannot split them, and the fill is downscaled (stderr says "downscale"); a soft result is acceptable. Large calm areas (sky, a wall, paper, a flat colour) can be filled in code with their own colour or gradient instead.- Never fill part of a hole while the rest of the object is still in the picture: LaMa copies what it sees and paints the object back. Every pass masks the whole object (all of it, also the parts you fill later); to work at higher resolution, crop around a region so the whole hole inside the crop is masked.
- Even when the elements cover most of the frame, still make the background, but tell the user plainly that it is soft there because those pixels never existed. That is the honest limit without image generation.
Where one element covers another (a cat in front of a sofa), the lower layer has a gap where the upper one was. Leave it, or fill small gaps with inpaint.py on that layer's own cut-out. A simple flat shape may be completed in code from what is visible (a sun disc, a colour band, a circle badge: fit the shape, fill it with its own colour or texture). Never invent complex hidden content (a face, a hand, a building's hidden side).
3. Pack the layers
$L/scripts/layers.py build <slug>-layers --source <a>/source.png --plate <a>/plate.png --depth <a>/depth.png \
--names "背景,原图,景深" --layer "背景人物=<a>/crowd.png" --layer "女孩=<a>/girl.png" --layer "帽子=<project>/src/assets/cap.png"
- Name each layer in the user's language, plainly ("女孩", "左边的杯子", "标题"), and pass
--namesfor the background, source and depth layers in that language too. - Order: list the layers from the bottom up (first = lowest). Decide it by what covers what in the picture.
--order depthsorts by mean depth instead, a quick guess for separate objects spread through a scene, wrong for things that sit on each other. - A cropped part from a project is found in the source automatically; if it was repainted or scaled, the script says so, then give its place as
name=file@x,y.
It writes layers.psd (background, then one layer per element, the source and the depth map as hidden layers on top), png/ (the background at full size, each element cropped to its own box, source.png, depth.png), layers.json (canvas size; per layer: file, x, y, width, height, z with 0 = bottom, mean depth) and preview.png.
Look at preview.png before you hand it over. A red "≠ source" card (and a check: warning) means the stacked layers do not reproduce the source there: a part is incomplete, misplaced or was repainted. Also look for ragged edges, missing hair, a halo, a part that grabbed its neighbour, a layer that should be two or two that should be one, the stacking order. Fix and build again. Then delete <slug>-layers/work/ unless the user wants the masks.
4. Hand it over
Tell the user briefly, in their language: where the folder is, which layers it has (names, in order), and how to use it:
layers.psdopens in Photoshop, Affinity Photo, Procreate, GIMP, or free in the browser at Photopea. The source and depth layers are hidden; switch them on to compare.png/withlayers.jsonfor After Effects, Figma, Keynote or a game engine: place each PNG at itsx, y, stack byz.- What the limits were: soft fill where a big element left the background, gaps where layers covered each other, text kept as pixels.
- They can turn the same picture into a film with
/lemo-wake:wake.
Signals
- GitHub stars
- 34
- Forks
- 4
- Last commit
- Oct 2026
Advanced
- Item type
- skill
- Key
layers- Source
- github.com/lemomo-ai/lemo-wake
github.com/lemomo-ai/lemo-wake