Paint by Numbers (usando la programmazione, non i numeri)


56

Il tuo compito è creare un programma che acquisisca un'immagine delineata in bianco e nero (le immagini di esempio sono sotto) e la riempie di colore. Spetta a te sezionare ogni regione e con quale colore riempirlo (potresti persino usare un RNG).

Per esempio:

uscita per esempio 1

Come puoi vedere, sono chiaramente un artista di livello superiore quando si tratta di MS Paint.


punteggio

Questo è un concorso di popolarità, quindi vince la risposta con il maggior numero di voti netti. Gli elettori sono incoraggiati a giudicare le risposte

  • Criterio di input: qualsiasi immagine composta da sfondo bianco / grigio chiaro e contorni nero / grigio scuro
  • Come viene eseguita la colorazione; significa che poche o nessuna area sono bianche diversamente da quanto sopra (a meno che tu non abbia ovviamente intenzione di usare il bianco, ad esempio per le nuvole)
  • Personalizzabilità dei colori utilizzati in alcune sezioni
  • Come funziona il sistema su una gamma di immagini diverse (con vari dettagli)
  • Pubblica quanto tempo impiega il tuo programma per immagine. Potremmo non giocare a code golf, ma un codice più breve, più veloce ed più efficiente dovrebbe essere considerato migliore
  • Dovrebbe produrre la nuova immagine sullo schermo o su un file (non più grande di 2 MB in modo che possa essere mostrato nella risposta)
  • Si prega di giustificare il motivo per cui si è scelto di produrre questo tipo di immagine e commentare / spiegare il funzionamento del proprio codice
  • L'applicabilità del colore utilizzato alla rispettiva forma è vincolata (una combinazione di colori realistica, ovvero l'erba è verde, i recinti di legno sono marroni, ecc.)

    "Potrei colorare casualmente ogni area, ma se potessi identificare la" recinzione "e renderla allo stesso modo colorata, allora è qualcosa che merita voti positivi." - NathanMerrill

Dato che si tratta di un concorso di popolarità, puoi anche giudicare facoltativamente da:

  • Appello generale (quanto è bella l'immagine)
  • Talento artistico; se è possibile programmare in sfumature o colorazioni ad acquerello, ecc.

In generale, vincerà l'immagine più piccola prodotta (dimensione del file) della massima qualità, con il programma a digiuno e il voto pubblico più alto.

Se hai altre specifiche di valutazione che ritieni debbano essere utilizzate, ti preghiamo di raccomandarle nei commenti di questo post.


Esempi

Non possiedo nulla; tutte le immagini di esempio sono di licenza Creative Commons.

esempio 1 in bianco / nero Fonte: https://pixabay.com/ro/stejar-arbore-schi%C5%A3%C4%83-natura-303890/ esempio 2 in bianco / nero Fonte: http://www.freestockphotos.biz/stockphoto/10665 esempio 3 in bianco / nero Fonte: http: / /crystal-rose1981.deviantart.com/art/Dragon-Tattoo-Outline-167320011 esempio 4 in bianco / nero Fonte: http://jaclynonacloudlines.deviantart.com/art/Gryphon-Lines-PF-273195317 esempio 5 in bianco / nero Fonte: http://captaincyprus.deviantart.com / art / Dragon-OutLine-331748686 esempio 6 in bianco / nero Fonte: http://electric-meat.deviantart.com/art/A-Heroes-Farewell-280271639 esempio 7 in bianco / nero Fonte: http://movillefacepalmplz.deviantart.com/art/Background-The-Pumpkin -Farm-di-buona-old-giorni-342865938


MODIFICA: a causa dell'antialiasing sulle linee che causano pixel non bianchi / neri e alcune immagini che potrebbero contenere grigio anziché bianco / nero, come sfida bonus puoi tentare di affrontarlo. Secondo me dovrebbe essere abbastanza facile.


4
A tutti: per favore non ridimensionare / chiudere questo come un "concorso artistico" - c'è di più
edc65

16
Benvenuti in PPCG! Ti applaudo per avere il coraggio non solo di far diventare il tuo primo post una sfida, e non solo una sfida pop-con, ma una sfida artistica in cima a tutto. Buona fortuna, ti auguro il meglio, e se rimani in giro penso che andrai lontano qui.
AdmBorkBork,

4
@OliverGriffin Sto votando contro la chiusura e, inoltre, ho aggiunto le immagini che hai collegato per te. Puoi rimuovere i commenti, se lo desideri.
Addison Crump,

2
Alla fine ho trovato un approccio che probabilmente non impilerà l'overflow, ma ora sta andando lentamente.
SuperJedi224,

4
Ho votato per riaprire la tua domanda e ho cambiato il mio -1 in +1. Buona modifica dei lavori e aggiunta di informazioni aggiuntive. Inoltre, ti applaudo per essere così ricettivo alle critiche della comunità. Benvenuti in PPCG! Spero ti sia piaciuto.
Zach Gates,

Risposte:


30

Aerografia spettrale (Python, PIL, scipy)

Questo utilizza un sofisticato algoritmo matematico per produrre assurdità colorate. L'algoritmo è correlato all'algoritmo PageRank di Google, ma per i pixel anziché per le pagine Web.

Ho adottato questo approccio perché pensavo che a differenza dei metodi basati sul riempimento di inondazioni potesse essere in grado di far fronte a immagini come il pollo e l'albero, dove ci sono forme che non sono interamente racchiuse da linee nere. Come puoi vedere, funziona in qualche modo, anche se tende a colorare in diverse parti del cielo in diversi colori

Per i matematici: quello che sta facendo è essenzialmente costruire il grafico di adiacenza dei pixel while nell'immagine, quindi trovare i primi 25 autovettori del grafico Laplacian. (Tranne il fatto che, poiché includiamo i pixel scuri, diamo solo alle loro connessioni un peso inferiore. Ciò aiuta a gestire l'antialias e sembra anche dare risultati migliori in generale.) Avendo trovato gli autovettori, crea un combinazione lineare casuale di questi, ponderata dai loro autovalori inversi, per formare i componenti RGB dell'immagine di output.

