Nodes/OmniNodes/Face Detect & Crop πŸ™‚
ComfyUI Node

Face Detect & Crop πŸ™‚

Find the face, crop the square, ship the batch

By TensorVizionΒ·Created 3 months agoΒ·Updated about 8 hours agoΒ· 0
Face Detect & Crop πŸ™‚
  • image
  • cropped_images
  • detected_mask
  • summary
β—„output_size512β–Ί
β—„margin0.35β–Ί
β—„selectβ–Ύβ–Ί
β—„on_no_faceβ–Ύβ–Ί
β—„min_neighbors5β–Ί
β—„scale_factor1.10β–Ί

Character LoRA datasets live or die on their crops. Train on full-body shots with the face tiny in the frame and the model learns a blurry blob where a face should be; train on clean face crops and it actually learns the likeness. Face Detect & Crop automates the boring, correct prep: it detects faces in a batch, crops each one to a square with a configurable margin, and resizes to a fixed output size. It's the node you run before training a character, not after.

The detection is OpenCV's built-in frontal-face Haar cascade - CPU-only, zero model downloads, no torch vision stack. For each frame in the batch it finds faces and crops around the chosen one (select: largest, the highest-area face - right for single-subject portraits - or first, whatever the cascade returned first). margin (default 0.35) expands the box around the face so you keep a little forehead/hair/neck context instead of a razor-tight crop. Everything comes out as output_size Γ— output_size (default 512).

The three outputs cover real needs: cropped_images (the batch, same length as input), detected_mask (a mask batch that's 1.0 where a face was found, 0.0 where the fallback fired - wire it into a filtering step if you want to drop the misses), and summary with the detection count.

What happens when no face is found is your call, via on_no_face:

  • center_crop - take a square from the middle anyway.
  • skip - a blank frame in that slot (keep the batch aligned, mark it in the mask).
  • pass_through - the original image resized, uncropped.

min_neighbors (5) and scale_factor (1.1) are the raw cascade parameters; bump min_neighbors to suppress false positives on noisy images, leave them alone otherwise.

Two things you need to know before building a pipeline on this. First, the OpenCV dependency isn't in the pack's requirements.txt - this is the one Image node that can't run on Pillow/NumPy/PyTorch alone. The node imports cv2 lazily and, if it's missing, returns blank outputs plus a clear message: pip install opencv-python. ComfyUI won't install it for you. Second, Haar cascades are frontal-face detectors. A profile shot, a heavily turned head, or a face at a weird angle won't be found - that's expected, not a bug, and it's exactly why the on_no_face fallbacks and the detection mask exist. If your dataset is mostly angled or profile shots, you'd want a real face-detection model (MediaPipe, YOLO-face, etc.) instead.

Honest positioning: this is a dataset-prep utility, not a flashy node, and it's from the same lineage as the crop/pad helpers in the wider ecosystem - but it does its narrow job (face β†’ square crop, consistently, on CPU) without pulling in a heavier detection stack. It pairs cleanly with the pack's Aspect Ratio Bucket for the full "crop the face, then snap to a training bucket" prep flow.

Install

Part of OmniNodes:

cd ComfyUI/custom_nodes
git clone https://github.com/TensorVizion/OmniNodes
pip install opencv-python   # required by this node specifically

Restart ComfyUI (or ComfyUI Manager β†’ "OmniNodes"). Note the extra pip step - it's the one Image node here that needs it.

Troubleshooting

  • Blank outputs + "opencv-python not installed" - install it (above). The node degrades gracefully, but it can't detect anything without cv2.
  • Faces missed on angled/partial shots - frontal Haar cascade limitation. Use on_no_face fallbacks, or a better detector for your dataset.
  • Crops too tight / too much background - adjust margin. 0.35 default is a good starting point; lower for tighter.
CategoryTensorVizion/Image

Inputs (7)

NameTypeDefaultDescription
imageIMAGEβ€”
output_sizeINT51264–2048β€”
marginFLOAT0.350–2β€”
selectCOMBO2 options: largest, first
on_no_faceCOMBO3 options: center_crop, skip, pass_through
min_neighborsINT51–20β€”
scale_factorFLOAT1.101.01–1.5β€”

Outputs (3)

NameTypeDescription
cropped_imagesIMAGEβ€”
detected_maskMASKβ€”
summarySTRINGβ€”