MostlyQR

Quelle peut être la taille du logo sur un code QR ? Nous l'avons mesuré

« Correction d'erreur 30 % » n'est pas un budget de logo. Nous avons percé des trous croissants dans les codes à chaque niveau EC jusqu'à ce qu'un vrai décodeur abandonne, et avons enregistré où c'est cassé.

Max Čelar··Impression et numérisation

Quoi de neuf ici : Le plus grand patch centré qu'un code QR a toléré à chaque niveau de correction d'erreur, mesuré en perçant un trou croissant dans un vrai symbole et en le décodant avec jsQR — 4 % en L, 7 % en M, 12 % en Q, 17 % en H — plus deux résultats que personne ne publie : les dégâts dispersés cassent un code à 4 % où une tache continue survit 17 %, et le même patch sur un motif de localisation le casse à 1 %.

Chaque guide pour placer un logo sur un code QR dit la même chose : utiliser le niveau de correction d’erreur H, et se souvenir qu’il peut récupérer 30 % du code. La deuxième moitié est répétée si souvent qu’elle est devenue un cahier des charges — couvrir jusqu’à 30 % — et ce n’est pas ce que le nombre signifie.

Nous avons mesuré ce que cela signifie réellement.

# Ce que « la correction d’erreur à 30 % » signifie réellement

Un code QR ne stocke pas vos données sous forme de pixels dont vous pouvez en perdre quelques-uns. Il stocke des mots de code : des blocs de huit modules, protégés par la correction d’erreur Reed–Solomon. Le chiffre principal du niveau H décrit à peu près combien de ces mots de code peuvent être reconstruits — et une partie de cette capacité est consommée par la surcharge de l’encodage lui-même avant que vous ne touchiez à quoi que ce soit.

Deux conséquences qui importent plus que le nombre :

  • Les dégâts sont comptés par mot de code, et non par module. Endommager un module ruine le mot de code entier auquel il appartient.
  • Les motifs de recherche, les motifs de synchronisation et les informations de format ne sont pas du tout couverts par la correction d’erreur. C’est ainsi que le décodeur trouve le symbole en premier lieu, et il n’y a rien pour les reconstruire.

Donc « 30 % » est un fait sur les mathématiques et non une permission sur l’image. Voici la permission.

# Le budget du logo mesuré, par niveau

La méthode, pour que vous puissiez la réexécuter : encoder https://mqr.sh/AB12CD avec l’encodeur fourni par MostlyQR (buildMatrix, enveloppant node-qrcode du MIT), épinglé à la version de symbole 3 (29 modules) à chaque niveau de correction d’erreur pour que EC soit la seule variable. Afficher à 8 pixels par module avec la zone silencieuse complète de 4 modules. Blanchir un carré centré, en commençant par 1 % de la zone du symbole et en augmentant de 1 % à la fois, et passer les pixels à jsQR 1.4.0 après chaque étape. Le nombre enregistré est la dernière taille qui a décodé avant le premier échec.

Correction d’erreur Plus grand patch blanc centré qui a encore été décodé
L 4 % de la zone du symbole
M 7 %
Q 12 %
H 17 %

Le niveau H vaut à peu près quatre fois le niveau L — une différence réelle, et c’est la raison pour laquelle chaque guide vous dit de l’utiliser. C’est aussi loin de 30 %.

À titre indicatif à partir de ces chiffres : au niveau H, un logo centré occupant environ 15 % de la zone du code — un carré d’environ 39 % de la largeur du code — se situe à l’intérieur de la limite mesurée avec un peu de marge. La limite mesurée au niveau M est de 7 %, ce qui est un carré d’environ 26 % de la largeur, donc appliquez la même réduction et vous vous retrouvez à environ un cinquième.

Nous avons réexécuté l’ensemble à 16 pixels par module et nous avons obtenu des résultats identiques, ce qui est le résultat attendu : c’est une propriété du symbole, et non du rendu.

# Pourquoi une tache est moins chère que des confettis

Voici le résultat que nous n’attendions pas, et c’est celui qui explique pourquoi les logos centrés fonctionnent du tout.