Nell'interesse del tempo di calcolo, l'immagine viene ridimensionata prima di fare tutto ciò, quindi ridimensionata di nuovo e quindi moltiplicata per l'immagine originale. Tuttavia, non funziona rapidamente, impiegando circa 2 e 10 minuti sulla mia macchina, a seconda dell'immagine di input, anche se per qualche motivo il pollo ha impiegato 17 minuti.

In realtà potrebbe essere possibile trasformare questa idea in qualcosa di utile, creando un'app interattiva in cui è possibile controllare il colore e l'intensità di ciascuno degli autovettori. In questo modo potresti sbiadire quelli che dividono il cielo in diverse sezioni e sbiadire quelli che raccolgono le caratteristiche rilevanti dell'immagine. Ma non ho intenzione di farlo da solo :)

Ecco le immagini in uscita:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

(Non ha funzionato così bene sulle zucche, quindi ometto quello.)

Ed ecco il codice:

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
Questo è DAVVERO bello. Probabilmente uno dei miei preferiti finora. Hai fatto un ottimo lavoro nel gestire l'antialias e le aree aperte e qualcuno ha finalmente colorato in Link! ( Stavo aspettando questo :-P salva impostato su desktop ) Mi chiedo cosa il mio vecchio insegnante di inglese avrebbe detto a riguardo come un'immagine statica ... "Mostra i due lati del suo cuore, un lato c'è pace e sul altro c'è il combattimento necessario per ottenere quella pace ". Basta con il mio amore per i giochi di Legend of Zelda ... È davvero un peccato che ci voglia così tanto tempo. Quanto erano grandi i file risultanti? Ps Love images 4 & 5
OliverGriffin

2
@donbright una terza elementare in grado di capire gli autovettori sarebbe davvero un bambino molto brillante - non sono sicuro che sia possibile per me spiegare l'algoritmo a quel livello. Ma lasciami provare comunque: immagina di stampare l'immagine su un foglio di metallo rigido. Quindi tagliamo con cura tutte le linee nere e le sostituiamo con qualcosa di molto più flessibile, come l'elastico. Quindi le parti bianche sono piastre di metallo e le parti nere sono tessuto flessibile. Successivamente appendiamo il tutto in aria dalla corda, quindi è libero di muoversi. Ora se tocchiamo le piastre di metallo, vibreranno ...
Nathaniel,

2
@donbright (continua) ... A seconda di come si colpisce la piastra metallica, vibrerà in diversi modi. Forse a volte solo una delle parti metalliche vibrerà e non le altre, ma altre volte (perché sono collegate da un elastico), colpire una piastra inizierà a muoverne anche un'altra. Questi diversi modi di vibrare sono chiamati modi vibrazionali . Questo programma simula alcune delle modalità vibrazionali di questa piastra metallica, ma invece di generare suono, le utilizza per capire quale colore disegnare.
Nathaniel,

