Os códigos QR de foto realmente funcionam? Nossos resultados de teste de decodificação
Um código QR que é uma fotografia parece que deve funcionar pior. Medimos o nosso com um decodificador real — desfocado, reduzido e lido da forma como um leitor lê.
O que há de novo aqui: Resultados de teste de decodificação para nossa própria implementação de código QR de foto, medidos com jsQR contra um código de controle simples: zero de 4.225 módulos lidos incorretamente em cada abertura de leitor de 0,10 a 0,45 módulos, tolerância de redução idêntica de 3x e tolerância de desfoque de 4-5 pixels em relação aos 6 do código simples — o custo específico e pequeno de transformar um código em uma imagem.
Um código QR que é uma fotografia parece que deve ser uma troca: bonito, mas você perde algumas leituras. Essa intuição está certa sobre a maioria das implementações e errada sobre como deve funcionar — e “algumas leituras” não é um número que ninguém publica.
Aqui estão as nossas, do conjunto de testes que tinha que passar antes de enviarmos a funcionalidade.
# O que é um código QR com foto e o que não é
Duas coisas muito diferentes recebem o mesmo nome.
Arte QR com IA — o tipo modelo de difusão — gera uma imagem condicionada a um código QR e depois espera que o resultado ainda decodifique. Às vezes funciona. O modo de falha é invisível até que alguém em um bar escuro aponte um telefone de três anos para ele.
Um código de foto pontilhado é a outra abordagem e a que é medida aqui. A imagem é reduzida a um bit — preto ou branco por subpixel — por difusão de erro, com uma restrição crucial: em cada centro do módulo a pontuação é forçada ao valor que o codificador exige, e o erro que o forçamento cria (até cerca de 95% do valor de um pixel, para um módulo branco em uma região escura) é empurrado para os subpixels vizinhos que ainda não foram limitados. A imagem é feita do espaço entre os centros dos módulos.
Essa distinção é o artigo inteiro. Significa que o código não gasta sua correção de erro em decoração: cada módulo ainda carrega o valor do codificador, então a redundância completa está intacta para rugas, brilho, um polegar sobre um canto — as coisas para as quais a correção de erro realmente existe.
# O teste
Tudo abaixo é reproduzível do nosso repositório, offline:
- Codificador: nosso próprio
packages/qr, correção de erro H, piso de densidademinVersion: 12→ versão de símbolo 12, 65 módulos de largura, 10 pixels por módulo, zona silenciosa de 4 módulos. - Estilos: halftone (uma fotografia verdadeiramente pontilhada) e mosaic (apenas os módulos são desenhados, dimensionados pela escuridão local), contra um código não pontilhado simples como controle — mesma carga útil, mesma versão, mesma escala.
- Imagens: imagens de teste procedurais, incluindo um gradiente diagonal (cada tom aparece) e cinza médio plano, que é o pior caso porque cada ponto forçado discorda de seus arredores.
- Decodificador: jsQR 1.4.0, um decodificador QR real, dado os pixels reais.
- Degradações: escala de vizinho mais próximo, desfoque de caixa seguido por re-limiar (uma câmera desfocada) e uma leitura de abertura.
O conjunto em que isso é construído é packages/qr/test/dither.test.js. Foram 39/39
passando em 2026-08-31, e um código que falha em decodificar é um teste falhando em vez
de um aviso — essa regra é por que a funcionalidade existe na forma que é. As
tabelas abaixo são impressas por draft/mostlyqr/seo/benchmarks/photo.js, que executa
os mesmos estilos pelas mesmas degradações; nada aqui foi transcrito.
# Zero módulos interpretados incorretamente, em cada abertura
A medição que mais importa não é “decodificou” mas “o leitor viu o valor correto em cada célula”, porque um código que decodifica apenas porque a correção de erro o resgatou é um código que falhará quando outra coisa der errado.
Um leitor em conformidade não amostra um pixel por módulo. Ele calcula a média de uma pequena abertura circular em cada centro do módulo e limita essa média. Então fizemos o mesmo, em raios de abertura de 0,10, 0,25, 0,36 e 0,45 módulos (0,5 seria o módulo inteiro), e contamos quantos dos 4.225 módulos seriam lidos incorretamente:
| Estilo | Módulos interpretados incorretamente, abertura 0,10 / 0,25 / 0,36 / 0,45 |
|---|---|
| código simples (controle) | 0 / 0 / 0 / 0 |
| foto de mosaico | 0 / 0 / 0 / 0 |
| foto halftone (gradiente) | 0 / 0 / 0 / 0 |
| foto halftone (cinza médio plano, pior caso) | 0 / 0 / 0 / 0 |
Nem um módulo, em nenhum estilo, em nenhuma abertura, incluindo a imagem do pior caso. O código de foto e o código simples apresentam ao leitor os mesmos valores. A correção de erro não é tocada e ainda está totalmente disponível.
# Qual é o custo: cerca de um passo de desfoque
Correção de erro não tocada não significa idêntica. A pontuação muda o que os pixels parecem entre os centros, e uma câmera muito fora de foco calcula a média desses pixels. Então empurramos cada estilo até quebrar:
| Estilo | Escala máxima de redução que ainda decodifica | Raio de desfoque máximo que ainda decodifica |
|---|---|---|
| código simples (controle) | 3× | 6 px |
| foto de mosaico | 3× | 5 px |
| foto halftone (cinza médio plano) | 3× | 6 px |
| foto halftone (gradiente) | 3× | 4 px |
A redução de escala — o código renderizado menor que o nativo — é idêntica em todos os estilos: cada um sobreviveu a 3× e cada um falhou primeiro em 4×. (A redução de escala de vizinho mais próximo não é monótona — alguns deles decodificaram novamente em 5×, onde a grade de amostragem caiu mais favoravelmente — então a figura que relatamos é a primeira falha, não o último sucesso.)
O desfoque é onde o custo aparece, e apenas para o estilo halftone no imagem mais difícil: um terço menos margem do que o controle simples. O halftone de um plano campo cinza médio correspondeu ao código simples exatamente, então este é um custo dependente de imagem em vez de uma propriedade da técnica. Em termos simples: um código de foto precisa que a câmera esteja cerca de um passo mais próxima de focada do que um código simples. Esse é um custo real e é um pequeno, e é a resposta honesta para “eles leem?” — não “sim” e não “não” mas “sim, com cerca de um passo menos tolerância de foco”.
O estilo de mosaico fica entre os dois, o que faz sentido: ele desenha apenas os módulos, então há menos tinta entre os centros para um desfoque desmantelar.
# Por que a densidade é o requisito real
A primeira versão dessa funcionalidade estava tecnicamente correta e parecia errada, por uma razão que vale a pena saber se você usar qualquer ferramenta de QR com foto:
https://mqr.sh/AB12CD com correção de erro H — que é o que um código de foto força
— codifica para uma grade de 29 módulos. São 841 células para uma fotografia inteira, e
o resultado parece ruído em vez de uma imagem: as pessoas concluem que a técnica
é quebrada quando o problema real é que não há lugar para a imagem viver.
Forçar um símbolo mais denso corrige:
| Versão mínima | Símbolo | Módulos de largura | Células disponíveis para a imagem |
|---|---|---|---|
| nenhuma (o que a carga útil precisa) | v3 | 29 | 841 |
| 8 | v8 | 49 | 2.401 |
| 12 (nosso padrão) | v12 | 65 | 4.225 |
Cinco vezes as células na versão 12. Todas as ferramentas de imagem QR sérias forçam isso para o mesmo motivo, e o piso nunca deve encolher um símbolo abaixo do que a carga útil realmente precisa — dados vencem densidade, sempre.
A consequência para impressão é direta, e é a razão pela qual este artigo fica no mesmo cluster que quantos módulos sua carga útil precisa: um código de 65 módulos precisa de 73 larguras de módulo de papel incluindo sua zona silenciosa. Em um módulo de 0,5mm são 36,5mm — então um código de foto é um cartaz, um cardápio, um painel de embalagem ou uma tela. Não é um cartão de visita.
# O que o teste não cobre
Dito claramente, porque um benchmark com limites não declarados é pior que nenhum:
- Um decodificador, pixels sintéticos. jsQR é um decodificador real mas não é uma pilha de câmera de telefone, e a entrada é saída renderizada limpa em vez de uma fotografia de algo impresso.
- Sem impressão, sem brilho, sem perspectiva, sem amassamento. Cada um desses custa margem, e custam um código de foto e um código simples diferentemente.
- Sem cor. Estes são códigos preto e branco de 1 bit.
- Nossa própria implementação. Nada aqui diz nada sobre QR de foto ou códigos QR de arte de IA de ninguém. Se eles sobrescrevem módulos e contam com a correção de erro para reparar o dano, eles se comportarão nada como isso, e o teste justo é o acima executado contra eles.
# Quando usar um
- Sim: cartazes, cardápios sob vidro, painéis de embalagem, telas, gráficos de exposição, qualquer coisa impressa grande.
- Provavelmente: uma capa de álbum, uma jaqueta de livro, um grande rótulo de produto — teste.
- Não: cartões de visita, panfletos de papel que são dobrados, qualquer coisa sob cerca de 35mm, qualquer coisa digitalizada com pouca luz à distância.
E se o que você quer não é uma fotografia inteira mas seu logo no meio de um código normal, essa é uma técnica diferente com um orçamento muito menor — medimos o tamanho que um logo pode atingir também, e a resposta é menor do que a internet pensa.
Os códigos de foto do MostlyQR são a implementação medida aqui. O mesmo núcleo de pontilhado é executado na visualização do navegador e no PNG renderizado pelo servidor, então o que você vê no construtor é o que a impressora recebe. A própria nota do construtor diz “melhor em telas e grandes impressões — um código de foto é uma leitura mais difícil em papel pequeno ou amassado”, que depois desses números parece ser a coisa certa para dizer.
Perguntas frequentes
Os códigos QR de foto funcionam com segurança?
Em nossos próprios testes, sim — com um custo mensurável. Ao ler nossos códigos de foto da maneira que um leitor compatível faz, fazendo a média de uma abertura circular em cada centro de módulo, nenhum dos 4.225 módulos foi lido incorretamente em qualquer abertura que testamos. Eles toleraram a mesma redução de 3x como um código simples. A única diferença medida foi o desfoque, e apenas na imagem mais difícil: o controle simples sobreviveu a um raio de desfoque de 6 pixels, o estilo mosaico de 5 e o estilo meio-tom de 4 em um gradiente (6 em cinza sólido). Isso é aproximadamente um passo de foco da câmera, não uma categoria diferente de confiabilidade.
Os códigos QR artísticos usam toda a correção de erros?
Muitas implementações fazem isso, é por isso que a técnica tem uma má reputação. A nossa não. Em vez de sobrescrever módulos inteiros com dados de imagem e confiar no Reed-Solomon para reparar a diferença, força um ponto em cada centro do módulo para o valor que o codificador exige e difunde o erro resultante para os sub-pixels circundantes. A imagem é paga com o espaço entre os centros dos módulos, portanto o orçamento completo de correção de erros ainda está lá para o mundo real — para vincos, brilho e um polegar sobre o canto.
Posso imprimir um código QR de foto em um panfleto?
Nós não faríamos. Nosso próprio gerador diz "melhor em telas e impressões grandes" e falamos sério: um código de foto precisa de um símbolo denso (65 módulos de largura no teste abaixo, contra 29 para o mesmo link curto não forçado), então no tamanho do panfleto cada módulo fica muito pequeno muito rapidamente. Cartazes, menus sob vidro, painéis de embalagem e telas são os locais certos. Um panfleto de papel que é dobrado em um bolso não é.
Por que meu código QR de foto parece ruído em vez de uma imagem?
Quase sempre porque o símbolo é muito grosseiro. Um link curto na correção de erros H é codificado em uma grade de 29 módulos — 841 células, muito poucos para carregar uma imagem reconhecível, então a imagem não tem lugar para viver. Forçar um símbolo mais denso conserta: a versão 8 oferece 49 módulos e a versão 12 oferece 65 (4.225 células, cinco vezes mais), e nosso gerador usa como padrão a versão 12 para códigos de foto exatamente por esse motivo. Os dados sempre vencem, portanto uma carga útil mais longa ainda obtém um símbolo maior.
- Qual é o tamanho máximo do logotipo em um código QR? Medimos"Correção de erros de 30%" não é um orçamento de logotipo. Fizemos buracos crescentes em códigos em cada nível de EC até um decodificador real desistir e registramos onde quebrou.
- Qual é o tamanho mínimo que um código QR pode ser impresso? Os tamanhos, calculadosNão há um único tamanho mínimo para um código QR. Passamos cinco cargas úteis reais pelo nosso próprio codificador para obter as contagens de módulos e depois convertemos em milímetros.