2 pontos por GN⁺ 2026-01-18 | 1 comentários | Compartilhar no WhatsApp
  • Foi desenvolvida uma técnica de renderização ASCII que preserva contornos e formas da imagem, resolvendo o problema de bordas borradas dos métodos tradicionais
  • Em vez de um mapeamento simples de brilho por pixel, ela usa uma abordagem baseada em vetores de alta dimensão que quantifica e compara a forma visual (shape) de cada caractere
  • Medindo a densidade nas regiões superior, inferior, esquerda e direita de cada caractere, gera-se um shape vector expandido de 2 para 6 dimensões, permitindo uma seleção de caracteres mais precisa
  • Para aumentar a nitidez das bordas, são aplicados algoritmos de realce de contraste global e direcional (contrast enhancement)
  • Com aceleração por GPU, cache e busca por árvore k-d, o sistema atinge desempenho de renderização ASCII em tempo real, produzindo efeitos visuais de alta qualidade

Conversão de imagem para ASCII

  • O ASCII tem 95 caracteres imprimíveis, e a imagem é dividida em uma grade usando uma fonte monoespaçada
    • O brilho de cada célula é calculado e mapeado de acordo com a densidade do caractere
  • A simples interpolação por vizinho mais próximo (nearest-neighbor interpolation) provoca o efeito de bordas serrilhadas conhecido como jaggies
  • Com supersampling, ao coletar várias amostras dentro da célula e calcular o brilho médio, o resultado fica mais suave, mas ainda surgem bordas borradas
  • O problema central está em tratar caracteres como se fossem pixels, sem considerar sua forma própria

Uso da forma (Shape) dos caracteres

  • Cada caractere tem uma distribuição visual de densidade diferente dentro da célula
    • Ex.: T é mais denso na parte superior, enquanto L é mais denso na parte inferior
  • Para quantificar isso, posiciona-se um círculo de amostragem dentro da célula e calcula-se a proporção ocupada pelo caractere em cada região
  • As proporções das regiões superior e inferior são representadas como um vetor, gerando um shape vector bidimensional
  • Os shape vectors de cada caractere são pré-calculados, e o caractere mais próximo do vetor amostrado da imagem é escolhido pela distância euclidiana (Euclidean distance)

Expansão para vetor de forma em 6 dimensões

  • Apenas as 2 dimensões superior/inferior não bastam para representar bem caracteres centrados no meio ou na esquerda/direita, como -, p e q
  • A célula é expandida para 6 círculos de amostragem, capturando superior, meio, inferior e as diferenças entre esquerda e direita
  • O shape vector em 6 dimensões reflete a forma dos caracteres com muito mais precisão e representa bem até caracteres circulares e diagonais
  • Na renderização de cenas 3D, os contornos externos ficam nítidos, mas surge o problema de bordas borradas entre superfícies

Realce de contraste (Contrast Enhancement)

  • Cada elemento do vetor amostrado é ajustado com um expoente (exponent), escurecendo mais os valores baixos e mantendo os valores altos
    • O vetor é normalizado, recebe o expoente e depois é restaurado para sua faixa original
  • Esse processo reforça a distinção visual das bordas, tornando a escolha dos caracteres mais clara
  • Em áreas de brilho uniforme, quase não há mudança, preservando gradientes suaves
  • Porém, em algumas bordas, surge o efeito de degraus (staircasing)

Realce de contraste direcional (Directional Contrast Enhancement)

  • Círculos de amostragem externos também são posicionados fora de cada célula para coletar informações de brilho ao redor
  • Valores claros no vetor de amostragem externo escurecem os elementos correspondentes do vetor interno, reforçando o contraste na direção da borda
  • Ao ampliar a amostragem externa para aumentar a influência entre topo, meio e base, torna-se possível uma representação de bordas suave e nítida
  • Quando combinado com o realce de contraste global, isso permite uma renderização ASCII de cenas 3D com contornos bem definidos e alta legibilidade

Otimização de desempenho

  • Como repetir de forma simples a busca do vizinho mais próximo na seleção de caracteres é lento, usa-se uma árvore k-d para buscas rápidas em espaço multidimensional
  • O cache permite reutilizar o resultado de vetores de amostragem idênticos
    • Cada vetor é quantizado em unidades de 5 bits para criar uma chave de cache eficiente em memória
    • Definir o intervalo como 8 mantém um equilíbrio entre qualidade e uso de memória
  • A busca em cache é extremamente rápida, e até milhares de caracteres podem ser processados em tempo real
  • O cálculo dos vetores de amostragem foi movido para a GPU, com amostragem interna e externa e operações de realce de contraste processadas no pipeline de shaders
    • Desempenho várias vezes superior ao da CPU

Conclusão

  • A abordagem que quantifica a forma dos caracteres em vetores melhora muito a resolução e a nitidez da renderização ASCII
  • O método é semelhante ao conceito de word embedding e pode ser aplicado a outros problemas visuais
  • A implementação inicial era lenta, mas, com aceleração por GPU, cache e busca por árvore k-d, passou a garantir FPS fluido até em dispositivos móveis
  • A representação ASCII baseada em cores não foi tratada, mas o texto menciona a possibilidade de experimentar no futuro combinações mais variadas de forma e contraste
  • Mais do que um simples efeito visual, a renderização ASCII mostra o potencial de expansão do reconhecimento de formas e das representações vetoriais

