1. Sharpness Analyzer
The one-input node that tells you exactly which frames are blurry
- images
- scores
The whole node is one input and one output. You feed it an IMAGE batch and it hands back a score for every frame - a single number per image that says how sharp (or how mushy) it is. That's it. No knobs, no model, no hidden settings. SharpnessAnalyzer is the scoring half of the SharpFrames duo in ethanfel/ComfyUI-Sharp-Selector, and its only job is to be the boring, reliable part of the pair.
Why would you reach for it? Generation filtering. Wan, AnimateDiff, and img2img passes all produce batches where a frame or two come out soft, smeared, or outright blurred. If those frames are about to go into an upscaler, a FaceDetailer, or a training dataset, you're spending GPU time and dataset slots on garbage. The pack author built this for exactly that: a personal project that auto-discards blurry frames from Wan outputs. The same logic that keeps a blurry frame out of your LoRA dataset (where, as the LoRA training notes community will tell you, dataset curation beats every training knob) also keeps one out of your second-pass upscale.
How it works
For every image in the batch it converts to grayscale and computes the Laplacian variance (cv2.Laplacian(gray, CV_64F).var()). High variance means lots of edge energy - sharp detail, in-focus subject. Low variance means flat, smooth, blurry. It's the classic computer-vision blur metric, zero machine learning involved: no weights, no downloads, nothing to tune. That's both its strength (instant, CPU-only, deterministic) and its limit (a "sharp" score isn't the same as "aesthetically good" - it just detects edge energy).
One honest gotcha: the README claims the analyzer "passes the images through." The shipped code doesn't. Its only output is the scores list, type SHARPNESS_SCORES. You keep your own IMAGE wire and feed both into the sibling SharpFrameSelector. And because SHARPNESS_SCORES is a custom type only this pack understands, the output wires only into nodes from this pack - you can't splice it into another pack's score plumbing.
What it wires into
- Inputs:
images- anyIMAGEbatch. VideoHelperSuite, AnimateDiff-Evolved, Load Video, or a stack of generations all work. - Outputs:
scores- one float per frame, in the same order as the input batch.
A typical chain: AnimateDiff output → SharpnessAnalyzer → scores → SharpFrameSelector (with the IMAGE wire run alongside) → keep the sharp frames → upscale. The selector's min_sharpness lets you actually use the scores instead of just looking at them.
Install
ComfyUI Manager (search "ComfyUI-Sharp-Selector") or:
cd ComfyUI/custom_nodes
git clone https://github.com/ethanfel/ComfyUI-Sharp-Selector
Its requirements.txt needs opencv-python and numpy - both already present in most ComfyUI installs. Restart after installing. If you hit a ModuleNotFoundError: cv2 at load, pip install opencv-python. The classic snag is a pack that already pulled in opencv-python-headless; the two don't play nice in the same environment, so expect pip to complain if that's your setup. No model files, ever - this node is pure math.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| scores | SHARPNESS_SCORES | — |