Рисование по номерам (используя программирование, а не числа)


56

Ваша задача - создать программу, которая берет черно-белое контурное изображение (примеры изображений ниже) и заполняет его цветом. Вы сами решаете, как разделить каждый регион и каким цветом его заполнить (вы даже можете использовать ГСЧ).

Например:

вывод для примера 1

Как вы можете видеть, я явно превосходный художник, когда дело доходит до MS Paint.


счет

Это конкурс популярности, поэтому победит ответ с наибольшим количеством голосов. Избирателям предлагается судить ответы по

  • Критерий ввода: любое изображение, состоящее из белого / светло-серого фона и черных / темно-серых контуров
  • Как хорошо окраска сделана; это означает, что мало или вообще нет областей белого цвета в отличие от вышеупомянутого (если вы явно не собираетесь использовать белый цвет, например, для облаков)
  • Настраиваемость цветов, используемых в определенных разделах
  • Насколько хорошо система работает на разных изображениях (с разной детализацией)
  • Опишите, сколько времени занимает ваша программа для каждого изображения. Возможно, мы не играем в гольф-код, но более короткий, быстрый и эффективный код следует рассматривать как лучший
  • Необходимо вывести новое изображение либо на экран, либо в файл (не более 2 МБ, чтобы его можно было отобразить в ответе)
  • Пожалуйста, объясните, почему вы выбрали вывод на этот тип изображения и прокомментируйте / объясните работу вашего кода
  • Применимость цвета, используемого для соответствующей формы, с которой он связан (реалистичная цветовая схема, т.е. трава зеленая, деревянные заборы коричневые и т. Д.)

    «Я мог бы произвольно раскрасить каждую область, но если бы я мог определить« забор »и ​​сделать его одинаково окрашенным, то это то, что заслуживает голосов». - Натан Меррил

Видя , как это является конкурс популярности, вы можете также необязательно судить по:

  • Общая привлекательность (насколько хорошо выглядит изображение)
  • Художественный талант; если вы можете программировать в оттенках или акварели и т. д.

Как правило, выигрывает самое маленькое изображение (размер файла) высочайшего качества с ускоренной программой и самым высоким публичным голосованием.

Если у вас есть другие судейские спецификации, которые, по вашему мнению, следует использовать, пожалуйста, порекомендуйте их в комментариях к этому посту.


Примеры

У меня ничего нет; Все примеры изображений имеют лицензию Creative Commons.

пример 1 в черно-белом Источник: https://pixabay.com/ro/stejar-arbore-schi%C5%A3%C4%83-natura-303890/ пример 2 в черно-белом Источник: http://www.freestockphotos.biz/stockphoto/10665 пример 3 в черно-белом Источник: http: / /crystal-rose1981.deviantart.com/art/Dragon-Tattoo-Outline-167320011 пример 4 в черно-белом Источник: http://jaclynonacloudlines.deviantart.com/art/Gryphon-Lines-PF-273195317 пример 5 в черно-белом Источник: http://captaincyprus.deviantart.com / art / Dragon-OutLine-331748686 пример 6 в черно-белом Источник: http://electric-meat.deviantart.com/art/A-Heroes-Farewell-280271639 пример 7 в черно-белом Источник: http://movillefacepalmplz.deviantart.com/art/Background-The-Pumpkin -Farm-оф-Good-старый-Days-342865938


РЕДАКТИРОВАТЬ: из-за сглаживания на линиях, которые вызывают не черные / белые пиксели и некоторые изображения, которые могут содержать серый вместо черного / белого, в качестве дополнительной проблемы вы можете попытаться справиться с этим. Это должно быть достаточно легко, на мой взгляд.


4
Всем: пожалуйста, не понижайте / не закрывайте это как «художественный конкурс» - это еще не все
edc65

16
Добро пожаловать в PPCG! Я приветствую вас за то, что вы набрались смелости, чтобы ваш первый пост был не только вызовом, и не только поп-коном, но и художественным вызовом. Удачи, я желаю вам всего наилучшего, и если вы останетесь, я думаю, вы далеко пойдете сюда.
AdmBorkBork

