RekogniFlow ⭐ Face Quality (batch)
Pick the sharpest, best-lit, front-facing render — no reference face needed
- image_batch
- best_image
- best_score
- best_attempt
- threshold_met
- detail_json
Unlike the other two nodes in this pack, RekogniFlow_FaceQualityBatch doesn't care who the face is. Give it a batch of renders and it scores each one on technical face quality - sharpness, brightness, and how front-facing the face is - then hands you the best of the bunch. No reference image, no likeness question. It's the "which of these is the cleanest portrait" node.
That distinction matters more than it sounds. Face compare answers "does this look like them?" This node answers "is this a usable photo of a face?" If you're batch-generating a face at high resolution and then upscaling or feeding it to a detailer, you want the source to be sharp, well-exposed, and looking at the camera - and this is the only node in the pack that automates picking that winner.
How it works
Each image goes to AWS Rekognition's DetectFaces (with Attributes=["ALL"], which is where it pulls the good stuff). It grabs three raw measurements off the most confident detected face:
- Sharpness and Brightness - quality scores straight from Rekognition.
- Pose - from the yaw/pitch/roll angles. Dead front-on scores 100; each degree off-axis costs points until 45° on any axis means zero.
Those three get folded into a single 0–100 composite using the three weight inputs, which auto-normalize, so they don't even have to add up to 100 (defaults: 35/30/35 for sharpness/brightness/pose). The highest composite wins, and the node returns that image.
The inputs that matter
image_batch- your renders. Only the firstmax_images(default 5, max 20) get scored, same cap pattern as the batch compare.target_threshold(default 80) - the bar forthreshold_met=YES. It doesn't reject below-threshold images; it still returns the best one either way. It's a flag, not a gate.weight_sharpness,weight_brightness,weight_pose- how much each factor counts. If you only ever shoot front-facing portraits, shift weight from pose into sharpness. If out-of-focus faces are your enemy, crank sharpness.
Outputs
best_image(IMAGE) - the winning frame, ready for a Save Image or a detailer.best_score(FLOAT) - the composite, 0–100.best_attempt(INT) - which batch index won (1-based).threshold_met(STRING) -YES/NO.detail_json(STRING) - per-image breakdown: sharpness, brightness, pose score, yaw/pitch/roll, and face confidence. This is where you see why the winner won, and why a face got scored 0 (usuallyno_face_detected).
Installing
Same pack as the rest - ComfyUI Manager search comfyui-rekogniflow, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Aiconomist/comfyui-rekogniflow
cd comfyui-rekogniflow
pip install -r requirements.txt
Only boto3, botocore, Pillow and numpy - no models, no GPU. Copy .env.example to .env in the pack folder, drop in an AWS key (IAM user with AmazonRekognitionReadOnlyAccess), leave the node's aws_* fields blank, restart. It lands under image/face/aws.
Gotchas
The trap is reading "quality" as "aesthetic." A sharp, perfectly exposed, front-on face can still be an ugly portrait - this scores technical quality, not taste. Pair it with the compare nodes if you also need likeness, or you'll be auto-selecting the crispest render that looks nothing like your subject. And remember each scored image is a billable AWS call (1,000/month free for a year, then ~a cent each), so max_images is a cost dial as much as a speed dial. If every image in detail_json shows no_face_detected, that's the story - your faces are too small, too distorted, or too far off-axis for Rekognition to even find.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image_batch | IMAGE | — | |
| aws_region | STRING | — | |
| aws_access_key | STRING | — | |
| aws_secret_key | STRING | — | |
| target_thresholdopt | FLOAT | 80.00–100 | — |
| max_imagesopt | INT | 51–20 | — |
| image_qualityopt | INT | 9550–100 | — |
| weight_sharpnessopt | FLOAT | 350–100 | — |
| weight_brightnessopt | FLOAT | 300–100 | — |
| weight_poseopt | FLOAT | 350–100 | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| best_image | IMAGE | — |
| best_score | FLOAT | — |
| best_attempt | INT | — |
| threshold_met | STRING | — |
| detail_json | STRING | — |