|
Download README.md from devmandan/qr-scan-difficulty-check: direct link, hf CLI and curl.
- Browser
- Download file 14.6 kB
-
https://huggingface.co/spaces/devmandan/qr-scan-difficulty-check/resolve/main/README.md
- Command line
-
hf download hf://spaces/devmandan/qr-scan-difficulty-check/README.md
-
curl -L -o README.md https://huggingface.co/spaces/devmandan/qr-scan-difficulty-check/resolve/main/README.md
14.6 kB
| title: QR Scan Difficulty Check | |
| emoji: 📷 | |
| colorFrom: gray | |
| colorTo: red | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| disable_embedding: true | |
| license: other | |
| short_description: Where your QR code falls among thousands of measured codes | |
| # How hard is your QR code to scan? | |
| All 6,499 codes [QR Scan Difficulty](https://huggingface.co/spaces/devmandan/qr-scan-difficulty) measured at seven | |
| sizes, on one scale from easy to hard, shaded by how many of eight scanners read each one at 1280 pixels. Add | |
| pictures of your own codes and each one appears as a numbered line where it falls. Move the slider to see a | |
| measured code from any spot, with what the eight scanners did on codes there. Each picture also gets a level (Easy, | |
| Everyday, Tough or Advanced), how confident that level is, and checks on the picture that explain it. | |
| ## How a picture is placed | |
| Each picture is read the way every measured code was: turned grey and shrunk, never enlarged, to seven sizes | |
| from 1920 down to 224 pixels on its long side, and read at each size by the five of the eight scanners that run | |
| on a Linux server, with the measurement's versions and settings: | |
| | Scanner | What runs here | | |
| |---|---| | |
| | Android Settings' scanner | [ZXing](https://github.com/zxing/zxing/releases/tag/zxing-3.5.2) 3.5.2, called as Android's Settings app calls it (QR only, inverted retry) | | |
| | WeChat's scanner | [WeChatQRCode](https://docs.opencv.org/4.12.0/d5/d04/classcv_1_1wechat__qrcode_1_1WeChatQRCode.html), OpenCV contrib 4.12.0.88, with its detector and super-resolution models (the app's own build may differ) | | |
| | zxing-cpp | [zxing-cpp](https://github.com/zxing-cpp/zxing-cpp/releases/tag/v3.1.1) 3.1.1, library defaults, QR only | | |
| | OpenCV, newer | [QRCodeDetectorAruco](https://docs.opencv.org/4.12.0/d3/db0/classcv_1_1QRCodeDetectorAruco.html), OpenCV 4.12, single-code `detectAndDecode` | | |
| | OpenCV, original | [QRCodeDetector](https://docs.opencv.org/4.12.0/de/dc3/classcv_1_1QRCodeDetector.html), OpenCV 4.12, single-code `detectAndDecode` | | |
| Transparent parts count as white, as on a printed page. A scanner reads a picture when it returns the content that | |
| more of the five return than any other, even if only one returns any (the measurement scored each code against its | |
| true content instead); a picture with several codes is placed by that one. A decode that runs past 20 seconds counts | |
| as a miss, as in the measurement, and a picture's reading stops after 40 seconds, so that each request ends within a | |
| minute; reads not done by then count as misses, and the page says so. Read again on this Space's Linux server, 416 | |
| of the measured codes gave the measured result in all but 7 of their 14,560 reads: on this processor WeChat's | |
| scanner and OpenCV's newer detector come out differently on a few borderline pictures. | |
| The other three scanners, Apple's, Google's and Huawei's (Scan Kit), can't run here: Apple's runs only on Apple | |
| devices, and Google's and Huawei's, as measured, need Android. So a picture is placed from its 35 reads (five | |
| scanners at seven sizes) on the scale all eight set, which stays as measured: the five scanners' reader curves from | |
| the measurement's two-parameter item-response fit are held fixed, and the picture's difficulty is the most likely | |
| one given its reads. On the measured codes, codes that at least two of the five read at 1280 pixels land within | |
| about 4 points of where all eight put them, 9 times in 10, on a 0 to 100 scale where clean prints sit near 19 and | |
| tough prints near 56. Where only one reads it at 1280 pixels, or none does but some do at another size, only about | |
| half land that close. A dashed line means low confidence; a reading cut short by the time limit is always low. A | |
| picture none of the five read at any size goes to the pile on the right, where its place is least sure. Of the | |
| measured codes like that, most are distorted research images; the phones' own scanners still read about 1 in 6 of | |
| them (280 of 1,754, at some size), and 33 of the 59 photos and prints among them (BoofCV's photos, Broken QR 104's | |
| codes from the web, and the simulated everyday and tough prints). | |
| The page shows how many of the five read a picture at 1280 pixels, its level and how confident that is, checks on | |
| the picture with advice, and, for its place on the scale, how much of the curve there is codes all eight read at | |
| 1280 pixels. The curve is an illustrative mix of the sets, not a count of them: half everyday prints, a fifth each | |
| clean and tough prints, a tenth the research sets. The page never claims what a phone would do with your picture. | |
| ## Levels, confidence and checks | |
| Each picture also gets a level from its difficulty d, with the cut points in `web/data/levels.json`, which the | |
| server and the page both read: Easy below 30 (the left pile included), Everyday from 30, Tough from 50 and Advanced | |
| from 60 (the right pile included); a d on a cut goes to the level above. On the curve, the levels line up with the | |
| simulated prints: most clean prints are Easy (184 of 200), most everyday prints Everyday (443 of 600) and most | |
| tough prints Tough (433 of 600). | |
| What a level means depends on the picture's size, because the measured codes come in two kinds: 1,553 pictures over | |
| 1280 pixels on the long side, mostly simulated prints with some real photos, and 4,946 smaller ones, mostly | |
| 512-pixel research images, which are read 'at 1280 pixels' as they are, never enlarged. So beside your picture the | |
| page describes its level by the measured codes in pictures of the same size class that the five scanners here place | |
| at that level (`meaning` in levels.json), except in the right pile, where it describes the level in general terms | |
| only: the codes the five place at Advanced were read far more often by the phones' own scanners than the pile's | |
| own. For pictures over 1280 pixels, at 1280 pixels: at Easy (309 codes) all three phones' own scanners read 98% and | |
| Android Settings' 92%; at Everyday (687) all three 98%, Android Settings' 88%; at Tough (429) each phone's own 94 | |
| to 96%, all three together 88%, Android Settings' 44%; at Advanced (128) each phone's own 43 to 69%, at least one | |
| of them 78%, Android Settings' 2%. For smaller pictures: at Easy (1,383) all three over 99%, Android Settings' over | |
| 99%; at Everyday (542) all three 97%, Android Settings' 42%; at Tough (302) each 80 to 92%, all three 65%, Android | |
| Settings' 12%; at Advanced (2,719) each 13 to 31%, at least one 38%, Android Settings' under 1%. The levels list | |
| under the curve describes all measured codes at each level, by all eight scanners' level, counted as they are (not | |
| in the curve's illustrative mix) and named by what they mostly are. | |
| A level's confidence (high, medium or low) measures one thing: how well the five scanners here stand in for all | |
| eight. On the 6,499 measured codes, the level from the five scanners' place matched the level from all eight for | |
| 5,832 (90%). A picture takes the share that matched among measured codes with the same evidence: on a pile, the | |
| codes in that pile; otherwise how many of the five read it at 1280 pixels (fewer than two, or more) and how far d | |
| is from the nearest cut (under 2 points, 2 to 4, or more), and, with two or more reads, also the picture's size | |
| class (over 1280 pixels on the long side, or not) and, within 4 points of a cut, the side of the cut d is on. It is | |
| high where at least 90% matched, medium from 70%, and low below. The size class and the side matter because the | |
| eight scanners' d is offset from the five's. For pictures over 1280 pixels with two or more reads, near cuts 30 and | |
| 50 it sits about 2 to 3 points higher, so just below those cuts such a picture is often a level harder for all | |
| eight (55% and 20% matched), and just above them 99% matched. Near 60 it is pulled towards the cut from both sides | |
| (1.9 points higher just below it, 1.6 lower just above it, where 5 of 21 matched), so a picture over 1280 pixels | |
| within 4 points of 60 counts as below the cut on either side. For smaller pictures the offset is smaller, and just | |
| above a cut a picture is more often a level easier for all eight (66% matched just above 50, 91% just below). A | |
| reading cut short by the time limit is always low. The right pile is high only on the condition that the picture | |
| holds a code: all 1,754 measured codes there do, and 1,742 of them were Advanced for all eight too; a picture with | |
| no QR code at all lands there as well, so the page always says 'if it holds a code'. Confidence doesn't cover the | |
| photo itself: another photo of the same code can land at another level. | |
| The checks are image measurements made in the decoder worker with NumPy and OpenCV only, on the largest frame read | |
| (at most 1920 pixels on the long side), at the corners of the code that the scanners agreeing on its content found: | |
| camera pixels per square at 1280 pixels (before any tilt, which the angle check covers); size (version, squares | |
| across, pixel width, share of the picture); margin; sharpness; contrast; lighting (shadows and washed-out patches); | |
| and angle. The same picture always gives the same results. Each check is Fine, Borderline or a Problem (`ok`, | |
| `watch` or `problem` in `/api/measure`) by [QR Scan | |
| Difficulty](https://huggingface.co/spaces/devmandan/qr-scan-difficulty)'s factor tests (the `ladders` in its | |
| `site.json`: one code all eight scanners read, changed one thing at a time, 80 synthetic codes a step, read at 1280 | |
| pixels), counting a scanner as reading a step when it reads at least 9 in 10 of its codes, as that Space does: Fine | |
| where all eight read the step, Borderline where the phones' own scanners did but another didn't, and a Problem | |
| where one of the phones' own didn't. Each limit sits halfway between the check's median values on the last step | |
| with one status and the first step with the next, measured as the Space measures a visitor's picture; where two | |
| tests set one limit (version and square size for pixels per square, focus and shake for sharpness), it sits in the | |
| middle of the range both allow. For pixels per square the Problem limit rises with the version: the tests set it at | |
| versions 3 and 13, and it rises at the same rate in between and on to version 21. The margin is Fine from the 4 | |
| squares the QR standard asks for, Borderline below that, and a Problem with next to none (under a quarter square), | |
| though all eight still read the margin test's codes with half a square; for small or blurred codes the margin may | |
| only be known to be under a bound, and the page says so. A code filling 30% or more of the picture's long side, | |
| more than any simulated print, gets a framing note, not a status: a close view or a tight crop gives each square | |
| more camera pixels than a photo from where people stand. A picture up to 1280 pixels is read at its own size, never | |
| enlarged, so, unless it is Easy, it gets a note that a full-size original can land at an easier level. The checks | |
| are diagnostics only: they never change d, the level or the confidence, and the five scanners' reads are unchanged. | |
| The page lets you say what each picture shows: not sure (the default), the original graphic, a printed code or a | |
| code on a screen. The choice stays in your browser, new pictures take the last one, and it changes only which | |
| explanations and advice are shown. | |
| `/api/measure` keeps every earlier field and adds `rating` (`level`, `confidence`, `agree` and `n` for the measured | |
| codes behind it, `why` naming its main reason, and `big` for the size class) and `checks` (null when nothing could | |
| be measured, and for a reading cut short, which the checks never measure). | |
| ## Privacy | |
| A picture is written to a temporary file, read, and deleted as soon as the reading ends. Nothing is stored, and | |
| this server keeps no access log. The decoded content is sent back to your browser only, so you can see which code | |
| was read. Hugging Face, which hosts the Space, has its own [privacy policy](https://huggingface.co/privacy). What | |
| you say a picture shows stays in your browser: it is never sent. | |
| ## Limits | |
| Up to 25 MB and 50 megapixels a picture, and 40 at a time; the page sends them one by one, and each must arrive | |
| within a minute. JPEG, PNG and WebP are read as sent. Other formats your browser can open (such as GIF, AVIF, or | |
| HEIC in Safari) are converted by your browser first, as it shows them: transparent parts on white, at most 16 | |
| megapixels, as PNG, or as a high-quality JPEG when the PNG would be over 25 MB. SVG files are not read. The server | |
| reads two pictures at once and keeps up to 16 more waiting; one that would wait longer than 10 seconds is turned | |
| away with a request to try again in a minute. On Hugging Face's free hardware the Space sleeps when nobody has used | |
| it for a while, and the first visit after that wakes it up. | |
| ## Credits | |
| - Scanners: ZXing (Apache-2.0), zxing-cpp (Apache-2.0), OpenCV and opencv_contrib (Apache-2.0), WeChat's QR | |
| models (© THL A29 Limited, a Tencent company; Apache-2.0) from WeChatCV's | |
| [opencv_3rdparty](https://github.com/WeChatCV/opencv_3rdparty/tree/3487ef7cde71d93c6a01bb0b84aa0f22c6128f6b), | |
| fetched at build time with their licence and checked against pinned SHA-256 sums. | |
| - Server: Starlette and Uvicorn (BSD-3-Clause), NumPy (BSD-3-Clause); Java: OpenJDK 17 (GPL-2.0 with the | |
| Classpath Exception). Libraries bundled in these packages keep their own licences. | |
| - Codes on the curve: made for the measurement | |
| ([QR Scan Difficulty: synthetic codes](https://huggingface.co/datasets/devmandan/qr-scan-difficulty), CC BY 4.0), and | |
| from research datasets, each under its own terms: | |
| [BoofCV QR singles](https://huggingface.co/datasets/devmandan/boofcv-qr-singles) (Peter Abeles' BoofCV QR | |
| Code Performance Benchmark photos, published openly without an explicit licence grant), | |
| [QR-DN1.0](https://huggingface.co/datasets/devmandan/qr-dn1.0) (CC BY 4.0, Mendeley Data, | |
| doi:10.17632/t2bdr663ms.2), | |
| [syn10k](https://huggingface.co/datasets/devmandan/syn10k-huawei-barcodes) (Bodnár, Grósz and Tóth; CC BY 4.0) | |
| and [Broken QR 104](https://huggingface.co/datasets/devmandan/broken-qr-codes-104) (annotations CC BY 4.0). | |
| Pictures are cropped and resized from their datasets; to have one removed, open a discussion on its dataset page. | |
| ## Disclosures | |
| Independent work, not affiliated with or endorsed by Apple, Google, Huawei, Tencent or DENSO WAVE, nor by the | |
| open-source projects and dataset authors credited above. QR Code is a registered trademark of DENSO WAVE | |
| INCORPORATED. Apple and iPhone are trademarks of Apple Inc.; Android and Google Play of Google LLC; | |
| Huawei of Huawei Technologies Co., Ltd.; WeChat of Tencent. Other names are trademarks of their owners. | |