4
@OliverGriffin Я голосую против закрытия, а также добавил изображения, на которые вы ссылались . Вы можете удалить комментарии, если хотите.
Эддисон Крамп

2
Я наконец нашел подход, который, вероятно, не будет переполняться стеком, но теперь он работает довольно медленно.
SuperJedi224

4
Я проголосовал, чтобы вновь открыть ваш вопрос и изменил мой -1 на +1. Хорошая работа по редактированию и добавлению дополнительной информации. Кроме того, я приветствую вас за то, что вы так восприимчивы к критике сообщества. Добро пожаловать в PPCG! Надеюсь, тебе понравится.
Зак Гейтс

Ответы:


30

Спектральная аэрография (Python, PIL, scipy)

Это использует сложный математический алгоритм, чтобы произвести красочную чепуху. Алгоритм связан с алгоритмом Google PageRank, но для пикселей вместо веб-страниц.

Я выбрал этот подход, потому что думал, что в отличие от методов, основанных на заливке, он может справиться с изображениями, такими как курица и дерево, где есть формы, которые не полностью заключены в черные линии. Как вы можете видеть, это своего рода работает, хотя он также имеет тенденцию окрашивать в разных частях неба в разные цвета

Для математически мыслящих: то, что он делает, это по существу построение графа смежности пикселей в изображении, а затем поиск 25 верхних собственных векторов графа Лапласа. (За исключением того, что это не совсем так, поскольку мы включаем темные пиксели, мы просто придаем их соединениям меньший вес. Это помогает бороться с сглаживанием, а также, по-видимому, дает лучшие результаты в целом.) Найдя собственные векторы, он создает случайная линейная комбинация их, взвешенная по их обратным собственным значениям, для формирования RGB-компонентов выходного изображения.

В интересах времени вычислений, перед тем как все это сделать, изображение уменьшают, затем снова увеличивают, а затем умножают на исходное изображение. Тем не менее, он не работает быстро, на моей машине от 2 до 10 минут, в зависимости от входного изображения, хотя по какой-то причине курица заняла 17 минут.

На самом деле, возможно, можно превратить эту идею во что-то полезное, создав интерактивное приложение, в котором вы сможете контролировать цвет и интенсивность каждого из собственных векторов. Таким образом, вы можете исчезать те, которые делят небо на разные части, и исчезать в тех, которые выбирают соответствующие функции изображения. Но я не собираюсь делать это сам :)

Вот выходные изображения:

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

(Это не очень хорошо сработало на тыквах, поэтому я опускаю эту.)

И вот код:

import sys
from PIL import Image
import numpy as np
import scipy.sparse as sp
import scipy.sparse.linalg as spl
import os
import time

start_time = time.time()

filename = sys.argv[1]
img = Image.open(filename)
orig_w, orig_h = img.size

# convert to monochrome and remove any alpha channel
# (quite a few of the inputs are transparent pngs)
img = img.convert('LA')
pix = img.load()
for x in range(orig_w):
    for y in range(orig_h):
        l, a = pix[x,y]
        l = (255-a) + a*l/255
        a = 255
        pix[x,y] = l,a
img = img.convert('L')

orig_img = img.copy()

# resize to 300 pixels wide - you can get better results by increasing this,
# but it takes ages to run
orig_w, orig_h = img.size
print "original size:", str(orig_w)+ ', ' + str(orig_h)
new_w = 300
img = img.resize((new_w, orig_h*new_w/orig_w), Image.ANTIALIAS)

pix = img.load()
w, h = img.size
print "resizing to", str(w)+', '+str(h)

def coords_to_index(x, y):
    return x*h+y

def index_to_coords(i):
    return (int(i/h), i%h)

print "creating matrix"

A = sp.lil_matrix((w*h,w*h))

def setlink(p1x, p1y, p2x, p2y):
    i = coords_to_index(p1x,p1y)
    j = coords_to_index(p2x,p2y)
    ci = pix[p1x,p1y]/255.
    cj = pix[p2x,p2y]/255.
    if ci*cj > 0.9:
        c = 1
    else:
        c =  0.01
    A[i,j] = c
    return c

