Напишите программу , которая принимает в полноцветный RGB изображений I , максимальное количество линий рисовать L , а минимальные м и максимальную M длину каждой строки. Выход изображения вывод , который выглядит как можно больше , как я и обращаются с использованием L или меньше прямыми линиями, все из которых имеет длину между евклидово м и М .
Каждая линия должна быть одного сплошного цвета, иметь обе конечные точки в границах O и быть нарисована с использованием алгоритма линии Брезенхэма (что большинство графических библиотек уже сделает для вас). Отдельные линии могут быть толщиной всего 1 пиксель.
Все строки, даже те, которые имеют длину 0, должны занимать как минимум один пиксель. Линии могут быть нарисованы друг на друге.
Перед рисованием любых линий вы можете инициализировать фон O любым сплошным цветом (который может зависеть от I ).
Детали
- O должен иметь те же размеры, что и я .
- L всегда будет неотрицательным целым числом. Это может быть больше , чем площадь I .
- m и M - неотрицательные числа с плавающей точкой с M > = m . Расстояние между двумя пикселями - это евклидово расстояние между их центрами. Если это расстояние меньше чем m или больше чем M , то линия между этими пикселями не допускается.
- Линии не должны быть сглажены.
- Непрозрачность и альфа не должны использоваться.
- Ваша программа не должна занимать более часа для запуска на приличном современном компьютере с изображениями с размером менее миллиона пикселей и L менее 10000.
Тестовые изображения
Вы, конечно, должны показать нам ваши наиболее точные или интересные выходные изображения (которые, я ожидаю, произойдут, когда L составляет от 5% до 25% от числа пикселей в I , а m и M составляют примерно одну десятую размера диагонали).
Вот некоторые тестовые изображения (нажмите для оригиналов). Вы также можете разместить свой собственный.
Более простые изображения:
Это конкурс популярности. Получивший наибольшее количество голосов выигрывает.
Заметки
- Может быть полезно, чтобы L было получено из процента от общего числа пикселей в I, а также из абсолютного значения. Например,
>>> imageliner I=img.png L=50% m=10 M=20
было бы то же самое, как>>> imageliner I=img.png L=32 m=10 M=20
если быimg.png
было изображение размером 8 на 8 пикселей. Нечто подобное можно сделать для м и м . Это не обязательно. - Так как линии не могут выходить за пределы, самые длинные линии возможно будут диагональная длиной I . Иметь М выше, чем это, ничего не должно сломать.
- Естественно, если m равно 0 и L больше или равно количеству пикселей в I , O может быть идентичным I, если иметь длину «строк» 0 в каждом положении пикселя. Такое поведение не требуется.
- Возможно, воспроизведение формы I является более важным, чем воспроизведение цвета. Вы можете посмотреть на обнаружение края .
источник
Ответы:
C ++ - несколько случайных строк, а затем некоторые
Сначала несколько случайных строк
Первый шаг алгоритма случайным образом генерирует линии, берет для целевого изображения среднее значение пикселей вдоль этого и затем вычисляет, будет ли сумма квадратов пространственных расстояний rgb всех пикселей меньше, если мы нарисуем новую линию (и только покрась, если есть). Цвет новых линий для этого выбирается как среднее по каналу значений rgb, со случайным добавлением -15 / + 15.
Вещи, которые я заметил и повлиял на реализацию:
Я экспериментировал с некоторыми числами, выбрал
L=0.3*pixel_count(I)
и ушел,m=10
иM=50
. Это даст хорошие результаты, начиная примерно0.25
с0.26
числа строк, но я выбрал 0.3, чтобы иметь больше места для точных деталей.Для полноразмерного изображения золотых ворот это привело к рисованию 235929 строк (для чего здесь потребовались колоссальные 13 секунд). Обратите внимание, что все изображения здесь отображаются в уменьшенном размере, и вам необходимо открыть их в новой вкладке / загрузить их, чтобы просмотреть полное разрешение.
Стереть недостойных
Следующий шаг довольно дорогой (для 235 тыс. Строк это заняло около часа, но это должно быть в пределах времени «час для 10 тыс. Строк на 1 мегапиксель»), но это также немного удивительно. Я прохожу все ранее нарисованные линии и убираю те, которые не делают изображение лучше. Это оставляет меня в этом прогоне только 97347 строк, которые производят следующее изображение:
Вам, вероятно, нужно скачать и сравнить их в соответствующем средстве просмотра изображений, чтобы определить большинство различий.
и начать все сначала
Теперь у меня есть много линий, которые я могу нарисовать снова, чтобы в общей сложности снова было 235929. Не так много, чтобы сказать, так вот изображение:
краткий анализ
Кажется, что вся процедура работает как размытый фильтр, чувствительный к локальному контрасту и размерам объектов. Но также интересно посмотреть, где нарисованы линии, поэтому программа также записывает их (для каждой строки цвет пикселя будет сделан на один шаг белее, в конце контраст будет максимальным). Вот соответствующие три цвета выше.
анимации
И так как мы все любим анимацию, вот несколько анимационных картинок всего процесса для меньшего изображения золотых ворот. Обратите внимание, что существует существенное сглаживание из-за формата gif (и поскольку создатели форматов файлов анимации истинного цвета и производители браузеров воюют из-за своего эго, стандартного формата для анимации истинного цвета не существует, в противном случае я мог бы добавить .mng или аналогичный ).
Еще немного
В соответствии с запросом приведены некоторые результаты других изображений (опять же, возможно, вам придется открыть их на новой вкладке, чтобы не уменьшать их масштаб)
Будущие мысли
Игра с кодом может дать некоторые интересные вариации.
Код
Это всего лишь две основные полезные функции, весь код здесь не помещается и может быть найден на http://ideone.com/Z2P6Ls.
Эти
bmp
классыraw
иraw_line
функции делают пиксели доступа и линии соответственно в объект , который может быть записан в формате BMP формат (Это был просто какой - то хак лежал вокруг , и я думал , что делает это несколько независимым от любой библиотеки).Формат входного файла - PPM
источник
Java - случайные строки
Очень простое решение, которое рисует случайные линии и вычисляет для них средний цвет исходного изображения. Цвет фона установлен на исходный средний цвет.
L = 5000, м = 10, М = 50
L = 10000, m = 10, M = 50
РЕДАКТИРОВАТЬ
Я добавил генетический алгоритм, который обрабатывает множество строк. В каждом поколении мы сохраняем только 50% лучших линий, отбрасываем остальные и генерируем случайно новые. Критерии для сохранения линий:
К моему большому разочарованию, алгоритм на самом деле не улучшает качество изображения :-( только линии становятся более параллельными.
Первое поколение (5000 линий)
Десятое поколение (5000 линий)
Игра с параметрами
источник
C - прямые
Основной подход в C, который работает с файлами ppm. Алгоритм пытается разместить вертикальные линии с оптимальной длиной линии, чтобы заполнить все пиксели. Цвет фона и цвета линий рассчитываются как среднее значение исходного изображения (медиана каждого цветового канала):
L = 5000, м = 10, М = 50
L = 5000, м = 10, М = 50
L = 100000, m = 10, M = 50
источник
Python 3 основан на «несколько случайных линиях, а затем и на некоторых», плюс распознавание краев.
код теоретически может работать вечно (так что я могу запустить его всю ночь для забавы), но он записывает его ход, поэтому все изображения снимаются с отметки 1-10 мин.
Сначала он читает изображение, а затем использует распознавание краев sobel, чтобы найти угол всех ребер, чтобы убедиться, что линии не пересекаются с другим цветом. Как только линия произвольной длины в пределах (lengthmin, lengthmax) установлена, она проверяет, вносит ли она вклад в общее изображение. В то время как меньшие линии лучше, я установил длину линии от 10-50.
источник