Au lieu d’un seul patch contigu, nous avons inversé des modules de données individuels au hasard sur le symbole — en laissant chaque motif de recherche, de synchronisation et d’alignement intact — et nous avons augmenté la fréquence jusqu’à l’échec du décodage. Même charge utile, même version, même décodeur, cinq graines aléatoires différentes :

Correction d’erreur Dégâts maximum dispersés (médiane de 5 exécutions)
L 1 % des 567 modules de données
M 3 %
Q 3 %
H 4 %

(Le symbole v3 a 841 modules, dont 567 portent des données ; les autres sont des motifs de recherche, de synchronisation, d’alignement et de format, que ce test a laissés intacts.)

Quatre pour cent dispersés, contre dix-sept pour cent dans une seule tache, au même niveau.

La raison en est le mot de code. Un carré contigu de 17 % ruine complètement un petit nombre de mots de code. La même quantité de dégâts saupoudrée régulièrement ruine une partie de nombreux mots de code — et un mot de code avec un mauvais module est exactement aussi cassé qu’un mot de code avec huit. La correction d’erreur compte les pertes, pas les dégâts.

Ce qui inverse l’instinct habituel. Une seule forme propre à un endroit est le moyen le moins cher de dépenser votre correction d’erreur. Les taches, une texture, un filigrane semi-transparent ou un filtre photo sur tout le code coûtent le plus cher, même quand cela semble être moins de dégâts.

# Les trois coins que vous ne devez pas couvrir

Même test, même carré grandissant, déplacé à deux autres positions :

Position du patch Point de rupture du niveau H
centre 17 %
coin inférieur droit (sur le motif d’alignement) 5 %
coin supérieur gauche (sur un motif de recherche) 1 %

Au niveau L, le cas du coin supérieur gauche a échoué à la toute première étape — moins de 1 %.

Ces coins sont la structure, pas le contenu. Les trois grands carrés concentriques sont les motifs de recherche, et le plus petit encastré près du coin inférieur droit est un motif d’alignement ; entre eux, le décodeur détermine où se trouve le symbole, sa taille et son inclinaison ou déformation. Couvrez-en un et il n’y a pas d’étape de décodage pour y arriver. Le niveau de correction d’erreur ne fait presque aucune différence, car la correction d’erreur ne les protégeait jamais.

C’est pourquoi l’endroit sûr pour un logo est le milieu, et pourquoi « rendez-le simplement plus petit et placez-le dans un coin » est précisément l’inverse.

# Ce qu’une caméra ajoute que ce test ne fait pas

Tout ce qui précède est un cas propre, synthétique, dans le meilleur des cas :

  • Un seul décodeur. jsQR est un bon décodeur largement utilisé, mais la pile de caméra d’un téléphone n’est pas jsQR. Les vrais lecteurs varient dans l’agressivité avec laquelle ils tentent de décoder un code endommagé.
  • Pixels parfaits. Pas de flou, pas d’éblouissement, pas de perspective, pas d’impression. Chacun d’eux réduit le budget.
  • Un trou blanc propre. Un vrai logo a de la couleur, des bords et de l’anticrénelage contre les modules en dessous. La plaque blanche derrière un logo n’est pas une décoration — c’est ce qui rend la zone couverte sans ambiguïté.

Considérez le tableau comme une limite supérieure mesurée dans des conditions idéales, et non comme une cible à concevoir jusqu’à. Notre propre conseil est de dépenser environ les deux tiers de celui-ci.

# Réexécuter cela vous-même

Chaque nombre ci-dessus est imprimé par un script plutôt que tapé dans l’article : draft/mostlyqr/seo/benchmarks/logo.js dans notre référentiel. Il rend le symbole à chaque niveau, augmente chaque patch d’un pour cent à la fois, exécute la comparaison des dégâts dispersés sur cinq graines, et réexécute le tout à une deuxième échelle de pixels. Il sonde également notre propre validateur pour la limite citée à la fin de cet article.