for x in range(w):
    for y in range(h):
        d = 0.
        if x>0:
            d += setlink(x,y,x-1,y)
        if x<w-1:
            d += setlink(x,y,x+1,y)
        if y>0:
            d += setlink(x,y,x,y-1)
        if y<h-1:
            d += setlink(x,y,x,y+1)
        i = coords_to_index(x,y)
        A[i,i] = -d

A = A.tocsr()

# the greater this number, the more details it will pick up on. But it increases
# execution time, and after a while increasing it won't make much difference
n_eigs = 25

print "finding eigenvectors (this may take a while)"
L, V = spl.eigsh(A, k=n_eigs, tol=1e-12, which='LA')

print "found eigenvalues", L

out = Image.new("RGB", (w, h), "white")
out_pix = out.load()

print "painting picutre"

V = np.real(V)
n = np.size(V,0)
R = np.zeros(n)
G = np.zeros(n)
B = np.zeros(n)

for k in range(n_eigs-1):
    weight = 1./L[k]
    R = R + V[:,k]*np.random.randn()*weight
    G = G + V[:,k]*np.random.randn()*weight
    B = B + V[:,k]*np.random.randn()*weight

R -= np.min(R)
G -= np.min(G)
B -= np.min(B)
R /= np.max(R)
G /= np.max(G)
B /= np.max(B)

for x in range(w):
    for y in range(h):
        i = coords_to_index(x,y)
        r = R[i]
        g = G[i]
        b = B[i]
        pixval = tuple(int(v*256) for v in (r,g,b))
        out_pix[x,y] = pixval

out = out.resize((orig_w, orig_h), Image.ANTIALIAS)
out_pix = out.load()
orig_pix = orig_img.load()

for x in range(orig_w):
    for y in range(orig_h):
        r,g,b = out_pix[x,y]
        i = orig_pix[x,y]/255.
        out_pix[x,y] = tuple(int(v*i) for v in (r,g,b))

fname, extension = os.path.splitext(filename)
out.save('out_' + fname + '.png')

print("completed in %s seconds" % (time.time() - start_time))

4
Это действительно круто. Вероятно, один из моих любимых до сих пор. Вы отлично справились с обработкой сглаживания и открытых областей, и кто-то наконец раскрасил Link! ( Я ждал этого: - P save set to desktop ) Интересно, что мой старый учитель английского сказал бы об этом как статичное изображение ... "Это показывает две стороны его сердца, одна сторона - мир и на другой - это боевые действия, необходимые для достижения этого мира ». Достаточно о моей любви к играм Legend of Zelda ... Это действительно позор, что так долго. Насколько большими были полученные файлы? Ps Love изображения 4 и 5
Оливер Гриффин

2
@donbright ученик третьего класса, который мог бы понять собственные векторы, был бы действительно очень умным ребенком - я не уверен, что я могу объяснить алгоритм на этом уровне. Но все же позвольте мне попробовать: представьте, что мы распечатываем изображение на жестком листе металла. Затем мы аккуратно срезаем все черные линии и заменяем их чем-то более гибким, например, эластичным. Таким образом, белые части - это металлические пластины, а черные - гибкая ткань. Затем мы вешаем все это в воздухе на веревочке, чтобы она могла свободно двигаться. Теперь, если мы постучим по металлическим пластинам, они будут вибрировать ...
Натаниэль

2
@donbright (продолжение) ... В зависимости от того, как вы попали в металлическую пластину, она будет вибрировать по-разному. Может быть, иногда только одна из металлических частей будет вибрировать, а не другие, но в других случаях (потому что они соединены упругим), удар по одной пластине приведет к движению другой. Эти разные способы вибрации называются вибрационными модами . Эта программа имитирует некоторые колебательные режимы этой металлической пластины, но вместо генерации звука она использует их для определения, какой цвет рисовать.
Натаниэль

2
@donbright Вы также можете увидеть здесь больше для визуализации вибрации металлических пластин.
Натаниэль

2
@donbright (это более техническое объяснение может также немного потерять вас, но это объяснение работает, потому что колебательные моды пластины также рассчитываются с использованием вычисления собственного вектора. Хотя возможно, что это не совсем то же вычисление, что и мой код - я не совсем уверен.)
Натаниэль

