Paint Numbers (використовуючи програмування, а не цифри)


56

Ваше завдання - створити програму, яка знімає чорно-біле окреслене зображення (приклади зображень нижче) і заповнює його кольором. Ви вирішуєте, як розділити кожен регіон і яким кольором його заповнити (можна навіть використовувати RNG).

Наприклад:

вихід наприклад 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://movillefacepalpalmplz.deviantart.com/art/Background-The-Pumpkin -Ферма Доброго-Старого-Дні-342865938


РЕДАКТУВАННЯ: Завдяки антижилу на лініях, що спричиняють не чорні / білі пікселі, а також деякі зображення, які можуть містити сірий замість чорного / білого, як бонусний виклик ви можете спробувати вирішити це. На мою думку, це повинно бути досить легко.


4
Для всіх: будь ласка, не знімайте / закривайте це як "конкурс мистецтв" - є ще більше
edc65

16
Ласкаво просимо до PPCG! Я вітаю вас за те, що ви мали сміливість не лише ваш перший пост бути викликом, і не лише викликом pop-con, але і мистецьким викликом у всьому. Удачі, я бажаю вам найкращого, і якщо ви будете триматися, я думаю, ви заїдете далеко сюди.
AdmBorkBork

4
@OliverGriffin Я голосую проти закриття, а також я додав у зображення, які ви пов’язали для вас. За бажанням можна видалити коментарі.
Аддісон Кримп

2
Нарешті я знайшов підхід, який, ймовірно, не буде переповнювати, але зараз він працює повільно.
SuperJedi224

4
Я проголосував за повторне відкриття вашого питання і змінив мій -1 на +1. Гарне редагування та додавання додаткової інформації. Також я аплодую вам за те, що ви так сприйнятливі до критики громади. Ласкаво просимо до PPCG! Сподіваюся, вам сподобається.
Зак Гейтс

Відповіді:


30

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

Тут використовується складний математичний алгоритм для створення різнокольорових дурниць. Алгоритм пов'язаний з алгоритмом PageRank Google, але для пікселів замість веб-сторінок.

Я застосував такий підхід, тому що думав, що на відміну від методів, що ґрунтуються на затопленні, він може впоратися із зображеннями на зразок курки та дерева, де є форми, які не повністю закриті чорними лініями. Як бачите, це щось працює, хоча також має тенденцію до забарвлення в різних частинах неба в різні кольори

Для математично зважених: те, що він робить, по суті, будує графік суміжності пікселів на зображенні, а потім знаходить 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
Це дійсно класно. Напевно, один із моїх улюблених поки що. Ви відмінно справились з обробкою антиалізингу та відкритих ділянок, а хтось нарешті пофарбувався у Посилання! (Чекали цього: - збережіть на робочому столі ) Цікаво, що мій старий вчитель англійської мови сказав би про це як статичне зображення ... "Це показує дві сторони його серця, з одного боку є мир, а на інше - це боротьба, необхідна для досягнення цього миру ". Досить про мою любов до ігор Legend of Zelda ... Це справді прикро, що це займає так довго. Наскільки великими були отримані файли? Ps Love images 4 & 5
OliverGriffin

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 (унікальний дракон): справжній користувач 0м2.260s 0m2.239s sys 0m0.021s


Гарні градієнти! Коли ви вставляєте цикл for у цикл for для циклу, а нічого іншого всередині першого не потрібно, щоб далі не відступати?
ОліверГріффін

впевнений, що ти робиш! це було проблемою копіювання / вставки ...
dieter

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

Матлаб

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

Java

Випадковий вибір кольору на ваш вибір палітри.

Попередження: пошук регіонів зараз дуже повільний, якщо білих регіонів незвично мало.

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)

Результати:

Палітра Dragon, Game Boy:

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

Інший дракон, синя + зелена палітра:

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

GOL натюрморт Mona lisa (як надано цією програмою ), триколірна палітра:

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


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