CPHTest Scan Analysis

November 11, 2026 · 4:03–5:21 PM Eastern · 40,112 candidate hashes

Methodology

This efficacy test began with just over 40,000 cover hashes in a local instance of Metron, representing approximately 21% of the metron.cloud issue count reported at the time (187,642 issues). The local search corpus contained 40,000 issues and 40,112 cover hashes, including variants.

Scanning was performed using a custom Android client named CPHTest (Cover Perceptual Hash Test), which was built for this purpose in the experimental Metron branch. Once configured with an API key for a local network instance, the client implements a simple workflow:

  1. The user captures a photo of the target cover.
  2. The user may optionally rotate the image and adjust the automatically detected bounding box.
  3. The client uses the bounding box to adjust for perspective, creating a cropped, rectangular capture of the cover, which the user reviews.
  4. The user confirms the corrected image and taps the button to search. A perceptual hash is computed from this image.
  5. The client queries a new API endpoint with the computed perceptual hash.
  6. The database compares the hash with its stored cover hashes and returns the top eight closest distinct comics. Results use competition ranking: if the closest matches differ by 8, 8, and 12 bits, they are ranked 1, 1, and 3.
  7. The client receives this data and displays the matches to the user.
  8. The user taps the checkmark beside the correct match, or the button at the bottom indicating that none of the top eight images are correct.
  9. The client calls a temporary “notetaker” API endpoint created specifically for this experiment, which captures data about the match or lack thereof for analysis. This includes success or failure, the ranking of the matching comic, and the recorded performance data.

Client Workflow

The screenshots illustrate corner editing, corrected-image review, search confirmation, and the result-feedback controls. They show different scans rather than a single continuous attempt.

Testing Environment

A consistent environment was used for testing, consisting of a worktable with a black mat marked with 1-inch grid squares and a single powerful LED worklamp.

The testing environment: gridded black work mat, comic covers, test phone, and LED worklamp.
The testing environment: gridded black work mat, comic covers, test phone, and LED worklamp.

Test Subjects

The tester scanned 139 comics from their collection. Care was taken in advance to ensure that the test subjects were represented in the local database. One unavailable reference cover was identified after the fact and its trial was excluded, leaving 138 eligible comic trials. The exclusion and subsequent collection-context findings are documented in Validation and Audit; later identification alone does not establish catalog presence at scan time.

Scanning Policy

  1. The first scan was principally a “devil may care” scan. The client’s automatic capture, triggered when the bounding box held steady for a moment, was used with minimal editing to the maximum extent possible, simulating a user’s likely expectations of this tool.
    1. The image was always edited to correct rotation on the first scan if the phone’s accelerometer caused an erroneous upside-down scan.
    2. The automatically detected bounding-box corners were sometimes adjusted on the first scan if detection resulted in an incomplete capture of a corner or excessive warping. This sometimes happened with dark covers: low contrast between the cover and background made automatic corner detection less reliable.
  2. If the first scan successfully identified the comic, the tester proceeded immediately to the next comic.
  3. If the first scan did not successfully identify the cover, a second scan was attempted.
    1. The tester always adjusted the bounding-box corners on the second attempt to ensure an ideal crop.
  4. The tester proceeded to the next comic regardless of whether the second scan was successful.

Results and Accuracy

127 of 138 eligible comics matched within two attempts (92.03%). First scan: 109; retry rescue: 18; failed twice: 11.

109 first-scan successes, 18 retry-only successes, 11 failures; final rank counts 122 at rank 1, 3 at rank 2, 2 at rank 3, 11 failures

The 40 included no-match reports are not 40 failed comics: they represent 29 failed first attempts plus 11 failed retries. Every successful comic contributes only its final selected rank. The 18 retry successes were all rank #1. Among successful comics, 96.06% ranked first; among all 138 eligible trials, 88.41% ended with a rank-one match.

Processing Times

MeasurementMin (ms)Max (ms)Mean (ms)Median (ms)
Android Client Hash Processing182.330284.137230.795232.121
Postgres Hash Search42.98386.27247.31745.430
API Round Trip178.139412.618219.380205.242
User Experience373.495684.622450.176441.723

All 167 eligible attempts included. Postgres hash search is part of API round trip, so these are overlapping timings. User experience excludes capture/corner editing, human decisions, artwork loading, and feedback submission.

Distributions of Android client hash processing, Postgres hash search, API round trip, and User experience

Measured Processing Work per Comic, Including Retries

Summed work across 1–2 attemptsnMin (ms)Max (ms)Mean (ms)Median (ms)
Android Client Hash Processing138182.330544.566279.296241.402
Postgres Hash Search13843.050129.53257.26146.517
API Round Trip138178.139620.557265.482214.896
User Experience138373.4951165.122544.778457.060

These totals sum measured work across each inferred comic trial; they do not include time spent recapturing or making decisions.

Trials with Negative Outcomes

These 11 eligible trials failed twice. Later user confirmation identifies 9 of them; 2 remain unidentified. Identities were not recorded in the original failure notes. Catalog presence at scan time is not established by this identity confirmation.

