blazediff-interpret
Structured region analysis for image diffs. Given two images and a set of changed regions, it says what changed in each one — not just where.
use blazediff_interpret::{interpret, ChangeSource};
// From a pixel diff — what `blazediff` does.
let result = interpret(&expected, &actual, ChangeSource::Diff {
output: &diff_image.data,
diff_count: diff.diff_count,
diff_percentage: diff.diff_percentage,
})?;
// From a similarity map — what `blazediff-ssim` does.
let result = interpret(&expected, &actual, ChangeSource::ScoreMap {
map: &outcome.map,
width: outcome.map_width,
height: outcome.map_height,
floor: 0.99,
})?;
// From boxes you already have.
let result = interpret(&expected, &actual, ChangeSource::Regions(&boxes))?;
println!("{}", result.summary);
for region in &result.regions {
println!("{:?} at {} ({:.2}%)", region.change_type, region.position, region.percentage);
}
Why it's a separate crate
The classifier is deliberately independent of whatever found the regions. Three producers feed it today:
| Producer | ChangeSource |
How it finds regions |
|---|---|---|
blazediff |
Diff |
connected components over a pixel-diff mask |
blazediff-ssim |
ScoreMap |
thresholding a local SSIM score map |
| your code | Regions |
DOM rectangles, a JS-side diff, a crop list — anything |
All three call the same function and get identical treatment; only the description of where
differs. blazediff and blazediff-ssim are independent of each other, so a classifier living in
either would be unreachable from the other. It sits below both instead.
Coarse regions are fine
A producer only has to know roughly where something changed. Before any statistic is computed, the supplied boxes are refined against the source pixels — every pixel whose YIQ delta falls below the noise floor is dropped — so shape, colour and gradient analysis stay per-pixel no matter how blocky the input was. (If a claimed box refines to nothing but the content does differ — a sub-threshold edit such as a subtle uniform recolor — the box is kept as-is so the region still gets meaningful statistics.)
// An 8x8 change, described exactly and then quantized to a 16px grid.
let exact = interpret(&a, &b, ChangeSource::Regions(&[BoundingBox { x: 16, y: 16, width: 8, height: 8 }]))?;
let coarse = interpret(&a, &b, ChangeSource::Regions(&[BoundingBox { x: 16, y: 16, width: 16, height: 16 }]))?;
assert_eq!(coarse.diff_count, exact.diff_count); // both 64
That is what makes an SSIM window map a usable region source: its grid is coarse, but the
statistics derived from it are not. diff_count therefore means the same thing on every path —
actually-changed pixels, never windows.
API
| Item | Purpose |
|---|---|
interpret |
the entry point: a ChangeSource in, a full InterpretResult out |
ChangeSource |
Diff (a pixel diff's output + counts), ScoreMap (a similarity map), or Regions |
classify_region / classify_regions |
classify against a mask you already hold |
detect_regions |
connected components over a boolean mask |
merge_overlapping_components |
fuse fragmented components whose bboxes overlap or nearly touch |
extract_change_mask |
recover a mask from an RGBA diff visualization |
detect_shifts |
the shift-relabeling pass, for producers holding an exact mask |
classify_severity, build_summary |
the pooling steps, exposed for custom pipelines |
Regions arriving from a caller are validated: a box outside the image is an
InterpretError::RegionOutOfBounds, not an out-of-bounds panic. That matters now that regions
cross the wasm and N-API boundaries.
Python - blazediff-interpret
pip install blazediff-interpret
PyO3 bindings shipped as abi3-py38 wheels for CPython ≥ 3.8 (macOS, Linux
manylinux, Windows; arm64 + x86_64). Built from this crate's python Cargo
feature.
import blazediff_interpret as interpret
result = interpret.interpret_images("expected.png", "actual.png", "diff.png")
print(result["summary"])
for region in result["regions"]:
print(region["changeType"], region["bbox"])
# Also: interpret_buffers(bytes, bytes), interpret_ssim(base, compare,
# metric=...) and interpret_regions(base, compare, regions).
The result crosses as a plain dict with camelCase keys, matching the N-API
binding and the CLI's --json. interpret_regions takes (x, y, width, height) tuples or mappings with those keys, so a bbox from a prior result
feeds straight back in.
What it classifies
Each region gets a change type, a shape, a position, a confidence, and the statistics behind them — colour delta, gradient/edge correlation, luminance correlation, chroma-plane movement (hue rotation, saturation, delta smoothness), fill ratios, and the signals the classifier used. See INTERPRET.md for the full algorithm: pipeline stages, formulas, and classification rules.
License
MIT
Metadata
Release files for blazediff-interpret 6.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| blazediff_interpret-6.4.0-cp38-abi3-win_arm64.whl | CPython 3.8 | abi3 | Windows ARM64 | Details |
| blazediff_interpret-6.4.0-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details |
| blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| blazediff_interpret-6.4.0-cp38-abi3-macosx_11_0_arm64.whl | CPython 3.8 | abi3 | macOS 11.0+ ARM64 | Details |
| blazediff_interpret-6.4.0-cp38-abi3-macosx_10_12_x86_64.whl | CPython 3.8 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 4.0 MB
Release files / blazediff_interpret-6.4.0-cp38-abi3-win_arm64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-win_arm64.whl |
|---|---|
| Size | 608.3 kB |
| Tags | CPython 3.8 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
65cb7f9410c0b593c6553862d32ecad52ac6fe4481901564b4d3a11ffc1c9855
|
|
BLAKE2b-256 checksum How to use checksums |
96424e092bf87faca3053a948d133a0664118dec094ea4081552eb20887dd98b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / blazediff_interpret-6.4.0-cp38-abi3-win_amd64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 642.5 kB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
76851d5f36605167e471dd8b2341364641b72a205cbc80ba07dc2b9aed84f821
|
|
BLAKE2b-256 checksum How to use checksums |
7df7e33be6535b5ee398c267541709d3685e673a8fb7a90c051a50a6a81484c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 751.8 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
157db4bc7b99e147ef15e34ecb92c5e7a0e8431575a9281e1af8c525c87deed6
|
|
BLAKE2b-256 checksum How to use checksums |
2b7e54bb882a1099bc5a2afa739e417ea6ec52684a2297b96f2bf45e0e67152e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 702.0 kB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
2d602368123972bed3195dfdf0dc02cf8f7bcdb2d4a5b5c03642980d7cdd8057
|
|
BLAKE2b-256 checksum How to use checksums |
b8c99f796fa7331c44b3cda8d6df93182c73051423afe43fde155b04ed636007
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / blazediff_interpret-6.4.0-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 630.9 kB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f75a304c9ac7558f9c8723114eb01abcfe768cf5bca074737e15f807ca385af5
|
|
BLAKE2b-256 checksum How to use checksums |
bfc1ce75c9eae8cc42cf792c671257060cd50e5f8d0002aba5343790b86e5ca1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / blazediff_interpret-6.4.0-cp38-abi3-macosx_10_12_x86_64.whl
| Download URL | blazediff_interpret-6.4.0-cp38-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 669.1 kB |
| Tags | CPython 3.8 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
1a4728ccca6fa0525a923d3820a36af42bc6c37d5993c97c257e935abbf77206
|
|
BLAKE2b-256 checksum How to use checksums |
33a1cb2e1a5f3491e590aaec31593a0ee5603c4a2e7711be1fcd85d94ce7f0f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|