25

Python 2 + PIL тоже моя первая раскраска

import sys, random
from PIL import Image

def is_whitish(color):
    return sum(color)>500

def get_zone(image, point, mask):
    pixels = image.load()
    w, h = image.size
    s = [point]
    while s:
        x, y = current = s.pop()
        mask[current] = 255
        yield current
        s+=[(i,j) for (i,j) in [(x,y-1),(x,y+1),(x-1,y),(x+1,y)] if 0<=i<w and 0<=j<h and mask[i,j]==0 and is_whitish(pixels[i,j])]

def get_zones(image):
    pixels = I.load()
    mask = Image.new('1',image.size).load()
    w,h = image.size
    for y in range(h):
        for x in range(w):
            p = x,y
            if mask[p]==0 and is_whitish(pixels[p]):
                yield get_zone(image, p, mask)



def apply_gradient(image, mincolor, maxcolor, points):
    minx = min([x for x,y in points])
    maxx = max([x for x,y in points])
    miny = min([y for x,y in points])
    maxy = max([y for x,y in points])
    if minx == maxx or miny==maxy:
        return
    diffx, diffy = (maxx - minx), (maxy-miny)
    stepr = (maxcolor[0] - mincolor[0] * 1.0) / diffy
    stepg = (maxcolor[1] - mincolor[1] * 1.0) / diffy
    stepb = (maxcolor[2] - mincolor[2] * 1.0) / diffy
    r,g,b = mincolor
    w, h = (abs(diffx+1),abs(diffy+1))
    tmp = Image.new('RGB', (w,h))
    tmppixels = tmp.load()
    for y in range(h):
        for x in range(w):
            tmppixels[x,y] = int(r), int(g), int(b)
        r+=stepr; g+=stepg; b+=stepb
    pixels = image.load()
    minx, miny = abs(minx), abs(miny)
    for x,y in points:
        try:
        pixels[x,y] = tmppixels[x-minx, y-miny]
    except Exception, e:
            pass

def colors_seq():
   yield (0,255,255)
   c = [(255,0,0),(0,255,0),(0,0,139)]
   i=0
   while True:i%=len(c);yield c[i];i+=1

def colorize(image):
    out = image.copy()
        COLORS = colors_seq()
    counter = 0
    for z in get_zones(image):
        c1 = COLORS.next()
        c2 = (0,0,0) if counter == 0 else (255,255,255)
        if counter % 2 == 1:
            c2, c1 = c1, c2
        apply_gradient(out, c1, c2, list(z))
        counter +=1
    return out

if __name__ == '__main__':
    I = Image.open(sys.argv[-1]).convert('RGB')
    colorize(I).show()

Я сделал то же самое, что и CarpetPython, за исключением того, что я заполняю область «градиентами» и использую другой цветовой цикл.

Мои самые великолепные окраски: введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

Время вычислений на моей машине:

  • изображение 1 (китайский дракон): реальный пользователь 0m2.862s 0m2.801s sys 0m0.061s

  • изображение 2 (гриффон): реальный пользователь 0m0.991s 0m0.963s sys 0m0.029s

  • изображение 3 (единорог дракон): реальный пользователь 0m2.260s 0m2.239s sys 0m0.021s


Хорошие градиенты! Когда вы вставляете цикл for внутри цикла for, а внутри первого ничего больше нет, вам не нужно делать отступ?
Оливер Гриффин

уверен, что вы делаете! это была проблема копирования / вставки ...
Дитер

23

Python 2 и PIL: психоделические миры

Я использовал простой алгоритм для заливки каждой белой области цветом из циклической палитры. Результат очень красочный, но не очень реалистичный.

Обратите внимание, что «белые» части на этих рисунках не очень белые. Вам нужно будет также проверить оттенки серого.

Код в Python 2.7:

import sys
from PIL import Image

WHITE = 200 * 3
cs = [60, 90, 120, 150, 180]
palette = [(199,199,199)] + [(R,G,B) for R in cs for G in cs for B in cs]

