Nodes/CMK Flow/CMK Face Crop
ComfyUI Node

CMK Face Crop

Crop the face you actually selected, not the one the detector liked

By CMKFlow·Created 3 months ago·Updated 2 days ago· 6
CMK Face Crop
  • image
  • selected_face
  • face_image
  • diagnostic
◄padding0.25►
◄square_croptrue►

Face crops are the one place in ComfyUI where a node producing slightly the wrong rectangle is worse than an error. This one takes a face the pack has already chosen and hands back a clean crop, plus a preview that draws the box and landmarks so you can see whether the choice was right.

What it is

CMKFaceCrop in CMK/Toolbox/Face. Inputs are your image and a selected_face - the pack's CMK_SELECTED_FACE type, which is what the face selection nodes in CMK produce - plus two controls: padding (default 0.25, range 0–2) and square_crop (default on). Outputs are face_image and a diagnostic.

That selected_face input is the whole reason this node exists rather than you just using ImageCrop. CMK lets you pick which face - largest, leftmost, a specific one from a set - and hands you a small payload describing it. This node turns that payload into pixels, so what you crop and what you selected can't drift apart.

How it works

It reads the bounding box out of the payload and computes a crop centred on that box. With square_crop on, the side is max(width, height) × (1 + 2 × padding), for both dimensions - one square, which is what nearly every downstream consumer of a face crop actually wants (restore networks and face-swap models expect square or near-square input, and squashing a face into a 1:1 box gives them something to interpret). With it off, width and height are expanded independently by the padding factor, which keeps your original aspect ratio.

Then it floors and ceils the rectangle, clamps it to the image bounds so a face at the frame edge doesn't throw, and returns the crop as a single-frame image. The padding is expressed as a fraction of the face box, so 0.25 adds a quarter of the face's size on every side - enough to include chin and ears with a bit of hair. Push it past 1.0 and you're cropping half the frame, which is occasionally what you want for a full portrait pass and usually not.

The diagnostic output is worth wiring up. It carries two preview stages: the source image with the face box and landmarks drawn on it, and the resulting crop, along with the selection method, the padding, the square flag and the final crop dimensions in the metadata. When a face pass looks wrong, this is how you find out in five seconds that the detector picked the person in the background.

Batch note: it uses the payload's image_index to pick the frame, and it raises a clear RuntimeError if that index is outside the batch - "image_index 3 out of range. Image batch size: 2" - which is a much better failure than a silent wrong frame.

Where it fits

Three jobs, all of them ordinary:

  • Feed a cropped face straight into a restore or detailer pass when you don't want the whole-frame route.
  • Build yourself a face dataset for LoRA training: detect, crop, adjust padding until the box sits the way you want, then save. Doing this by hand in an image editor for 40 images is a special kind of misery.
  • Check detection quality. The box-and-landmarks preview is a debugging tool you'll end up leaving on.

Install

Comes with the pack. Manager: search CMK Flow, install the CMKFlow entry, restart. Manually, from the folder containing main.py:

git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py

You want CMK dependency check: OK. The pack is a single-author GPL-3.0 project by Carsten Kirschner, open-sourced in July 2026, and it installs as one unit - ultralytics, onnxruntime, insightface, segment-anything, imageio-ffmpeg, opencv-python, nudenet==3.4.2 - so the crop node itself needs nothing but its neighbours do. Detection models go under models/ultralytics/bbox; the resource check knows which filenames the shipped workflows expect:

python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/shared/models"

Issues worth knowing

If you feed it a selected_face from nowhere - an empty payload - it raises rather than guessing a box. That's correct; it means the selection node upstream didn't find a face.

The other one is the aspect-ratio question, and it's not a bug so much as a choice you have to make consciously: with square_crop off, a padding of 0.25 on a wide face yields a very wide crop that will be squashed by anything downstream expecting squares. Turn it on unless you have a specific reason.

CategoryCMK/Toolbox/Face

Inputs (4)

NameTypeDefaultDescription
imageIMAGE—
selected_faceCMK_SELECTED_FACE—
paddingFLOAT0.250–2—
square_cropBOOLEANtrue—

Outputs (2)

NameTypeDescription
face_imageIMAGE—
diagnosticCMK_DIAGNOSTIC—