arkennemasis Calibrate (derive tolerances from a real set)
Stop guessing your thresholds — measure them
- plate
- report
- tolerances_json
- frame_tolerance
- colour_tolerance_de
- identity_tolerance
ArkCalibrate is the node that turns verification thresholds from vibes into numbers. Instead of picking a colour-tolerance value out of thin air and hoping, it runs every check across an existing set of images for a product and derives the thresholds from the measurements themselves. And here's the part that makes it almost free: no generation, no API calls, no spend. It just reads images off disk and measures them against the locked plate.
In the arkennemasis Variation pipeline, Verify Candidate is the step that used to live in the operator's head - pass/soft/hard on identity, frame match, colour ΔE, bleed. But a verdict is only as good as its tolerances, and tolerances were guesswork until this node. Calibrate is the "stop guessing" step you run before you trust a pipeline with a real client.
How it works
You point image_dir at a folder of already-produced images for the product and give it the locked plate. It runs the full battery of checks on each image - silhouette overlap, shape distance, ratio drift, bounding-box shifts, SSIM, colour ΔE, bleed - and collects the distributions. Then two modes:
- With a
labels_csv(filename,label, label beingacceptorreject): thresholds are chosen to separate the two populations. This is the honest version - you're telling the node what good and bad look like in your own book, and it finds the boundary. - Without labels: it's descriptive only, and thresholds are set at the
percentileof the observed distribution (default 95). That's "your set is the population, keep the 95th percentile of what it actually produces" - useful, but it can't tell good from bad; it just tells typical from extreme.
Two optional CSVs refine it. targets_csv (filename,region,hex) gives the colour check a per-image target, which matters when different images target different regions. write_to dumps calibration.json and a per-image measurements CSV so the calibration survives as a record rather than existing only in the node. limit (0 = all) caps how many images get measured, and percentile only applies in the no-labels mode.
The outputs
report- the human-readable summary, including (when labelled) the operator's true current pass rate. The tooltip calls it "a number worth having before building anything," and it's right: if your existing set passes at 38%, no threshold tweak is going to fix that.tolerances_json- the full derived set, the thing you feed back into the recipe so verification uses measured values.frame_tolerance,colour_tolerance_de,identity_tolerance- the three headline numbers as plain floats, so you can wire them straight into a verification node or a report without parsing JSON.
One important detail: IS_CHANGED returns NaN here, so the node re-runs every time - appropriate, since a calibration shouldn't be served from ComfyUI's cache. It's also an output node, so it will always execute when its inputs are present.
Installing and using it
It ships with the comfyui-arkennemasis pack:
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
pip install replicate httpx
then restart, and it's under arkennemasis/Variation. No models, no key, no generation spend - the whole thing is PIL/numpy math over a folder of images.
The practical flow: run a first pass with permissive-ish thresholds, collect a real labelled set from what comes back (you will have rejects), then run Calibrate with labels_csv to find where the boundary actually sits. Feed tolerances_json back into Recipe Compile and the next run verifies against measured reality. Where people get burned: pointing image_dir at a folder containing images for different products - the calibration is per-product, and mixing plates guarantees nonsense boundaries.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image_dir | STRING | Folder of already-produced images for this product. | |
| plate | IMAGE | The locked base plate. | |
| plate_lock_jsonopt | STRING | — | |
| labels_csvopt | STRING | Optional CSV of 'filename,label' where label is accept or reject. With it, thresholds are chosen to separate the two populations; without it the report is descriptive only. | |
| targets_csvopt | STRING | Optional CSV of 'filename,region,hex' so the colour check has a per-image target. | |
| percentileopt | FLOAT | 95.050–100 | With no labels, thresholds are set at this percentile of the observed distribution. |
| limitopt | INT | 00–10000 | Measure at most this many images. 0 = all. |
| write_toopt | STRING | Optional folder for calibration.json and the per-image measurements CSV. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| report | STRING | — |
| tolerances_json | STRING | — |
| frame_tolerance | FLOAT | — |
| colour_tolerance_de | FLOAT | — |
| identity_tolerance | FLOAT | — |