def fill(p, color):
    perim = {p}
    while perim:
        p = perim.pop()
        pix[p] = color
        x,y = p
        for u,v in [(x+dx, y+dy) for dx,dy in [(-1,0), (1,0), (0,1), (0,-1)]]:
            if 0 <= u < W and 0 <= v < H and sum(pix[(u,v)]) >= WHITE:
                perim.add((u,v))

for fname in sys.argv[1:]:
    print 'Processing', fname
    im = Image.open(fname)
    W,H = im.size
    pix = im.load()
    colornum = 0
    for y in range(H):
        for x in range(W):
            if sum(pix[(x,y)]) >= WHITE:
                thiscolor = palette[colornum % len(palette)]
                fill((x,y), thiscolor)
                colornum += 1
    im.save('out_' + fname)

Пример картинки:

Красочный дракон

Тыквы на ЛСД


3
Страшно то, что цвета действительно работают. Сколько времени вам потребовалось, чтобы раскрасить каждое изображение и насколько большими были файлы?
Оливер Гриффин

1
Программа раскрашивает каждое изображение примерно за 2 секунды. Размеры выходного изображения такие же, как и у входных файлов. Размеры файлов в основном на 10-40% меньше, чем у оригиналов (возможно, из-за того, что используются разные параметры сжатия JPEG).
Логика Найт

3
Я глубоко впечатлен тем, насколько короткий код! Мне также нравится, как вы эффективно ограничиваете цвета, доступные для использования, сохраняя при этом установленный поддон. Мне действительно очень нравится, это отчасти дает грандж (это правильное слово? Я не художник).
Оливер Гриффин

@OliverGriffin, я рад, что тебе понравилось. Я стремился к палитре без ярких или темных цветов, но все еще с некоторым контрастом. Эта цветовая гамма, казалось, имела самые приятные результаты.
Логика Найт

11

Matlab

function [output_image] = m3(input_file_name)
a=imread(input_file_name);
b=im2bw(a,0.85);
c=bwlabel(b);
h=vision.BlobAnalysis;
h.MaximumCount=10000;
ar=power(double(step(h,b)),0.15);
ar=[ar(1:max(max(c))),0];
f=cat(3,mod((ar(c+(c==0))-min(ar(1:end-1)))/ ...
    (max(ar(1:end-1))-min(ar(1:end-1)))*0.9+0.8,1),c*0+1,c*0+1);
g=hsv2rgb(f);
output_image=g.*cat(3,c~=0,c~=0,c~=0);

Мы используем цветовое пространство HSV и выбираем для каждого региона оттенок в зависимости от его относительного размера между белыми регионами. Самый большой регион будет синим ( Hue = 0.7), а самый маленький регион - фиолетовым ( Hue = 0.8). Области между этими двумя размерами имеют оттенки в диапазоне 0.7 -> 1=0 -> 0.8. Оттенок диапазона линейно выбирается относительно функции area^0.15. Насыщенность и значение всегда равны 1 для каждого не черного пикселя.

Для раскраски изображения требуется менее 1 секунды.

3 картинки с закрытыми областями, где алгоритм работает прилично:

Дракон

другой дракон

может быть, другой дракон

И остальные изображения:

Дракон

другой дракон

может быть, другой дракон