TrialAttempt indicesComic (when confirmed)Identity source
66,7Absolute Wonder Woman (2024) #6User confirmed in chat on 2026-11-11
3845,46Unknownnot recorded
4251,52Unknownnot recorded
5565,66Absolute Green Arrow (2026) #3User confirmed in chat on 2026-11-11
5869,70Buffy the Vampire Slayer Season Eight (2007) #1User confirmed in chat on 2026-11-11
6072,73Buffy the Vampire Slayer Season Eight (2007) #3User confirmed in chat on 2026-11-11
6174,75Buffy the Vampire Slayer Season Eight (2007) #4User confirmed in chat on 2026-11-11
86106,107Fables (2022) #158User confirmed in chat on 2026-11-11
87108,109Fables (2022) #159User confirmed in chat on 2026-11-11
93115,116Guardians of the Galaxy (2023) #1User confirmed in chat on 2026-11-11
109136,137Monstress (2015) #37User confirmed in chat on 2026-11-11

Validation and Audit

Excluded Trial: Unavailable Reference Cover

Trial 7 — Absolute Wonder Woman #12, unrepresented variant. The user confirmed this cover is not in Metron and requested its exclusion. Its original attempts 8 and 9 are omitted from outcome percentages, rank frequencies, per-attempt processing times, and per-comic processing totals. The raw notes remain unchanged. The eligible analysis therefore contains 138 comics and 167 attempts, from an archive of 139 trials and 169 notes. This is a coverage-based exclusion, not a removed timing outlier.

Exclusion rationale · All trials with inclusion flags · All attempts with inclusion flags

Collection and Cover-reference Context Supplied After Scanning

Retry pairing is based on chronology and the supplied policy, not similarity or guessed titles. One pair changed by 20 hash bits and is flagged in the audit for review, without changing its grouping. This single-session result should not be treated as a general population accuracy estimate.

Data and Reproducibility

Retry grouping is reconstructed. Trials are reconstructed from chronological records and the stated policy. Failure notes contain no intended comic/session ID. Later user confirmations identify 9 included failed comics; 2 remain unidentified. Assumes every attempt was recorded and the policy was followed without exceptions. Original records are preserved; the pairing audit makes every grouping reviewable.

All attempts · Comic trials · Retry audit · Rank data · Summary JSON · Methodology

Original notes remain unchanged at the source. Local Metron and PostgreSQL remain stopped.

Appendix: Measurement Definitions

These are elapsed wall-clock measurements, not CPU-only measurements. Waiting, I/O, scheduling delays, and garbage collection inside a measurement window are included. The processing order is:

Android client hash processing → API request → Postgres hash search → API response. API round trip surrounds the request, database work, and response.

Android Client Hash Processing

Starts on Android immediately before dispatching hash work to Dispatchers.Default. Ends immediately after the hexadecimal hash string is produced, before bitmap recycling and returning the finished result to the UI thread.

Includes waiting for the background task to start; reading the corrected JPEG's dimensions; reading and decoding the JPEG into an ARGB bitmap; allocating/copying the pixel array; converting to grayscale; Lanczos resizing to 32 × 32; computing the DCT; selecting the 8 × 8 coefficients; calculating the median; and forming the 64-bit hexadecimal hash. First-use hash-object initialization, if any, is inside this window as well.

Excludes camera capture, corner adjustment, perspective correction, preview, user confirmation, bitmap recycling after the timestamp, and dispatch back to the UI thread after the hash completes.

Postgres Hash Search

Starts when PostgreSQL evaluates the materialized start-clock expression before scanning candidate hashes. Ends when the outer SQL result samples the elapsed clock after ranking and assembling the match records. This is the instrumented matching portion of query execution, not the complete database request duration.

Includes reading valid issue and variant hashes; XOR/popcount Hamming distance calculations; taking each comic's closest cover; ranking and selecting the top eight distinct comics; retrieving winning cover hashes, URLs, and variant IDs; counting hashes checked; SQL result assembly; and instrumentation overhead.

Excludes SQL parsing/planning, opening a database connection, transport between Django and PostgreSQL, authentication, the subsequent query for descriptive metadata of the eight comics, and Django's response serialization.

API Round Trip

Starts immediately before dispatching the API operation to Dispatchers.IO. Ends after it returns to the UI thread.

Includes client dispatch/queue waits; constructing and validating the request and headers; acquiring a connection; DNS, TCP setup, and TLS negotiation when needed; request and response network travel; server request handling, authentication, throttling, validation, database matching, the separate comic-metadata query, and response serialization; receiving the complete JSON body; Android JSON parsing and basic result-shape validation; response cleanup; and returning to the UI thread. Connection reuse may avoid DNS/connection/TLS setup on a particular request.

Excludes building result cards, downloading/displaying cover artwork, human match selection, and feedback submission.

User Experience

Derived sum: Android client hash processing + API round trip.

This is not one continuously running timer and is not the complete human scan experience. The gap between its component timers is excluded: bitmap recycling, returning from the hash task, and updating the “Searching Metron…” UI. It also excludes capture, corner adjustment/perspective correction, preview/confirmation, human decisions, result rendering, artwork loading, and feedback submission.

Postgres hash search is already included in API round trip. Do not add it again. Per-comic processing-work totals sum these measurements over the one or two attempts reconstructed for that comic, without adding the human retry delay.