# Ce qu’il faut vraiment faire

  1. Utilisez le niveau de correction d’erreur H quand il y a un logo. Cela multiplie à peu près par quatre votre budget, et cela coûte environ quatre modules supplémentaires par côté sur un lien court — ce qui est une décision de taille que vous pouvez calculer plutôt que de deviner.
  2. Gardez le logo centré, et gardez-le sous environ 15 % de la zone du code. C’est un carré d’environ 39 % de la largeur du code, au niveau H.
  3. Placez-le sur une plaque solide, pour que la zone couverte soit propre plutôt qu’ambiguë.
  4. Ne laissez rien toucher les trois carrés de coin — pas le logo, pas un cadre, pas un recadrage aux coins arrondis.
  5. Testez l’impression réelle avec un mauvais téléphone. Chaque nombre ici indique quels designs valent la peine d’être testés. Seul le test indique si cela fonctionne.

Si vous voulez que l’image soit le code entier plutôt qu’un patch au milieu, c’est une technique différente avec un budget différent — nous avons mesuré les codes QR photo séparément, et il s’avère qu’ils ne dépensent aucune correction d’erreur du tout. Et si vous voulez simplement un code avec votre logo dessus, le générateur de MostlyQR force la correction d’erreur jusqu’au niveau H dès qu’un logo est ajouté, maintient la zone silencieuse de 4 modules, et définit par défaut le logo à 22 % de la largeur du code — 4,8 % de sa zone, confortablement à l’intérieur de tout ce qui a été mesuré ci-dessus.

Une note honnête sur notre propre code, puisque nous publions les chiffres : la protection qui refuse un logo surdimensionné utilise la figure nominale de 30 % de récupération avec une réduction de 15 %, donc elle acceptera un logo couvrant environ 25 % de la zone au niveau H. Notre mesure indique que le plafond réel est plus proche de 17 %. La valeur par défaut que personne ne change est sûre avec une large marge, mais la limite est plus lâche que ce que les preuves le justifient, et c’est un bug dans notre validateur plutôt qu’une subtilité des codes QR, et c’est sur la liste des corrections.

Questions fréquemment posées

Un logo peut-il couvrir 30 % d'un code QR ?

Non. Le « 30 % » au niveau de correction d'erreur H fait référence aux mots de code — des blocs de huit modules que Reed-Solomon peut reconstruire — et une partie de ce budget est déjà dépensée dans l'encodage lui-même, non pas réservée pour vous. Dans notre test, le plus grand carré centré que nous pourrions blanchir d'un code de niveau H et toujours décoder était 17 % de la zone du symbole. Au niveau L c'était 4 %. Considérez 30 % comme une description mathématique, pas comme un budget de conception.

Quel niveau de correction d'erreur dois-je utiliser pour un code QR avec un logo ?

H, si vous pouvez vous permettre la taille. Dans notre mesure, il a à peu près quadruplé le patch toléré centré par rapport au niveau L (17 % contre 4 %) au prix de quatre modules supplémentaires par côté sur un lien court. La seule réserve est que la correction d'erreur et une petite taille imprimée concurrencent le même budget — un code de niveau H avec un logo doit être imprimé plus grand, pas plus petit.

Pourquoi mon code QR cesse-t-il de fonctionner quand je couvre un coin ?

Parce que les coins ne sont pas des données. Les trois grands carrés sont des motifs de localisation, le plus petit carré près du bas-droit est un motif d'alignement, et les deux sont comment un lecteur localise et redresse le symbole avant de décoder quoi que ce soit. Ils ne sont pas protégés par la correction d'erreur — il n'y a rien à partir de quoi les reconstruire. Dans notre test, un patch sur un motif de localisation a cassé le décodage à 1 % de la zone du symbole, contre 17 % au milieu.

Un logo sur un code QR a-t-il besoin d'une bordure blanche ?

En pratique oui, et nos chiffres en supposent un. Nous avons testé en blanchissant un carré, ce qui est le meilleur cas : un trou propre et à haut contraste avec des bords nets que le décodeur peut traiter comme uniformément clair. Un logo placé directement sur les modules sans plaque derrière produit des modules ambigus semi-sombres autour de son bord, ce qui coûte plus que la même zone de blanc propre.

Sources
  1. jsQR — the decoder used in the test
  2. node-qrcode (the MIT encoder our matrix builder wraps)
  3. QR Code standardization (ISO/IEC 18004) — Denso Wave
Plus sur ce sujet