Como o Escaneamento de QR Code Funciona Tecnicamente
Como o escaneamento de QR code funciona tecnicamente: captura de imagem, binarização, finder patterns, correção de erros Reed-Solomon e o pipeline de 8 etapas.

Este artigo foi escrito pela equipe da QR Nova. Desenvolvemos software de codigos QR, o que pode influenciar nossa perspectiva.
Seu celular decodifica um QR code em menos de 100 milissegundos. Nesse tempo, captura um quadro de vídeo, converte uma fotografia em gradiente numa grade binária, localiza três alvos nos cantos usando uma proporção que funciona em qualquer ângulo, corrige a distorção de perspectiva, amostra de 441 a 31.329 células individuais, executa aritmética polinomial sobre um campo finito para recuperar bytes corrompidos, e entrega uma URL ou string de texto. Tudo antes de você ter conscientemente registrado que apontou a câmera. A maioria dos textos explicativos para em "seu celular lê o padrão." Este aqui percorre cada etapa de como o escaneamento de QR code funciona tecnicamente, do fóton bruto ao payload decodificado, seguindo o pipeline definido na ISO/IEC 18004.
Resumo rápido
- O pipeline tem oito etapas distintas: captura de imagem, binarização, detecção de finder patterns, correção de perspectiva, amostragem de grade, decodificação de formato, extração de dados e correção de erros Reed-Solomon.
- Finder patterns, os três quadrados nos cantos, são o que torna QR codes escaneáveis em ângulos. A proporção 1:1:3:1:1 é a chave.
- A correção de erros Reed-Solomon funciona tratando dados como um polinômio sobre GF(256). No nível H, até 30% das codewords podem ser corrompidas e totalmente recuperadas.
- Falhas de contraste e zonas silenciosas ausentes são as duas causas físicas mais comuns de falha de escaneamento, ambas afetam etapas que rodam antes de a correção de erros poder ajudar.
- A computação real leva menos de 30ms. O atraso que você percebe é o autofoco da câmera, não o decodificador.
Etapa 1: captura de imagem e binarização
Generate your first QR code — free
ComecarUma câmera de celular não vê módulos preto e branco. Captura um gradiente de luminância contínuo: dados de quadro JPEG ou raw onde cada pixel tem um valor de 0 a 255. O primeiro trabalho do decodificador é converter essa imagem em tons de cinza numa imagem verdadeiramente binária. Todo pixel se torna 0 (módulo escuro) ou 1 (módulo claro). Sem meio-termo.
A abordagem ingênua é escolher um limiar global de 128 e chamar tudo mais escuro de "preto." Isso falha no momento em que um QR code é impresso numa superfície levemente reflexiva, escaneado sob luz irregular, ou colocado perto de uma janela clara. A parte do código na sombra pode ter média em torno de 60 enquanto a parte iluminada fica em torno de 180; um único limiar global classifica errado uma delas.
Decodificadores de produção usam limiarização adaptativa (local). A imagem é dividida numa grade de pequenos blocos (ZXing usa tamanho de bloco de aproximadamente 1/8 da largura da imagem). Para cada bloco, um limiar local é calculado a partir do histograma de luminância apenas daquela região. Um pixel conta como escuro se seu valor cai suficientemente abaixo da média local, tipicamente por um delta de 5 a 10. Então uma sombra sobre o canto superior esquerdo do código não afeta o limiar aplicado ao canto inferior direito.
O que sai é um bitmap binário onde cada célula do QR code é representada como preto sólido ou branco sólido, assumindo que o contraste original era adequado. É por isso que contraste não é uma preocupação cosmética. Baixo contraste produz valores de pixel ambíguos que a limiarização adaptativa não consegue classificar de forma confiável. Um QR code azul-marinho escuro sobre fundo cinza escuro? Morto na etapa 1, antes de qualquer outro passo rodar.
Etapa 2: encontrando os finder patterns
Com a imagem binária pronta, o decodificador precisa localizar o QR code dentro dela. As âncoras são os três finder patterns: os grandes quadrados concêntricos nos cantos superior esquerdo, superior direito e inferior esquerdo de todo QR code.
Cada finder pattern tem uma estrutura específica: um centro quadrado escuro 3x3, cercado por uma borda clara de 1 módulo de largura, cercada por uma borda escura de 1 módulo. Varra qualquer linha horizontal ou vertical pelo centro e a sequência de comprimentos de corrida de pixels escuros e claros produz a proporção 1:1:3:1:1. Um escuro, um claro, três escuros, um claro, um escuro.
O decodificador explora isso varrendo cada linha da imagem binária da esquerda para a direita, contando corridas de pixels da mesma cor. Toda vez que cinco corridas consecutivas aparecem, verifica se seus comprimentos satisfazem a proporção 1:1:3:1:1 (dentro de uma tolerância de cerca de 0,5x). Pontos centrais candidatos são registrados. Depois a mesma varredura roda verticalmente pela coluna de cada candidato, confirmando que a proporção se mantém em ambas as direções. Onde confirmações horizontal e vertical se cruzam, você tem um centro de finder pattern de alta confiança.
O que torna isso inteligente: a proporção é invariante a escala e rotação. Quer o QR code tenha 50 ou 500 pixels de largura, esteja rotacionado 45 graus, a proporção se mantém. A geometria do finder pattern codifica orientação, não os módulos de dados. Localize três deles e você sabe imediatamente a posição, escala e rotação do código na imagem.
A zona silenciosa (a borda branca obrigatória de 4 módulos ao redor do código) existe para servir essa etapa. Sem ela, a varredura 1:1:3:1:1 gera falsos positivos de elementos escuros do fundo adjacentes ao finder pattern, ou o cálculo da caixa delimitadora para a extensão do código fica impreciso. Zonas silenciosas ausentes são uma das fontes mais comuns de falhas intermitentes em códigos que parecem perfeitamente normais a olho nu.
Etapa 3: correção de perspectiva
Câmeras raramente encaram um QR code de frente. O código está inclinado, enviesado, ou fotografado de um ângulo que faz um padrão quadrado parecer um trapézio. Ler posições de módulos de uma imagem distorcida produz valores errados, então o decodificador reverte a distorção primeiro.
Com os centros dos três finder patterns conhecidos, mais o alignment pattern (presente em versões 2+) ou o quarto canto inferido, o decodificador tem quatro pontos conhecidos na imagem distorcida que correspondem a quatro posições conhecidas numa grade ideal, frontal. Problema clássico de homografia: encontrar a matriz de transformação perspectiva 3x3 que mapeia as coordenadas distorcidas para a grade canônica.
A homografia é computada usando transformação linear direta (DLT) ou solver similar. Uma vez conhecida, a posição canônica do centro de cada módulo mapeia de volta para uma coordenada de pixel na imagem original, dizendo ao decodificador exatamente qual pixel amostrar para cada célula da grade. A maioria das implementações faz isso de forma lazy: computa a transformação uma vez, depois amostra cada módulo sob demanda em vez de deformar a imagem inteira.
Para QR codes de versão mais alta (versão 7 e acima, que podem ter regiões de dados densas cobrindo uma grande área física), a variação local de perspectiva pela área do código se torna significativa. Alignment patterns, pequenos quadrados concêntricos embutidos na área de dados em intervalos regulares, servem como âncoras de calibração adicionais. O decodificador amostra centros de alignment patterns e os usa para refinar o modelo de perspectiva localmente, dividindo o código em regiões menores cada uma com sua própria grade de amostragem corrigida.
Etapa 4: amostragem da grade
Após a correção de perspectiva, o decodificador sabe onde o centro de cada módulo está na imagem original. A amostragem é direta: para cada célula na grade do QR code, leia o valor do pixel na coordenada mapeada e classifique como preto ou branco.
Vale entender: essa amostragem reutiliza o limiar adaptativo já computado para aquela região da imagem, não um novo limiar global. O decodificador tem trabalhado no espaço binário desde a etapa um. Agora está apenas recuperando valores em coordenadas específicas.
O resultado é uma grade booleana 2D, uma matriz NxN de valores escuros e claros onde N varia de 21 (versão 1) a 177 (versão 40). A maior parte são dados, mas certas regiões têm significados fixos: os próprios finder patterns, timing patterns (faixas alternadas preto-branco que calibram o espaçamento da grade), o módulo escuro (sempre escuro numa posição fixa) e alignment patterns. O decodificador mascara essas áreas estruturais e foca em todo o resto.
Etapa 5: lendo informação de formato e versão
Antes de extrair qualquer dado, o decodificador precisa de duas informações estruturais: a informação de formato e, para códigos versão 7+, a informação de versão.
A informação de formato mora em duas cópias idênticas em posições fixas adjacentes aos finder patterns. Codifica 15 bits: 2 para o nível de correção de erros (L, M, Q ou H), 3 para o padrão de máscara dos dados, e 10 bits de correção de erros BCH que protegem a própria informação de formato contra até 3 erros de bit. Esses bits sofrem XOR com um padrão de máscara fixo (101010000010010) antes do armazenamento para que nunca sejam todos zero, mesmo para combinações desfavoráveis.
O padrão de máscara é crítico. Dados brutos de QR frequentemente têm longas corridas de módulos da mesma cor, e a etapa de binarização interpreta erroneamente essas como artefatos de borda. Durante a codificação, um dos oito padrões de máscara XOR predefinidos é aplicado aos módulos de dados para quebrar essas corridas. O codificador avalia todas as oito máscaras e escolhe a que produz o padrão mais equilibrado e de alto contraste por uma pontuação de penalidade. Sem saber qual máscara foi aplicada, o decodificador não consegue desfazê-la, e os bits de dados são lixo.
Errar a informação de formato é fatal. Ambas as cópias corrompidas além da capacidade de correção BCH? O decodificador não consegue determinar o padrão de máscara e não consegue desembaralhar nada. Um adesivo ou arranhão cobrindo o canto adjacente a um finder pattern é muito mais danoso do que destruição equivalente em qualquer outro lugar do código.
Etapa 6: extraindo as codewords de dados
Com a máscara conhecida, o decodificador aplica XOR de volta sobre a região de dados, restaurando os bits originais codificados. Os dados são lidos numa ordem específica de zigue-zague: começando do canto inferior direito, duas colunas por vez, lendo para cima e depois para baixo num caminho serpentino alternado, pulando regiões estruturais fixas. Cada módulo de dados é visitado exatamente uma vez.
O fluxo de bits é agrupado em codewords de 8 bits. Os primeiros bits especificam o modo de codificação: numérico (10 bits por três dígitos), alfanumérico (11 bits por dois caracteres), byte (8 bits por caractere) ou Kanji (13 bits por caractere). Um campo de contagem de caracteres vem em seguida, depois os dados codificados, uma sequência terminadora e preenchimento para completar a capacidade restante.
Após as codewords de dados vêm as codewords de correção de erros, computadas durante a codificação por Reed-Solomon e adicionadas em blocos definidos. A próxima etapa as usa para verificar e reparar os dados.
Etapa 7: correção de erros reed-solomon
Essa é a etapa que faz QR codes sobreviverem a danos físicos. Requer um pouco de aritmética de campo finito, mas o conceito é acessível sem provas completas.
A base do campo finito
Reed-Solomon opera sobre GF(256), um Campo de Galois com 256 elementos. Pense nele como um sistema numérico onde todo valor é um único byte (0-255), mas as regras aritméticas diferem da matemática inteira comum. Adição é simplesmente XOR. Sem carries, totalmente reversível. Multiplicação é definida por um polinômio primitivo; em QR codes, o campo usa x^8 + x^4 + x^3 + x^2 + 1. Todo elemento diferente de zero do GF(256) pode ser expresso como potência de uma raiz primitiva alpha, o que simplifica multiplicação para adição de expoentes módulo 255.
Por que usar um campo finito? Na aritmética comum, dividir polinômios produz frações. Sobre um campo finito, todo elemento diferente de zero tem um inverso multiplicativo, então a divisão de polinômios sempre produz quocientes e restos exatos dentro do campo. Essa propriedade é o que faz todo o esquema de correção de erros funcionar.
Codificação: adicionando bytes de verificação
Durante a criação do QR code, os bytes de dados são tratados como coeficientes de um polinômio D(x). Multiplique por x^r (deslocando r posições para a esquerda, onde r é o número de codewords de correção de erros), depois divida por um polinômio gerador G(x) usando divisão longa de polinômios sobre GF(256). O resto dessa divisão, r bytes, é adicionado aos dados como as codewords de correção de erros.
O polinômio gerador para r bytes de verificação é o produto de r fatores lineares: G(x) = (x - alpha^0)(x - alpha^1)...(x - alpha^(r-1)) onde alpha é o elemento primitivo do GF(256). Para QR nível H com 28 codewords de correção de erros por bloco, G(x) tem 28 raízes.
Decodificação: calculando síndromes
No seu celular, o decodificador trata a sequência de codewords recebida (dados mais bytes de correção de erros) como um polinômio R(x). Se nada deu errado, R(x) se divide uniformemente por G(x) e o resto é zero. Se erros entraram, R(x) = C(x) + E(x) onde C(x) é o polinômio correto de codewords e E(x) é um polinômio de erros com coeficientes diferentes de zero nas posições corrompidas.
O decodificador avalia R(x) em cada uma das r raízes do gerador: S_i = R(alpha^i) para i de 0 a r-1. Esses r valores são as síndromes. Todos zeros significa mensagem limpa. Qualquer síndrome diferente de zero significa que existem erros.
Localizando e corrigindo erros
Dados os valores de síndrome, o decodificador executa o algoritmo Berlekamp-Massey para encontrar o polinômio localizador de erros, cujas raízes correspondem às posições dos bytes corrompidos. Encontrar essas raízes (avaliando o polinômio em todos os 255 elementos não-zero do campo, um processo chamado busca de Chien) dá as localizações dos erros. Então o algoritmo de Forney calcula as magnitudes dos erros em cada localização: quanto aplicar de XOR em cada byte corrompido para restaurar o valor correto.
Para erasures (posições onde o decodificador sabe que um byte não é confiável, como um módulo que ficou abaixo de um limiar de confiança durante a amostragem), a capacidade de correção dobra. Um código com r bytes de verificação corrige t erros onde t = r/2. Se k posições de erasure já são conhecidas, ele lida com até r - k erros desconhecidos adicionais além disso. QR nível H com 28 bytes de verificação por bloco corrige 14 erros desconhecidos ou 28 erasures conhecidos por bloco, ou qualquer combinação entre os dois.
O que isso significa na prática
Um QR code versão 1-Q tem 13 codewords de dados e 13 codewords de correção de erros por bloco. Destrua 6 dessas codewords de dados completamente (um arranhão que apaga aproximadamente 46% da região de dados) e todos os 13 bytes originais ainda são recuperáveis. É por isso que logos embutidos em QR codes funcionam: os módulos centrais são intencionalmente corrompidos, e a correção de erros absorve a perda.
O limite é real, porém. Exceda a capacidade de correção e o decodificador produz uma saída errada (raro, porque a verificação final detecta a maioria das falhas) ou não retorna nada. Decodificadores de produção lidam com casos extremos verificando ambas as cópias da informação de formato e tentando novamente com limiares ligeiramente variados. O ZXing, por exemplo, tenta novamente com parâmetros de binarização progressivamente mais grossos antes de desistir.
Etapa 8: remontando a mensagem
Após Reed-Solomon, o decodificador tem uma sequência de bytes verificada. O passo final desempacota de acordo com o modo e campos de contagem de caracteres lidos na etapa 6.
Para modo byte (o mais comum para URLs), cada codeword de 8 bits mapeia diretamente para um byte Latin-1 ou UTF-8. Leia a contagem de caracteres, pegue essa quantidade de bytes do payload, produza a string final. Modo numérico mapeia grupos de 10 bits para números decimais de três dígitos; modo alfanumérico mapeia grupos de 11 bits para pares de dois caracteres de um alfabeto de 45 caracteres. Você pode até concatenar múltiplos segmentos com modos diferentes num único QR code. Uma URL com apenas caracteres alfanuméricos seguida de um payload binário é perfeitamente válida.
A string de saída é o que seu celular mostra: uma URL, um número de telefone, uma mensagem de texto simples, um bloco de credenciais Wi-Fi. Nesse ponto o trabalho do scanner acabou e o sistema operacional assume. Seguir a URL, discar o número, solicitar conexão Wi-Fi.
Por que o design do pipeline importa para qualidade do código
Conhecer o pipeline muda como você deve pensar sobre design de QR code. Cada etapa tem consequências práticas.
- Binarização significa que relação de contraste não é opcional. Você precisa de pelo menos 40% de diferença de luminância entre módulo e fundo para escaneamento confiável entre dispositivos. Códigos escuro-sobre-escuro ou claro-sobre-claro falham na etapa 1 independente do nível de correção de erros.
- Detecção de finder patterns significa que zonas silenciosas são estruturais, não cosméticas. Códigos que sangram até a borda de uma área impressa sem margem falham na etapa 2.
- Sensibilidade da informação de formato significa que os cantos adjacentes aos finder patterns devem ser protegidos de danos e obstruções. Mesmo correção de erros nível H não ajuda aqui, porque a informação de formato é decodificada antes de o nível de correção de erros ser conhecido.
- Capacidade Reed-Solomon significa que tolerância a danos é previsível e quantificável. Para um código exibido ao ar livre ou impresso num ambiente de alto desgaste, escolher nível Q ou H e dimensionar generosamente dá resiliência real, não uma promessa vaga de que "QR codes aguentam danos."
O gerador da QR Nova permite definir o nível de correção de erros antes de criar um código, porque a escolha certa depende inteiramente de onde o código vai estar. Um código exibido em tela num ambiente controlado fica bem no nível M. Um adesivo de vinil que deve durar três anos em equipamento externo justifica nível H, mesmo ao custo de um código mais denso e de versão mais alta.
A velocidade real detalhada
No hardware atual de smartphones (testado em iPhones e Androids top de linha 2024-2025), veja como o pipeline de decodificação se divide por quadro de vídeo:
- Conversão para escala de cinza e binarização: 2-5ms (otimizado com SIMD em bibliotecas nativas)
- Varredura de finder patterns: 3-8ms (linear na altura da imagem)
- Correção de perspectiva e amostragem de grade: 1-3ms
- Decodificação de formato + Reed-Solomon: menos de 1ms para códigos versão 1-10
Pipeline total: bem abaixo de 30ms num único quadro. A 30fps o decodificador tem 33ms por quadro; a 60fps, 16ms. De qualquer forma, a computação não é o gargalo. Aqueles 0,5 a 2 segundos que você experimenta ao escanear é quase inteiramente óptico: autofoco estabilizando, motion blur de mão instável, e o tempo que o código passa parcialmente fora do quadro antes de você centralizá-lo.
Isso também explica algo que irrita as pessoas: escanear um QR code numa tela às vezes é mais difícil do que escanear um impresso. Telas com brilho alto introduzem reflexo que a etapa de binarização trata como um halo claro ao redor de módulos escuros, encolhendo o tamanho efetivo do módulo abaixo do que o amostrador de grade espera. Reduzir levemente o brilho da tela ao exibir um QR code não é superstição. Remove um artefato genuíno de binarização.
Conclusão
Aquela decodificação de cem milissegundos são oito etapas computacionais distintas trabalhando em sequência, cada uma dependente da anterior. Binarização converte óptica em dados. Finder patterns fornecem invariância de orientação. Correção de perspectiva mapeia uma captura distorcida do mundo real para uma grade canônica. Informação de formato destrava a máscara. Aritmética Reed-Solomon sobre GF(256) recupera bytes corrompidos com certeza matemática, até um limite definido.
Uma vez que você entende o pipeline, falhas de QR code param de ser misteriosas. Um código que escaneia de forma inconsistente quase nunca está "quebrado." Está batendo numa fronteira de etapa específica: contraste muito baixo para binarização, zona silenciosa muito estreita para detecção de finder, região de formato danificada antes de a correção de erros poder entrar em ação. Diagnostique a etapa e você diagnostica a correção.
Se você está gerando códigos para uso em produção, combine o nível de correção de erros com onde o código vai estar, mantenha a zona silenciosa intacta, e verifique o contraste programaticamente, não apenas visualmente. A matemática cuida do resto.
Perguntas frequentes
Como o escaneamento de QR code funciona tecnicamente, passo a passo?
O escaneamento de QR code funciona tecnicamente em oito etapas: o leitor captura uma imagem, converte para preto e branco através de limiarização adaptativa, localiza os três finder patterns nos cantos, corrige a distorção de perspectiva usando uma transformação homográfica, amostra cada módulo na grade, lê a informação de formato para determinar o nível de correção de erros e padrão de máscara, extrai as codewords codificadas, e então executa correção de erros Reed-Solomon para recuperar bytes corrompidos antes de finalmente decodificar o payload de dados em texto ou URL.
O que são finder patterns num QR code e por que importam?
Finder patterns são os três grandes alvos quadrados nos cantos superior esquerdo, superior direito e inferior esquerdo de todo QR code. Cada um tem uma proporção escuro-claro de 1:1:3:1:1 em qualquer linha de varredura pelo centro. Como essa proporção é invariante independente da escala ou rotação, um decodificador pode localizar e orientar um QR code mesmo quando a câmera está num ângulo acentuado ou o código está parcialmente fora do quadro. Sem finder patterns, o decodificador não teria ancoragem confiável para estabelecer a posição e orientação do código.
O que é correção de erros Reed-Solomon e como funciona em QR codes?
A correção de erros Reed-Solomon trata os bytes de dados como um polinômio e adiciona bytes de verificação computados pela divisão desse polinômio por um polinômio gerador sobre um Campo de Galois (GF(256)). Durante a decodificação, o receptor recalcula a mesma divisão. Qualquer resto diferente de zero revela que existem erros; os valores de síndrome então permitem que o decodificador localize quais bytes estão errados e compute os valores corretos, até a capacidade de correção do código. Em QR codes no nível H, até 30% das codewords podem ser corrompidas e totalmente recuperadas.
Por que o contraste do QR code importa para o escaneamento?
A etapa de binarização que converte a imagem da câmera em módulos preto e branco depende da detecção de um limite claro de luminância entre células escuras e claras. Quando o contraste é baixo, por exemplo, cinza escuro sobre preto, ou amarelo claro sobre branco, o algoritmo de limiar adaptativo pode classificar módulos com o valor errado. Um único módulo errado numa região de dados custa uma codeword; um módulo errado na região de informação de formato pode causar falha total da tentativa de decodificação antes mesmo da correção de erros entrar em ação, porque o decodificador precisa da informação de formato para saber o padrão de máscara.
Um QR code danificado ainda pode ser escaneado?
Sim, até o limite do nível de correção de erros usado. Nível L corrige até 7% das codewords, nível M até 15%, nível Q até 25% e nível H até 30%. Dano físico, borrão de tinta ou oclusão parcial que corrompe codewords dentro desses limites é totalmente recuperável. O porém é que todos os blocos de informação de formato devem permanecer legíveis, porque o decodificador usa a informação de formato para determinar o nível de correção de erros e a chave de desmascaramento antes de poder sequer tentar a recuperação de dados.
Quão rápido é o escaneamento de QR code na prática?
Num celular moderno a 60fps, o pipeline completo, binarização, busca de finder patterns, correção de perspectiva, amostragem de grade, decodificação de formato, Reed-Solomon e decodificação final, roda em menos de 30ms num único quadro de vídeo quando o código está razoavelmente bem enquadrado e iluminado. O atraso aparente que os usuários percebem é quase sempre o autofoco estabilizando, não a computação de decodificação. Bibliotecas como ZXing e ZBar são altamente otimizadas; o gargalo é óptico, não algorítmico.
O que é a zona silenciosa num QR code e por que importa?
A zona silenciosa é a margem em branco obrigatória de pelo menos quatro módulos em todos os quatro lados de um QR code. O algoritmo de detecção de finder pattern funciona procurando a proporção 1:1:3:1:1; sem a zona silenciosa, um fundo escuro pode produzir correspondências falso-positivas adjacentes aos finder patterns reais, ou fazer o cálculo da caixa delimitadora errar a extensão do código. Zona silenciosa ausente é uma das causas mais comuns de falhas intermitentes de escaneamento em códigos que parecem perfeitamente normais a olho nu.
Artigos relacionados
Arquitetura de Redirect de QR Code Dinâmico: Edge em Escala
Como funciona a arquitetura de redirect de QR code dinâmico: a cadeia do scan ao destino, latência edge, cache, failover e vendor lock-in.
ISO 18004: O Padrão de QR Code Explicado
ISO 18004 é a especificação que todo QR code segue. Saiba o que ela define: estrutura, modos de codificação, correção de erros e o sistema de versões.
Como Escanear um QR Code em Qualquer Celular
Como escanear um QR code no iPhone, Android ou PC, câmera integrada, Central de Controle, Google Lens e escaneamento de screenshot. Sem app necessário.
Generate your first QR code — free
Comecar