View Full Version : [TeoriaImmagini] Algoritmi Filtri
Salve a tutti
Come da titolo , volevo avere da voi , se possibile , delucidazioni su algoritmi di filtraggio immagini come :seppia , bianco e nero ecc...
Per il momento so solo che per applicare tali filtri occorrerebbe modificare , direttamente tramite codice, il codice (scusate la ripetizione) esadecimale dell'immagine...
Qualche spunto o idea o link per capirci qualcosa?
Grazie mille
Ciao :)
per quello che mi ricordo :D
detto semplicemente e linearmente(il caso base) ad ogni pixel sono associati 3 valori rappresentanti le 3 componenti di "colore" per quel pixel (a seconda della codifica potrebbe essere rgb o cmy o his o altre)
a seconda del filtraggio scelto modifichi uno o più componenti per ottenere il risultato desiderato :)
se cerchi su google qualcosa trovi sicuro (magari usando come chiavi i vari tipi di codifica)
Grazie innanzitutto :)
Mostro qui sotto un'immagine di un editor esadecimale:
http://www.portablefreeware.com/graphics/xvi32/screenshot.gif
La parte destra è codice Ascii , se non erro.
La sinistra dovrebbe rappresentare la parte esadecimale di ogni pixel (sbaglio?)
Ho trovato inoltre questo riferimento
http://it.wikipedia.org/wiki/Seppia_(colore)
Solo che qui viene indicato il colore Seppia , non la tecnica di filtraggio che si basa , si , su colorazioni marroncine...
yorkeiser
09-04-2009, 15:24
In primis, devi distinguere se l'immagine è in formato compresso o meno.
Ad esempio, in una bitmap (.bmp) l'immagine non è compressa, quindi, dopo il necessario header (una serie di byte iniziali che indicano, tra gli altri, la dimensione dell'immagine, la profondità di bit ed altre informazioni) partono le informazioni relative ai colori di ogni singolo pixel.
Ergo, se hai una bitmap con profondità di colore a 32 bit, ovvero 8 bit per ogni componente di colore (rossa, verde e blu) più 8 bit per la componente alfa, ogni coppia di esadecimali (come 'FF', che è un byte, ovvero 8 bit) rappresenta una componente di colore per quel pixel.
Ad esempio, un pixel blu intenso è composto da 4 byte che in esadecimale sarebbero 00 - 00 - 00 - FF, dove 'FF' è il massimo valore (255) per la componente blu, mentre alfa, rosso e verde sono settati a '00', ovvero 0.
Se l'immagine invece è in un formato compresso (ad esempio .jpg), per ottenere il valore di colore dei singoli pixel devi prima passare per un opportuno algoritmo di decompressione.
Una volta che ottieni tutte le terne di colori per ogni singolo pixel della tua immagine, basta modificare quei valori per ottenere degli effetti di filtraggio.
Grazie mille per la risposta ;)
Ti vorrei porre un altro quesito: come dovrebbero essere gli algoritmi di filtraggio (mi ripeto , vedi Seppia) ,una volta ottenute le terne di colori in forma "trattabile"?
Ovvero sia , in che modo operano questi algoritmi?
In base a cosa modificano le singole terne , creando quei tanto "piacevoli" o non, effetti?
Vorrei capire come "ragionano" per intenderci...
Grazie :)
P.s: mi sono scaricato persino i source di Gimp per cercare di capire come funzionino :asd:
Se devi farlo in C/C++ ti consiglio FreeImage, ti permette di accerere ai dati di immagini di qualsiasi formato in maniera piuttosto intuitiva (20 righe) poi si trova codice per il loading/saving pronto all'uso.
Quando ottieni poi l'elenco dei raw pixel diventa molto facile eseguire qualsiasi filtro ti serva, devi solo fare attenzione quando accedi il buffer dei pixel (monodimensionale) come un'immagine (due dimensioni).
yorkeiser
09-04-2009, 17:55
Grazie mille per la risposta ;)
Ti vorrei porre un altro quesito: come dovrebbero essere gli algoritmi di filtraggio (mi ripeto , vedi Seppia) ,una volta ottenute le terne di colori in forma "trattabile"?
Ovvero sia , in che modo operano questi algoritmi?
In base a cosa modificano le singole terne , creando quei tanto "piacevoli" o non, effetti?
Vorrei capire come "ragionano" per intenderci...
Grazie :)
P.s: mi sono scaricato persino i source di Gimp per cercare di capire come funzionino :asd:
Non ho idea precisamente di cosa voglia dire effetto seppia, ma facciamo l'esempio del bianco e nero (o meglio, scala di grigi), che forse ci si avvicina.
Un'idea per effettuare un rozzo effetto di bianco e nero potrebbe essere quella di calcolare l'intensità di ogni pixel e trasformarla in grigio.
L'intensità di un pixel potresti ad esempio calcolarla come:
(R + G + B) / 3
dove R, G e B sono i valori della componente rossa, verde e blu del pixel originario.
Una volta calcolata l'intensità, per trasformarla in un grigio basta copiare il suo valore (appena calcolato) nelle tre componenti R G B (un pixel grigio è caratterizzato dall'avere le 3 componenti di valore uguale o comunque con poca differenza).
Le immagini sono funzioni del colore nello spazio o funzioni del colore nella frequenza.
I filtri non sono altro che composizioni di funzioni con l'immagine (intesa a sua volta come funzione).
Ad esempio il blur è una funzione che taglia i picchi di frequenza dall'immagine intesa come funzione del colore nella frequenza (ottieni una rappresentazione del colore nella frequenza applicando una trasformata di fourier alla funzione del colore nello spazio).
Il "sepia tone" fa una cosa simile solo che anzichè "tagliare" i picchi sposta le bande in un range di frequenza che corrisponde ad un determinata tonalità di colore.
Almeno in teoria, non ho mai provato ad applicare un effetto seppia da codice :D:
Beh, ci son sicuramente diversi modi di intendere i filtri... per esempio uno shader su un'immagine è sicuramente un filtro.
IMHO al computer, più che come una funzione, è meglio pensare all'immagine come ad un array di colori... e il filtro come una funzione che li "mischia" a seconda della loro prossimità.
Il seppia credo sia facile da fare, basta rendere l'immagine una grayscale e poi usarla per interpolare fra marrone scuro e giallino... almeno io farei cosi' :stordita:
BrutPitt
10-04-2009, 07:10
Quoto PGI-Bis, anche se ce ne sarebbe da dire sull'argomento... :)
Insomma un filtro e' una "funzione" (nel termine matematico del termine) tale che y=f(x) per ogni x,y appartenenti a RGB, o CMY, o HSL, o HSV, o CrCbY... etc. che sono tutti spazi di rappresentazione dell'immagine.
Analoghe funzioni possono lavorare anche in frequenza... eventualmente dopo opportune "trasformazioni".
Non ho idea precisamente di cosa voglia dire effetto seppia, ma facciamo l'esempio del bianco e nero (o meglio, scala di grigi), che forse ci si avvicina.
Un'idea per effettuare un rozzo effetto di bianco e nero potrebbe essere quella di calcolare l'intensità di ogni pixel e trasformarla in grigio.
L'intensità di un pixel potresti ad esempio calcolarla come:
(R + G + B) / 3
dove R, G e B sono i valori della componente rossa, verde e blu del pixel originario.
Una volta calcolata l'intensità, per trasformarla in un grigio basta copiare il suo valore (appena calcolato) nelle tre componenti R G B (un pixel grigio è caratterizzato dall'avere le 3 componenti di valore uguale o comunque con poca differenza).
Quasi... :)
Per acquisire la luminanza (immagine in tonalita' di grigi), bisognerebbe tener conto dell'influenza delle varie lunghezze d'onda delle tre componenti e quanto queste influenzano la percezione, .
In pratica la formula per estrapolare la luminanza:
Date le componenti di colore R,G,B , la luminanza Y e' data dal'espressione:
Y = (0.299 * R) + (0.587 * G) + (0.114 * B)
Una volta ottenuta la luminanza, per ottenere il seppia, potresti seguire qualcosa del genere:
Assumendo che il valore di Y sia compreso in [0,255] e che l'immagine risultante sara' in forma r,g,b, ogni valore compreso tra [0,255], allora le tre componenti sono date da:
se (Y < 225) allora ( r = Y + 30 ) altrimenti ( r = 255 )
g = Y
se (Y > 30) allora ( b = Y - 30 ) altrimenti ( b = 0 )
(qui pero' dipende dalle tonalita', piu' "calde" o piu' "fredde", che desideri ottenere... e adattare le costanti all'occasione)
E cosi' hai trasformato la tua immagine R,G,B... attraverso questo procedinemto (funzione)... in seppia (r,g,b).
In sintesi: (r,g,b) = f(R,G,B).
Grazie mille per la spiegazione :) (scusate il ritardo)
Avreste altre idee per "filtri"?
Finora gli unici che mi son venuti in mente , son "seppia" e "bianco e nero"...
Altri non saprei sinceramente , ho provato a guardare quelli per photoshop (tipo Mosaico) ma non mi sembrano semplicissimi...
Grazie ancora , saluti
P.s: Buone feste ;)
stdecden
12-04-2009, 14:51
All'inizio comincerei con una sfocatura con l' algoritmo box-blur, che non fa altro che fare la media di tutti i pixel vicini.
^TiGeRShArK^
13-04-2009, 09:43
high pass, low pass, unsharp mask, deconvolution....
All'inizio comincerei con una sfocatura con l' algoritmo box-blur, che non fa altro che fare la media di tutti i pixel vicini.
Del tipo: analizzo il primo pixel (terna di colori) lo confronto con quello sotto e quello di lato , faccio la media tra i tre e assegno al primo pixel questa media?
E via di seguito?
stdecden
13-04-2009, 12:11
Non solo quello sotto e quello di lato, ma anche quello sopra, quello sotto a destra, e così via...
Ma sennò l'idea di base è giusta
^TiGeRShArK^
13-04-2009, 21:29
Del tipo: analizzo il primo pixel (terna di colori) lo confronto con quello sotto e quello di lato , faccio la media tra i tre e assegno al primo pixel questa media?
E via di seguito?
per quelli semplici basta applicare una matrice di convoluzione, magari meglio nello spazio di colore YUV.
http://it.wikipedia.org/wiki/Matrice_di_convoluzione
Praticamente (singolo esempio) un pixel di A viene sostituito con il prodotto del pixel sottostante ad A con il pixel di B (quello centrato)?
Oppure no?
Mi sembra non sia così , però non riesco a spiegarmi meglio pardon :(
Il pixel di destinazione è composto dalla somma dei pixel della sorgente per i corrispondenti valori del kernel.
Vale a dire, supponendo che il kernel della convoluzione sia la matrice 3x3
0.0,0.1,0.2
0.3,0.4,0.5
0.6,0.7,0.8
applicandola ad un'immagine di 3x3 pixel
P0, P1, P2
P3, P4, P5
P6, P7, P8
Otteniamo l'immagine di destinazione:
P0, P1, P2
P3, XX, P5,
P6, P7, P8
con
XX = F{(P0 * 0.0) + (P1 * 0.1) + (P2 * 0.2) + (P3 * 0.3) + (P4 * 0.4) + (P5 * 0.5) + (P6 * 0.6) + (P7 * 0.7) + (P8 * 0.8)}
PX * N è la moltiplicazione di un vettore (r, g, b, a) per uno scalare N, F(P) è la funzione di riduzione dei componenti di P al limite inferiore o superiore (es. se il canale red va da -1 a 1 e la moltiplicazione col kernel lo porta a ventimila F lo riduce a 1).
Se l'immagine è più grande del kernel la convoluzione si applica allo stesso modo, "spostando il kernel all'interno dell'immagine".
Vale a dire, immagine:
P00, P01, P02, P03
P04, P05, P06, P07
P08, P09, P10, P11
Kernel:
A,B,C
D,E,F
G,H,I
la convoluzione genera l'immagine:
P00, P01, P02, P03
P04, XXX, YYY, P07
P08, P09, P10, P11
con
XXX = F(A*P00 + B*P01 + C*P02 + D*P04 + E*P05 + F*P06 + G*P08 + H*P09 + I*P10).
YYY = F(A*P01 + B*P02 + C*P03 + D*P05 + E*P06 + F*P07 + G*P09 + H*P10 + I*P11).
Tutto qua.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.