На этих изображениях есть большие белые области, которые должны быть идеально окрашены несколькими цветами (эта проблема была хорошо решена в решении Натаниэля .


Хороший и короткий код для некоторых довольно согласованных по цвету результатов! Мне нравится, как вы использовали область, чтобы помочь определить оттенок. Сколько времени заняло обработка среднего изображения и почему оно не сработало на некоторых более детальных изображениях? Были ли области слишком малы?
Оливер Гриффин

1
@OliverGriffin ответил в моем посте и добавил остальные изображения.
рандома

7

Питон 3 с подушкой

Код немного длинный, чтобы включить в этот ответ, но вот суть этого .

  1. Возьмите входное изображение и, если оно имеет альфа-канал, скомпонуйте его на белом фоне. (Это необходимо, по крайней мере, для изображения цыпленка, потому что все это изображение было черным, отличалось только прозрачностью, поэтому простое удаление альфа не помогло.)
  2. Преобразовать результат в оттенки серого; мы не хотим, чтобы артефакты сжатия или сглаживания, или серые линии, которые не совсем серые, могли нас испортить.
  3. Создайте двухуровневую (черно-белую) копию результата. Оттенки серого преобразуются в черный или белый на основе настраиваемого порога среза между белым и самым темным оттенком изображения.
  4. Заполните каждую белую область изображения. Цвета выбираются случайным образом с использованием выбираемой палитры, которая учитывает расположение начальной точки для операции заливки.
  5. Заполните черные линии их цветами ближайшего соседа. Это помогает нам заново внедрить сглаживание, предотвращая окаймление каждой цветной области в зазубренный черный цвет.
  6. Возьмите серое изображение из шага 2 и создайте из него альфа-маску: самый темный цвет полностью непрозрачный, самый светлый цвет полностью прозрачный.
  7. Скомпонуйте изображение в оттенках серого на цветном изображении, начиная с шага 5, используя эту альфа-маску.

Эти последние несколько шагов, к сожалению, до сих пор не устранили более светлые «ореолы», которые видны в темных областях, но они, по крайней мере, внесли заметные изменения. Обработка изображений никогда не была моей областью изучения, поэтому, насколько я знаю, есть более успешные и более эффективные алгоритмы, чтобы делать то, что я пытался сделать здесь ... ну да ладно.

На данный момент есть только две выбираемые палитры для шага 4: чисто случайная и очень грубая «естественная», которая пытается присвоить цвета неба верхним углам, цвета травы нижним углам, коричневый (камни или дерево). ) цвета к середине каждой стороны, и различные цвета по центру. Успех был ... ограничен.


Использование:

usage: paint_by_prog.py [-h] [-p PALETTE] [-t THRESHOLD] [-f | -F] [-d]
                        FILE [FILE ...]

Paint one or more line-art images.

positional arguments:
  FILE                  one or more image filenames

optional arguments:
  -h, --help            show this help message and exit
  -p PALETTE, --palette PALETTE
                        a palette from which to choose colours; one of
                        "random" (the default) or "natural"
  -t THRESHOLD, --threshold THRESHOLD
                        the lightness threshold between outlines and paintable
                        areas (a proportion from 0 to 1)
  -f, --proper-fill     fill under black lines with proper nearest-neighbour
                        searching (slow)
  -F, ---no-proper-fill
                        fill under black lines with approximate nearest-
                        neighbour searching (fast)
  -d, --debug           output debugging information

Образцы:

paint_by_prog.py -t 0.7 Gryphon-Lines.png Цветной грифон

paint_by_prog.py Dragon-Tattoo-Outline.jpg Цветной мультяшный дракон

paint_by_prog.py -t 0.85 -p natural The-Pumpkin-Farm-of-Good-old-Days.jpg Цветная ферма

paint_by_prog.py -t 0.7 Dragon-OutLine.jpg Цветной гранж дракон

paint_by_prog.py stejar-arbore-schiţă-natura.png Цветное дерево, очень похожее на флаг

Цыпленок выглядит не очень хорошо, и мой последний результат для изображения Link не самый лучший; тот, который пришел из более ранней версии кода, был в основном бледно-желтым и имел интересную атмосферу пустыни ...


Представление:

Каждое изображение занимает пару секунд, чтобы обработать с настройками по умолчанию, что означает, что приблизительный алгоритм ближайшего соседа используется для шага 5. Истинный ближайший сосед значительно медленнее, занимая, возможно, полминуты (на самом деле я не рассчитал время).


Первое изображение выглядит фантастически, особенно этот карие глаза. Отличная работа. Я также аплодирую вам, получая зеленую траву, коричневые поля тыкв и пурпурные облака.
Оливер Гриффин

3

Ява

Случайный выбор цвета из вашего выбора паллет.

Предупреждение: Обнаружение областей в настоящее время очень медленное, если только белые области не являются необычно маленькими.

import java.awt.Color;
import java.awt.image.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.function.Supplier;

import javax.imageio.ImageIO;


