Программно изменить изображение, чтобы заменить детали текстом?
-
03-07-2019 - |
Вопрос
Как можно было бы программно воспроизвести следующий эффект?
(источник: artext.co.uk)
Я бы хотел автоматизировать процесс, если это возможно, но иметь некоторый контроль над выводом (т. Е. инвертировать цветовую палитру для создания светлого фона для темных изображений и т.д.).Получение результатов в векторном формате тоже было бы здорово, если это возможно.
Обновить: Вместо того, чтобы просто воссоздавать с помощью ASCII-art, я хотел бы также указать строку, которая используется для воссоздания изображения.
Решение
Это довольно просто:разделите изображение с помощью сетки, вычислите средний цвет (или яркость, или оттенок и т.д.) пикселей, найденных в каждой ячейке сетки, создайте изображение того же размера, нарисуйте букву, соответствующую ячейке сетки, найденным цветом.
Другие советы
Я был немного не в себе, но в конце концов немного взломал Обработка набросок для демонстрации моего алгоритма.
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);
}
}
}
Должно лучше работать с жирным (bold) моноширинным шрифтом.
Для mplayer есть два драйвера, которые решают эту проблему, один из них называется "libaa" / ascii-art, другой "libcaca".:
Исходники доступны обоим, я не помню, под какой лицензией.
Смотрите скриншоты обеих библиотек в действии:http://liquidweather.net/howto/index.php?id=74
Это даже проще, чем ответ Филхо.Просто преобразуйте текст в изображение того же размера, полностью белое на черном фоне (это может быть предварительно сгенерировано, если хотите) и умножьте это изображение "текстовой маски" на ваше исходное изображение.Размытие исходного изображения с помощью гауссова размытия, радиус которого сравним с размером текста, может быть желательным, если вы не хотите, чтобы детали размером меньше символа оставались видимыми.