image-bridge-toolkit
image-bridge-toolkit provides cache-backed perceptual image fingerprinting and cross-dataset bridge matching designed to handle large scale (50,000+ image) libraries. It finds identical or highly similar images across disparate folders while remaining resilient to scale shifts, aspect ratio changes, heavy compression, and intrusive watermarks.
Key Features
- Per-Directory JSON Caching: Generates and maintains lightweight
image_cache.jsonfiles within each directory, keyed by filename and modification time (mtime). - Scale-Invariant Waveform Approximations: Uses 16-float 1D Discrete Cosine Transform (DCT) grayscale histogram vectors to ignore local watermark text spikes and compression artifacts.
- 5-Tier Matching Funnel:
- Tier 1 (Bitwise pHash Luma + Color): Generous 64-bit Hamming filtering to eliminate obvious non-matches.
- Tier 2 (Histogram Waveform): Euclidean distance on 16 low-frequency DCT coefficients to filter lighting distribution changes.
- Tier 3 (LAB Perceptual Metrics): Vector distance across
lab_value,lab_hue,lab_chroma, andlab_warmth. - Tier 4 (Spatial Layout Tie-Breaker): 16-point color spatial coordinates down-weighting image outer margins where signatures and borders reside.
- Tier 5 (Optional SSIM Direct Comparison): Full structural similarity pixel comparison on top candidate matches.
- Resumable & High Performance: Output streams as
.jsonlobjects, allowing runs over huge original sets to resume instantly without re-processing. - Zero-Dependency Fallback: Runs with
OpenCVif available for acceleration, or falls back to pureNumPy+Pillow.
Installation
Install via PyPI:
# Minimal installation (NumPy + Pillow)
pip install image-bridge-toolkit
# Recommended installation (includes OpenCV acceleration & progress bars)
pip install "image-bridge-toolkit[all]"
For development:
git clone [https://github.com/akingdom/image_bridge_toolkit.git](https://github.com/akingdom/image_bridge_toolkit.git)
cd image_bridge_toolkit
pip install -e ".[all]"
Usage
1. Build or Update Metadata Caches (imgcache-build)
Walks a root directory, scanning all subdirectories (skipping any directory containing .ignore_subdir), and generates or updates image_cache.json.
# Build cache for a query dataset (e.g., 1,000 watermarked images)
imgcache-build /path/to/thumbnails_set
# Build cache for a target dataset (e.g., 50,000 original images)
imgcache-build /path/to/originals_set
2. Match Datasets (imgmatch-bridge)
Matches images from the query dataset against the target library, generating a bridge mapping file with confidence scores and top candidate lists.
imgmatch-bridge /path/to/thumbnails_set /path/to/originals_set \
-o bridge_map.jsonl \
--max-hamming 16 \
--candidate-threshold 0.03 \
--direct-compare
Command-Line Options
| Flag | Default | Description |
|---|---|---|
-o, --output |
bridge_map.jsonl |
File path for output streaming results. |
--max-hamming |
16 |
Maximum allowed Tier 1 pHash Hamming distance threshold. |
--candidate-threshold |
0.03 |
Percentage band (e.g., 3%) to include close secondary matches. |
--direct-compare |
False |
Performs Tier 5 pixel-level SSIM re-ranking on candidates. |
visual_sig Schema (v2.0+)
Each visual_sig entry is an array of signature points. Starting with this release, each point contains:
| Field | Type | Range | Description |
|---|---|---|---|
x, y |
float | 0–100 | Normalised position (percentage) |
size |
float | 0–100 | Spatial weight (percentage) |
hex |
str | #rrggbb |
Dominant colour |
lab |
[float, float, float] | L:0–100, a/b:‑128–127 | CIELAB colour |
grad_theta |
float | 0–2π | Gradient direction (radians) |
grad_mag |
float | ≥0 | Gradient magnitude |
elongation |
float | 0–1 | 0=round, 1=line |
axis_phi |
float | 0–π | Principal orientation (radians) |
primitive |
int | 0 or 1 | 0=plane, 1=edge |
density |
float | 0–1 | Local point concentration |
curvature |
float | ≥0 | Isophote curvature (clamped) |
All fields are computed from the image. Consumers that only read x, y, hex, size will continue to work unchanged; the extra fields are ignored.
Example access:
cache = json.load(open("image_cache.json"))
points = cache["image.jpg"]["visual_sig"]
for p in points:
print(f"{p['hex']} at ({p['x']:.1f}, {p['y']:.1f}) curvature={p['curvature']:.2f}")
visual_sig — Neighbour‑Based Topology (v2.0+)
Each visual_sig node now carries a flattened set of topology fields computed from the spatial neighbourhood of the point within a dense scaffold (16×16 grid). This enables categorical recognition of shapes (e.g., apple, person, car) and handles non‑rigid curves.
| Field | Description |
|---|---|
x, y |
Position (0‑100) |
size |
Saliency (Voronoi assignment over scaffold) |
hex, lab |
Dominant colour (hex + CIELAB) |
grad_theta, grad_mag |
Gradient direction (radians) and magnitude |
elongation, axis_phi |
Shape anisotropy (0=round, 1=line) and principal axis |
primitive |
0=plane, 1=edge (quadrant variance) |
density |
Local point concentration (fraction of scaffold within radius) |
curvature |
Local bend κ (clamped to 2.5) |
Selection algorithm:
- Greedy phase: picks colour‑diverse, spatially spread points.
- Structural phase: scores remaining points by elongation, curvature, gradient; applies NMS for spacing.
- Budget: dynamic between 10 and 20 points.
Experimental matcher: compute_topological_similarity uses these fields for more discriminating matching.
How Topology Fields Are Computed
For each visual_sig point, topology fields are sampled from the image at that location:
- Gradient (
grad_theta,grad_mag): First derivatives(Ix, Iy)from the grayscale image. - Shape (
elongation,axis_phi): Hessian eigenvalues and eigenvectors(Ixx, Iyy, Ixy).elongation=1 - |λ_min / λ_max|(0 = round, 1 = line)axis_phi= angle of the dominant eigenvector.
- Primitive (
primitive): 1 if edge‑like (elongation > 0.5andgrad_mag > 5.0), else 0. - Curvature (
curvature): Isophote curvature formula:κ = |Ixx·Iy² - 2·Ixy·Ix·Iy + Iyy·Ix²| / (Ix² + Iy²)^(3/2) - Density (
density): Fraction of other points within 0.1 normalized distance. - Colour (
lab): Converted fromhexusing sRGB → XYZ → CIELAB.
All derivatives are computed on a 64×64 resized grayscale image and sampled at each point's location.
Cache Integrity & Updating
mtimeMatching: A cached entry is preserved as long as the file's modification time matches the record inimage_cache.json.- Partial Recomputation: If an existing cache entry is missing a newly added metric type (e.g.,
hist_waveform), only the missing calculation is executed; existing valid metrics are preserved. - Corrupt Cache Handling: Invalid or unparseable JSON files are automatically caught and rebuilt without interrupting directory traversal.
- Subdirectory Exclusion: Placing a
.ignore_subdirmarker inside any directory causes the builder and matcher to ignore that folder and all nested subdirectories.
Programming Usage
Includes
from pathlib import Path
from image_bridge_toolkit.cache_builder import ImageCacheBuilder
from image_bridge_toolkit.matcher import run_match
--- Tool A: build/refresh caches ---
builder = ImageCacheBuilder("/data/deviantart", workers=8)
stats = builder.run() # returns dict: dirs, files_seen, files_updated, files_reused
print(stats)
builder = ImageCacheBuilder("/data/originals", workers=16)
builder.run()
--- Tool B: match ---
run_match(
da_root="/data/deviantart",
orig_root="/data/originals",
output_path="bridge_map.jsonl",
max_hamming=16,
candidate_threshold=0.03,
do_direct_compare=True,
workers=8,
resume=True,
)
read results back in
import json
with open("bridge_map.jsonl") as f:
for line in f:
result = json.loads(line)
print(result["query_path"], "->", len(result["top_matches"]), "candidates")
License & Copyright
- Source Code (
src/): Licensed under the MIT License. - Documentation & Branding: Copyright © 2026 Andrew Kingdom. Licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (CC BY-NC-ND 4.0).
- Translation Permission: Permission is explicitly granted to translate this documentation into other languages, provided that full attribution to Andrew Kingdom is maintained, a direct link to the original repository is included, and no non-linguistic modifications or structural alterations are made to the content.
Metadata
Release files for image-bridge-toolkit 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| image_bridge_toolkit-0.3.1.tar.gz | 43.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| image_bridge_toolkit-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 86.8 kB
Release files / image_bridge_toolkit-0.3.1.tar.gz
| Download URL | image_bridge_toolkit-0.3.1.tar.gz |
|---|---|
| Size | 43.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3633f95da3de11279a3bb579ffaffa767bb575634ed8b6b494072c80dbe97d6c
|
|
BLAKE2b-256 checksum How to use checksums |
9fb1459d604846c1f4f339dbc7b26a8a010ba0da2cb427550bd5399f905c588f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.7
|
Release files / image_bridge_toolkit-0.3.1-py3-none-any.whl
| Download URL | image_bridge_toolkit-0.3.1-py3-none-any.whl |
|---|---|
| Size | 43.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bde152239b1b4717f36132bdb5678aa41c6b6ad24a4d81e4de124bc3ec36af79
|
|
BLAKE2b-256 checksum How to use checksums |
520161d74cfa318e1e18011d1865c2806564d39ad63aa55a322f19913a1ddf37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.7
|
Security for image-bridge-toolkit 0.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.