public class Colorer{
    public static boolean isProbablyWhite(int x,int y){
        Color c=new Color(image.getRGB(x, y));
        if(c.getRed()<240)return false;
        if(c.getBlue()<240)return false;
        if(c.getGreen()<240)return false;
        return true;
    }
    static class Point{
        int x,y;
        public boolean equals(Object o){
            if(o instanceof Point){
                Point p=(Point)o;
                return x==p.x&&y==p.y;
            }
            return false;
        }
        public Point(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    static BufferedImage image;
    static int W,H;
    public static void check(Point p,List<Point>l1,List<Point>l2,List<Point>l3){
        if(!isProbablyWhite(p.x,p.y))return;
        if(l1.contains(p))return;
        if(l2.contains(p))return;
        if(l3.contains(p))return;
        l1.add(p);
    }
    public static void process(int x,int y,Color c){
        List<Point>plist=new LinkedList<>();
        int rgb=c.getRGB();
        plist.add(new Point(x,y));
        List<Point>l3=new LinkedList<>();
        int k=0;
        for(int i=0;i<W*H;i++){
            System.out.println(k=l3.size());
            List<Point>l2=new LinkedList<>();
            for(Point p:plist){
                int x1=p.x;
                int y1=p.y;
                if(x1>0){
                    check(new Point(x1-1,y1),l2,plist,l3);
                }
                if(y1>0){
                    check(new Point(x1,y1-1),l2,plist,l3);
                }
                if(x1<W-1){
                    check(new Point(x1+1,y1),l2,plist,l3);
                }
                if(y1<H-1){
                    check(new Point(x1,y1+1),l2,plist,l3);
                }
            }
            while(!plist.isEmpty()){
                l3.add(plist.remove(0));
            }
            if(l3.size()==k)break;
            plist=l2;
        }
        plist=l3;
        for(Point p:plist){
            image.setRGB(p.x,p.y,rgb);
        }
    }
    public static void main(String[]args) throws Exception{
        Random rand=new Random();
        List<Supplier<Color>>colgen=new ArrayList<>();
        colgen.add(()->{return new Color(rand.nextInt(20),50+rand.nextInt(200),70+rand.nextInt(180));});
        colgen.add(()->{return new Color(rand.nextInt(20),rand.nextInt(40),70+rand.nextInt(180));});
        colgen.add(()->{return new Color(150+rand.nextInt(90),10+rand.nextInt(120),rand.nextInt(5));});
        colgen.add(()->{int r=rand.nextInt(200);return new Color(r,r,r);});
        colgen.add(()->{return Arrays.asList(new Color(255,0,0),new Color(0,255,0),new Color(0,0,255)).get(rand.nextInt(3));});
        colgen.add(()->{return Arrays.asList(new Color(156,189,15),new Color(140,173,15),new Color(48,98,48),new Color(15,56,15)).get(rand.nextInt(4));});
        Scanner in=new Scanner(System.in);
        image=ImageIO.read(new File(in.nextLine()));
        final Supplier<Color>sup=colgen.get(in.nextInt());
        W=image.getWidth();
        H=image.getHeight();
        for(int x=0;x<W;x++){
            for(int y=0;y<H;y++){
                if(isProbablyWhite(x,y))process(x,y,sup.get());
            }
        }
        ImageIO.write(image,"png",new File("out.png"));
    }
}

Требуется два ввода: имя файла и идентификатор палитры. Включает некоторую коррекцию сглаживания, но не включает логику для прозрачных пикселей.

В настоящее время распознаются следующие палитры:

0: Blue and greeen
1: Blue
2: Red
3: Greyscale
4: Three-color Red, Green, and Blue
5: Classic Game Boy pallette (four shades of green)

Результаты:

Дракон, палитра Game Boy:

введите описание изображения здесь

Другой дракон, синяя + зеленая палитра:

введите описание изображения здесь

GOL натюрморт Мона Лиза (как показано в этой программе ), триколор палитра:

введите описание изображения здесь


+1 за настройку цвета! :) если бы вы могли исправить проблему сглаживания, это выглядело бы еще лучше. Сколько времени у вас ушло на вывод этих изображений?
Оливер Гриффин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.