2
@donbright Puoi anche vedere qui per ulteriori informazioni sulla visualizzazione delle vibrazioni delle piastre metalliche.
Nathaniel,

2
@donbright (questa spiegazione più tecnica potrebbe anche farti perdere un po ', ma questa spiegazione funziona perché anche le modalità vibrazionali di una piastra sono calcolate usando un calcolo autovettore. Sebbene sia possibile non è esattamente lo stesso calcolo che il mio codice fa - Sto non proprio sicuro.)
Nathaniel

25

Anche Python 2 + PIL, il mio primo libro da colorare

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()

Ho fatto esattamente lo stesso di CarpetPython, tranne per il fatto che riempio la regione di "gradienti" e utilizzo un ciclo di colori diverso.

I miei coloranti più magnifici: inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Tempi di calcolo sulla mia macchina:

  • immagine 1 (drago cinese): reale 0m2.862s utente 0m2.801s sys 0m0.061s

  • immagine 2 (grifone): reale 0m0.991s utente 0m0.963s sys 0m0.029s

  • immagine 3 (drago unicorno): reale 0m2.260s utente 0m2.239s sys 0m0.021s


Belle sfumature! Quando si inserisce un ciclo for all'interno di un ciclo for con nient'altro all'interno del primo non è necessario rientrare ulteriormente?
OliverGriffin

certo che lo fai! è stato un problema di copia / incolla ...
Dieter,

23

Python 2 e PIL: mondi psichedelici

Ho usato un semplice algoritmo per riempire inondazioni ogni area bianca con un colore da una palette di ciclismo. Il risultato è molto colorato, ma non molto realistico.

Si noti che le parti "bianche" in queste immagini non sono molto bianche. Dovrai testare anche le sfumature di grigio.

Codice in 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)

Immagini di esempio:

Un drago colorato

Zucche su LSD


3
La parte spaventosa è che i colori sembrano effettivamente funzionare. Quanto tempo hai impiegato per colorare ogni immagine e quanto erano grandi i file?
OliverGriffin

1
Il programma colora ogni immagine in circa 2 secondi. Le dimensioni dell'immagine di output sono le stesse dei file di input. Le dimensioni dei file sono per lo più inferiori del 10% al 40% rispetto agli originali (probabilmente perché vengono utilizzate diverse impostazioni di compressione jpeg).
Logic Knight

3
Sono profondamente impressionato da quanto sia corto il codice! Mi piace anche come limitare efficacemente i colori disponibili da utilizzare, mantenendo così un pallet impostato. In realtà mi piace davvero, dà un po 'di atmosfera grunge (è la parola giusta? Non sono un artista).
OliverGriffin

@OliverGriffin, sono contento che ti piaccia. Stavo puntando su una tavolozza senza colori chiari o scuri, ma avevo ancora un po 'di contrasto. Questa gamma di colori sembrava avere i risultati più piacevoli.
Logic Knight,

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);

Usiamo lo spazio dei colori HSV e scegliamo ogni tonalità Tonalità in base alla dimensione relativa tra le regioni bianche. La regione più grande sarà blu ( Hue = 0.7) e la regione più piccola sarà viola ( Hue = 0.8). Le regioni tra queste due dimensioni sono indicate Tonalità nell'intervallo 0.7 -> 1=0 -> 0.8. La tonalità sulla gamma viene selezionata linearmente rispetto alla funzione area^0.15. Saturazione e valore sono sempre 1 per ogni pixel non nero.

Ci vuole meno di 1 secondo per colorare un'immagine.

Le 3 immagini con regioni chiuse in cui l'algoritmo funziona in modo decente:

Drago

un altro drago

forse un altro drago

E il resto delle immagini:

Drago

un altro drago

forse un altro drago