1 comentários

 
GN⁺ 2026-01-18
Comentários do Hacker News
  • Se você normalizar os vetores e depois calcular a distância euclidiana, dá para obter o mesmo resultado com um simples produto de matrizes (matmul)
    Isso acontece porque, com vetores normalizados, a distância euclidiana é uma transformação linear da distância cosseno
    Se o que importa é só o ranking, e não o valor exato da distância, também dá para pular a operação de sqrt e obter o mesmo resultado, com um cálculo um pouco mais rápido

    • Teria sido muito bom saber disso nos anos 90, quando eu desenvolvia engines de jogo
  • Adoro esse tipo de texto. Parece simples à primeira vista, mas para ficar realmente bom exige uma exploração profunda
    Também recomendo o texto que Lucas Pope escreveu ao desenvolver o sistema de dithering de Return of The Obra Dinn
    Diário de desenvolvimento de Lucas Pope

  • Fiquei surpreso ao ler a frase “gerei a imagem de Saturno com o ChatGPT”
    Há tantas fotos reais de Saturno em domínio público por aí; fico me perguntando por que alguém faria questão de criar uma imagem falsa para poluir a internet

    • Isso me lembrou a reportagem sobre a polêmica das ‘fotos falsas da Lua’ da Samsung. Vai ver os planetas também não são reais?
    • Não entendo por que fazer o modelo reproduzir uma imagem que provavelmente já estava incluída nos dados de treinamento
    • “Fiz uma imagem de Saturno com o ChatGPT” é só o começo
      Talvez um dia a gente nem escreva mais wikis, sites ou fóruns diretamente
      Se for possível gerar na hora uma “imagem de Saturno em alto contraste no tamanho X×Y”, isso seria uma mudança quase mágica
      Assim como calculadoras e a internet não mataram a criatividade, os humanos sempre escolhem a ferramenta com menos atrito e continuam avançando rumo às estrelas
  • Toda vez que eu via um exemplo pensava “legal, mas ainda dá para melhorar”, e fiquei impressionado porque o autor realmente resolveu isso
    É um texto belíssimo, e o blog inteiro tem esse mesmo nível de profundidade, então vale a pena assinar
    alexharri.com/blog

  • Quando criei o projeto ascii-side-of-the-moon, pensei em implementar eu mesmo um renderizador ASCII
    No fim usei o chafa, mas pretendo tentar de novo algum dia
    Fiquei curioso se há planos de lançar isso como biblioteca, ou se posso simplesmente me basear no código do site

    • Eu me diverti bastante usando a ferramenta ASCII Moon
      No momento não há plano de transformar isso em biblioteca, mas, se precisar, fique à vontade para aproveitar o código do site
      Se eu fosse fazer isso, provavelmente aumentaria a compatibilidade com uma conversão de WebGL 2 para WebGL 1, e também criaria uma ferramenta para pré-calcular os shape vectors de cada fonte
  • Sobre a frase “nunca vi um exemplo de uso de shape em arte ASCII”, na verdade existe um gerador que usa shape
    É o projeto ascii-silhouettify, que usa um algoritmo para escolher o maior caractere que se encaixa no contorno das áreas de cor

    • Os exemplos da galeria monocromática são realmente muito bonitos
    • Mas parece ser cerca de 150 vezes mais lento. Talvez, aumentando a resolução de amostragem, dê para obter uma nitidez parecida
  • Acerola tentou em 2024 um renderizador ASCII baseado em detecção de bordas
    O método sobrepunha símbolos direcionais (| / - \) sobre uma camada baseada em brilho
    Veja o vídeo relacionado

    • Parece haver bastante espaço para estilo nessa área
      Por exemplo, daria para experimentar várias abordagens, como usar contornos grossos no estilo da arte 2D tradicional ou representar contrastes suaves de luz e sombra como em Chiaroscuro
  • A maioria dos filtros ASCII não considera a forma (shape) dos glifos
    O chafa trata cada glifo como um bitmap 8×8, e achei essa abordagem impressionante
    Olhando o código-fonte do chafa e a galeria, dá para sentir o nível de refinamento

    • Não vi exemplos de renderização de texto ASCII na galeria do chafa; fiquei curioso se existem exemplos assim também
    • Na faculdade eu também usei uma abordagem de converter bitmaps 8×8 em inteiros de 64 bits e comparar com popcnt
      Fico curioso se uma abordagem mais centrada em direcionalidade conseguiria representar melhor formas maiores
    • Pessoalmente, os glifos do IBM Code Page 437 são os meus favoritos
      A lista de fontes de PCs antigos é um verdadeiro buraco sem fim
  • No meu tempo livre, estou experimentando com gráficos coloridos baseados em braille
    A resolução é suficiente, mas falta precisão na representação das cores, então depois da amostragem é preciso fazer um ajuste de contraste (contrast fixup)
    Acho que seria interessante aplicar a técnica de amostragem do autor para reforçar o contraste das cores
    Antes eu tinha tentado aumentar o contraste com um filtro de Sobel, mas não funcionou porque ele não se alinhava com a grade de caracteres

  • Foi uma abordagem técnica realmente excelente, com uma análise profunda
    No final eu esperava ver uma versão melhorada do Cognition cube array, então fiquei um pouco decepcionado por isso não aparecer
    Isso me lembrou um designer que, anos atrás, no YouTube, implementou favicons melhores com contraste de cor por subpixel
    Texto relacionado (Web Archive)

    • Eu também queria ver uma versão com contraste reforçado do logo da Cognition
      Mesmo assim, o texto em si foi excelente, e os exemplos dinâmicos foram realmente impressionantes