marioslideshow - Subject Framer
Stop the Ken Burns pan from cutting heads off
- photos
- images
- masks
- focus
- framing_preview
- focus_json
Animated slideshows have a nasty habit: the camera pushes in, pans across, and crops the frame - and if it's cropping around the image center, it decapitates people. The "marioslideshow - Subject Framer" exists to stop that. For every photo in your collection it figures out where the subject actually is and hands the renderer a focus point plus a protected region, so the camera moves keep the subject in frame instead of through it.
Read the description on the tin again: "Compute framing guidance... Connect the same source photos to this node and the renderer." This node plans crops. It doesn't generate, upscale, or touch pixels - it outputs a plan (MARIO_FOCUS) that the Renderer consumes. It slots between Load Images and the Renderer, and it's worth having in every slideshow with people in it.
How it works
Three ways to say "here's the subject," chosen by mode:
- Faces - runs a classical face detector on each photo. The nice part: it's the LBP frontal-face cascade that ships inside
scikit-image(data.lbp_frontal_face_cascade_filename()), so there's no model download and it runs on CPU in milliseconds. The honest part: it detects frontal faces, not profiles, not dogs, not products. When nothing is found you get a center fallback, and the JSON will tell you it happened (each item records amethodlikefaces,mask,manual,overrideorcenter fallback). - Manual - you supply normalized
focus_x/focus_y(0 to 1) as the point of interest for every image. - masks (optional
MASKsocket) - one mask per source image, in matching order, where white (>0.5) means subject. The node takes the mask's bounding box as the protected region, and masks override face detection entirely.
subject_margin (default 0.2) expands the detected face or mask bounds to give the subject breathing room inside the crop. And when the detector or your masks get one wrong, overrides_json fixes individual images without re-running everything - zero-based per-image overrides like {"0": {"x": 0.8, "y": 0.3}}, or a full box {"box": [left, top, right, bottom]} in normalized coordinates. It's multiline and designed to be edited in the widget.
Outputs
- focus (
MARIO_FOCUS) - the payload; wire it into the Renderer'sfocussocket. - framing_preview (
IMAGE) - a contact sheet with a green box around each protected region and a red cross at the focus point. Shows up to 12 images, but all of them get analyzed. This is your sanity check before committing to a long render. - focus_json (
STRING) - the same plan as printable JSON, handy for eyeballing themethodper image.
Installing it
Same pack install as the others:
cd ComfyUI/custom_nodes
git clone https://github.com/mariobilly/msch-slideshow.git
cd msch-slideshow
python -m pip install -r requirements.txt
python -m pip install -r requirements-advanced.txt
That second line matters: Faces mode lazily imports scikit-image when it runs, and skimage lives in requirements-advanced.txt, not the base file. If you skip it, you'll get an import error the first time you hit Faces. Base requirements (numpy, Pillow, imageio-ffmpeg, torch, av) come from the first file. Windows portable users substitute .\python_embeded\python.exe. And remember the README banner: this standalone repo is superseded by the unified MSCH Nodes pack - one install or the other, not both, or nodes register twice.
Where people get burned
Connect exactly one of photos or images - the node errors out if you feed both or neither. Face mode plus masks is fine (masks win), but the masks socket needs one mask per source image as [B, H, W], and each image in your slideshow can only be framed by so much. If a mask is inverted you'll frame the background - flip it so white is the subject.
The ordering rule is the real trap, and it's worth repeating because every MSCH node obeys it: framing items are indexed to the photo order you loaded. Wire the same Load Images output, in the same order, to both the Subject Framer and the Renderer. Change the photo collection between the two runs and your focus boxes drift onto the wrong pictures.
Finally, set expectations: Faces mode finds faces, not subjects in general. The pack's own guide is blunt - for products, side-profile portraits, or anything the detector misses, use masks or Manual mode. And "Smart fit" can still fall back to a contained crop when the protected region doesn't fit the scene's aspect ratio; this is framing guidance, not foreground segmentation, so it can't save a subject from a transition that sweeps across it.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| mode | COMBO | 2 options: Faces, Manual | |
| subject_margin | FLOAT | 0.200–1 | — |
| focus_x | FLOAT | 0.500–1 | — |
| focus_y | FLOAT | 0.500–1 | — |
| overrides_json | STRING | Optional zero-based image overrides, e.g. {"0": {"x": 0.8, "y": 0.3}}. Coordinates are normalized. | |
| photosopt | MARIO_IMAGES | — | |
| imagesopt | IMAGE | — | |
| masksopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| focus | MARIO_FOCUS | — |
| framing_preview | IMAGE | — |
| focus_json | STRING | — |