Su queste immagini ci sono grandi aree bianche collegate che dovrebbero essere idealmente colorate da più colori (questo problema è stato ben risolto nella soluzione di Nathaniel .


Codice carino e abbreviato per risultati coordinati con un bel colore! Mi piace come hai usato l'area per aiutare a determinare la tonalità. Quanto tempo ci è voluto per elaborare l'immagine media e perché non ha funzionato su alcune delle immagini più dettagliate? Le aree erano troppo piccole?
OliverGriffin,

1
@OliverGriffin Mi ha risposto nel mio post e ha aggiunto il resto delle immagini.
randomra,

7

Python 3 con cuscino

Il codice è un po 'lungo da includere in questa risposta, ma ecco l'essenza di esso .

  1. Prendi l'immagine in ingresso e, se ha un canale alfa, componila su uno sfondo bianco. (Necessario almeno per l'immagine del pollo, perché l'intera immagine era nera, distinta solo dalla trasparenza, quindi semplicemente cadere l'alfa non era utile.)
  2. Converti il ​​risultato in scala di grigi; non vogliamo che manufatti di compressione o anti-aliasing, o linee grigie che non sono abbastanza grigie, ci rovinino.
  3. Crea una copia a due livelli (in bianco e nero) del risultato. Le tonalità di grigio vengono convertite in bianco o nero in base a una soglia di taglio configurabile tra il bianco e la tonalità più scura dell'immagine.
  4. Riempi tutte le aree bianche dell'immagine. I colori vengono scelti a caso, utilizzando una tavolozza selezionabile che tiene conto della posizione del punto iniziale per l'operazione di riempimento.
  5. Riempi le linee nere con i colori dei vicini più vicini. Questo ci aiuta a reintrodurre l'antialiasing, evitando che ogni regione colorata sia delimitata da un nero irregolare.
  6. Prendi l'immagine in scala di grigi dal passaggio 2 e creane una maschera alfa: il colore più scuro è completamente opaco, il colore più chiaro è completamente trasparente.
  7. Comporre l'immagine in scala di grigi sull'immagine colorata dal passaggio 5 usando questa maschera alfa.

Questi ultimi passaggi, sfortunatamente, non hanno ancora eliminato gli "aloni" più chiari che sono visibili nelle regioni di colore più scuro, ma almeno hanno fatto una notevole differenza. L'elaborazione delle immagini non è mai stata il mio campo di studio, quindi per quanto ne so ci sono algoritmi più efficaci e di successo per fare ciò che ho cercato di fare qui ... ma vabbè.

Finora, ci sono solo due palette selezionabili per il passaggio 4: una puramente casuale e una molto "ruvida" naturale, che cerca di assegnare i colori del cielo agli angoli superiori, i colori dell'erba agli angoli inferiori, il marrone (rocce o legno ) colori al centro di ciascun lato e vari colori al centro. Il successo è stato ... limitato.


Uso:

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

Campioni:

paint_by_prog.py -t 0.7 Gryphon-Lines.png Grifone colorato

paint_by_prog.py Dragon-Tattoo-Outline.jpg Drago colorato di cartoni animati

paint_by_prog.py -t 0.85 -p natural The-Pumpkin-Farm-of-Good-old-Days.jpg Scena di fattoria colorata

paint_by_prog.py -t 0.7 Dragon-OutLine.jpg Drago colorato grunge

paint_by_prog.py stejar-arbore-schiţă-natura.png Albero colorato, molto simile a una bandiera

Il pollo non sembra molto buono e il mio risultato più recente per l'immagine Link non è il migliore; uno che proveniva da una versione precedente del codice era in gran parte giallo pallido e aveva un'interessante atmosfera desertica al riguardo ...


Prestazione:

Ogni immagine impiega un paio di secondi per l'elaborazione con le impostazioni predefinite, il che significa che viene utilizzato un algoritmo approssimativo più vicino al vicino per il passaggio 5. Il vero vicino più vicino è significativamente più lento, impiegando forse mezzo minuto (non l'ho ancora cronometrato).


La prima immagine sembra fantastica, in particolare quell'occhio marrone. Buon lavoro. Ti applaudo anche per avere erba verde, campi marroni di zucche e nuvole viola.
OliverGriffin,

3

Giava

Selezione casuale del colore dalla scelta della pallette.

Avvertenza: la ricerca della regione è attualmente molto lenta, a meno che le regioni bianche non siano insolitamente piccole.

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"));
    }
}

Richiede due input: il nome file e l'ID tavolozza. Include una correzione dell'antialias, ma non include la logica per i pixel trasparenti.

Sono attualmente riconosciute le seguenti tavolozze:

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)

risultati:

Dragon, tavolozza Game Boy:

inserisci qui la descrizione dell'immagine

L'altro drago, tavolozza blu + verde:

inserisci qui la descrizione dell'immagine

GOL still life mona lisa (come renderizzato da questo programma ), palette tricolore:

inserisci qui la descrizione dell'immagine


+1 per la personalizzazione del colore! :) se potessi risolvere il problema dell'antialias questo sarebbe ancora meglio. Quanto tempo hai impiegato per produrre queste immagini?
OliverGriffin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.