¿Modificar programáticamente una imagen para reemplazar detalles con texto?

StackOverflow https://stackoverflow.com/questions/416376

  •  03-07-2019
  •  | 
  •  

Pregunta

¿Cómo se reproducirá programáticamente el siguiente efecto?


(fuente: artext.co.uk )

Me gustaría automatizar el proceso si es posible, pero tener cierto control sobre la salida (es decir, invertir la paleta de colores para producir un fondo claro para imágenes oscuras, etc.). Producir resultados en formato vectorial también sería excelente si es posible.

Actualización: En lugar de simplemente recrear con ASCII-art, también me gustaría especificar la cadena que se usa para recrear la imagen.

¿Fue útil?

Solución

Es bastante simple: divida la imagen con una cuadrícula, calcule el color promedio (o luminosidad o tono, etc.) de los píxeles encontrados en cada celda de la cuadrícula, cree una imagen del mismo tamaño, dibuje la letra correspondiente a la cuadrícula Celda con el color encontrado.

Otros consejos

Estaba un poco nervioso, pero finalmente pirateé un pequeño boceto Procesando para demostrar mi algoritmo.

final int GRID_SIZE_H = 9;
final int GRID_SIZE_V = 9;
final int GRID_SIZE = GRID_SIZE_H * GRID_SIZE_V;
final String TEXT_TO_DISPLAY = "Picture yourself in a boat on a river With tangerine trees and marmalade skies";

void setup()
{
  size(600, 600);
  smooth();
  noStroke();
  background(0);

  PImage niceImage = loadImage("SomeImage.png");
  int niW  = niceImage.width;
  int niH = niceImage.height;
  int imgW = niW + 10;
  image(niceImage, 0, 0);

  PFont f = loadFont("Arial-Black-12.vlw");
  textFont(f);
  textAlign(CENTER);
  String textToDisplay = TEXT_TO_DISPLAY.toUpperCase().replaceAll("\\s", "");

  int pos = 0;
  niceImage.loadPixels();
  for (int j = 0; j < niH - GRID_SIZE_V; j += GRID_SIZE_V)
  {
    for (int i = 0; i < niW - GRID_SIZE_H; i += GRID_SIZE_H)
    {
      long avgR = 0, avgG = 0, avgB = 0;
      for (int x = 0; x < GRID_SIZE_H; x++)
      {
        for (int y = 0; y < GRID_SIZE_V; y++)
        {
          int c = niceImage.pixels[i + x + (j + y) * niW];
          avgR += (c >> 16) & 0xFF;
          avgG += (c >>  8) & 0xFF;
          avgB +=  c        & 0xFF;
        }
      }
      color clr = color(avgR / GRID_SIZE, avgG / GRID_SIZE, avgB / GRID_SIZE);
      fill(clr);
      char chr = textToDisplay.charAt(pos++);
      pos = pos % textToDisplay.length();
      text(chr, i + imgW, j + 12);
    }
  }
}

Debería funcionar mejor con una fuente monoespaciada gruesa (en negrita).

Hay dos controladores para mplayer que abordan este problema, uno se llama BW " libaa " / ascii-art, el otro "libcaca":

Las fuentes están disponibles para ambos, no recuerdo bajo qué licencia.

Vea esto para capturas de pantalla de ambas librerías en acción: http://liquidweather.net/howto/index.php?id=74

Es incluso más simple que la respuesta de PhiLho. Simplemente renderice el texto a una imagen del mismo tamaño en todo el fondo blanco sobre negro (esto podría ser generado previamente si lo desea) y multiplique esta " máscara de texto " Imagen con su imagen de origen. Difuminar la imagen de origen con un desenfoque gaussiano cuyo radio es comparable al tamaño del texto puede ser conveniente si no desea que los detalles más pequeños que los caracteres permanezcan visibles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top