PDA

View Full Version : [JAVA] Manipolazione di immagini


xirc85
16-10-2007, 10:25
Ciao a tutti!
Devo fare un'applicazione su piattaforma J2ME per l'analisi di immagini.
Vorrei sapere come posso accedere ai byte che la compongono, dato che uso un'oggetto di tipo Image.
Mi piacerebbe riuscire ad ottenere un array che contenga la codifica del colore per ogni pixel se possibile, così da poterli modificare a mio piacimento...

Grazie a tutti

andbin
16-10-2007, 10:49
Devo fare un'applicazione su piattaforma J2ME per l'analisi di immagini.
Vorrei sapere come posso accedere ai byte che la compongono, dato che uso un'oggetto di tipo Image.
Mi piacerebbe riuscire ad ottenere un array che contenga la codifica del colore per ogni pixel se possibile, così da poterli modificare a mio piacimento...Non programmo in J2ME ma ho la documentazione sotto mano. Image ha un metodo getRGB() (nota, MIDP 2.0) per ottenere un array con i dati dei pixel.
Dipende da cosa devi farci con questi pixel. Potresti anche ottenere il Graphics con il metodo getGraphics() e poi disegnarci sopra con dei metodi più comodi e pratici es. drawLine(), fillRect() ecc....
Di più non so dirti.

xirc85
16-10-2007, 10:54
Innanzitutto, grazie :D
In pratica io devo controllare i pixel per regolare il contrasto come prima cosa (o meglio devo convertire per così dire l'immagine da scala di grigi o a colori a un'immagine bianca e nera a un bit...) e poi devo scandirmela in modo opportuno per capire cosa contiene..

grazie ancora

andbin
16-10-2007, 11:10
In pratica io devo controllare i pixel per regolare il contrasto come prima cosa (o meglio devo convertire per così dire l'immagine da scala di grigi o a colori a un'immagine bianca e nera a un bit...) e poi devo scandirmela in modo opportuno per capire cosa contiene..Allora devi proprio accedere direttamente ai valori dei pixel, l'uso di Graphics non ti serve (visto che fa solo operazioni di "alto" livello).

Se stai usando MIDP 2.0 vedi quindi il metodo getRGB() della classe javax.microedition.lcdui.Image.

xirc85
16-10-2007, 11:26
grazie mille!
adesso mi studio un pò la documentazione :D :D e poi provo a fare qualche esperimento...

xirc85
16-10-2007, 13:20
Ho provato a smanettarci un pò e dopo aver richiamato il metodo getRGB, mi stampo l'array contenente le codifiche dei pixel... non riesco però a capire questa codifica...

Ad esempio mi stampa una cosa del tipo "-15658735" e sinceramente non riesco a capire se si tratta di una codifica del colore in intero, o se è un numero generato dalla composizione di più parametri concatenati :muro:

Qualcuno mi può aiutare??

andbin
16-10-2007, 13:26
Ho provato a smanettarci un pò e dopo aver richiamato il metodo getRGB, mi stampo l'array contenente le codifiche dei pixel... non riesco però a capire questa codifica...

Ad esempio mi stampa una cosa del tipo "-15658735" e sinceramente non riesco a capire se si tratta di una codifica del colore in intero, o se è un numero generato dalla composizione di più parametri concatenati :muro: La documentazione è pure molto chiara. Ogni pixel è memorizzato in un valore di tipo int nel formato 0xAARRGGBB. Il sostanza il valore a 32 bit è suddiviso in 4 campi da 8 bit. Quindi il valore non è da trattare come un puro valore numerico.

Un valore come -15658735, in esadecimale è 0xFF111111, pertanto in questo caso rosso, verde e blu hanno valore 0x11 o in decimale 17.

xirc85
16-10-2007, 13:38
mmm... grazie!

quindi per poter capire di che colore è effettivamente quel pixel, devo trattare il valore numerico per estrarre le informazioni?
Dato che a me interessa più che altro capire se un colore è "chiaro" o "scuro" potrei basarmi sul valore massimo e minimo contenuto nell'array (magari dopo aver tolto "l'informazione" riguardante l'Alpha processing...)??

andbin
16-10-2007, 14:21
quindi per poter capire di che colore è effettivamente quel pixel, devo trattare il valore numerico per estrarre le informazioni?Se devi prendere in considerazione i singoli colori R, G e B, devi prelevare solo gli 8 bit necessari dal int. E questo richiede l'uso degli operatori bitwise di AND (&) e di shift.

Dato che a me interessa più che altro capire se un colore è "chiaro" o "scuro"Potresti determinare il valore su scala di grigio che è molto semplice da calcolare: 30% di R + 59% di G + 11% di B.

xirc85
16-10-2007, 14:36
grazie per l'idea.. mi sembra un pò complicata , comunque adesso provo a implementarla.:fagiano:

recoil
16-10-2007, 15:22
se non esiste già fai una piccola classe che contenga i tre valori RGB e che ti consenta di ottenere un valore unico per la scala di grigio.
devi fare operazioni tipo dithering sull'immagine? perché attenzione, non tutte le elaborazioni si fanno sul singolo pixel senza considerare quelli che stanno attorno

xirc85
16-10-2007, 15:25
Io pensavo di fare una cosa di questo tipo: estrarre i tre valori rgb, metterli in scala di grigio, poi cercarmi il valore massimo e quello minimo, farmi la media e se il valore è sotto o sopra la media metterlo direttamente in nero o in bianco...
è una cretinata??

andbin
16-10-2007, 15:33
Nota che le percentuali che ho indicato non sono "sparate" a caso. Sono le percentuali "standard" che rispecchiano la sensibilità dell'occhio umano ai tre colori primari rosso/verde/blu.

E comunque non devi fare complicate operazioni in floating-point! Una volta che hai "isolato" i 3 valori RGB, li moltiplichi rispettivamente per 30, 59 e 11, fai la somma, poi dividi il tutto per 100. Tutte operazioni "intere".

recoil
16-10-2007, 15:34
viene una schifezza purtroppo, ti ritrovi con delle grosse zone di nero facendo così. te lo dico perché me ne sono occupato per lavoro, dovevo convertire immagini da colore/grigi a bianco e nero

devi utilizzare degli algoritmi per il dithering, però per farlo non puoi leggere un pixel alla volta.
ad esempio puoi usare questo http://en.wikipedia.org/wiki/Floyd-Steinberg_dithering

non posso darti il mio codice perché l'ho usato per lavoro però puoi trovare delle implementazioni open source, ad esempio nella libreria netpbm. non è niente di complicato da capire e implementare :)

quello che succede è che viene introdotto "rumore" nell'immagine e in questo modo puoi passare da una RGB a un'immagine "puntinata", che ti assicuro è di qualità piuttosto buona se non la ingrandisci troppo. senza quel rumore casuale dovresti basarti sul valore del pixel ma avresti, come ti dicevo, zone nere o bianche a blocchi.
io l'ho impiegato per un fax e la stampa che ottengo a partire da un'immagine a colori è di buona qualità

xirc85
16-10-2007, 15:37
ma comunque il fatto di "discriminare" se un pixel deve essere messo in bianco o in nero va bene basandosi sulla "tonalita media" (non so se mi spiego...) che è presente nell'immagine?

recoil
16-10-2007, 15:38
ma comunque il fatto di "discriminare" se un pixel deve essere messo in bianco o in nero va bene basandosi sulla "tonalita media" (non so se mi spiego...) che è presente nell'immagine?

cosa intendi per "tonalità media"?

xirc85
16-10-2007, 15:47
chiedo scusa se ho fatto una domanda alla quale avevate già risposto, ma ho avuto problemi di refresh della pagina...:fagiano:


per quello che ho definito come "tonalità media" intendo un valore rgb che sia equamente distante dagli estremi che sono realmente presenti nell'immagine in quanto non posso sapere a priori quale è il valore più chiaro e quello più scuro... (non so se mi sono spiegata meglio...)
le immagini che tratto io, in pratica sono delle fotografie di codici a barre (in realtà sono una specie...) e quindi sono prevalentemente in bianco e nero...
In questo caso devo comunque fare un'algoritmo di dithering?

recoil
16-10-2007, 15:52
uhm con un codice a barre probabilmente no, avrai valori molto sopra e molto sotto il tuo threshold, che probabilmente potrai tenere costante conoscendo le caratteristiche dell'immagine
il dithering comunque non dovrebbe disturbarti, nelle zone nere non mette puntini bianchi a casaccio. sarebbe un costo inutile.

se devi occuparti di immagini più comuni, come una foto, il dithering diventa obbligatorio se vuoi passare al bw

andbin
16-10-2007, 15:55
ma comunque il fatto di "discriminare" se un pixel deve essere messo in bianco o in nero va bene basandosi sulla "tonalita media" (non so se mi spiego...) che è presente nell'immagine?Se devi ottenere una immagine in bianco/nero, allora è giusto quello che ha detto recoil. Hai bisogno di effettuare il dithering per ottenere dei buoni risultati.

Ti mostro cosa succederebbe (qui le immagini in b/w le ho fatte con un programma di grafica ma il concetto non cambia):

immagine originale:
http://img153.imageshack.us/img153/9276/catcva4.jpg

immagine bianco/nero con la riduzione "nearest color" (in pratica quello che stavi dicendo tu, stabilisci se un colore è più vicino al nero o al bianco):
http://img89.imageshack.us/img89/535/catbwcx4.gif

immagine bianco/nero con la riduzione con dithering "Floyd-Steinberg":
http://img140.imageshack.us/img140/2904/catbwdithbl1.gif

Nota il notevole miglioramento con il dithering.

xirc85
16-10-2007, 16:02
Quindi in teoria, potrei farne a meno... anche perchè l'unico "disturbo" sulla foto potrebbe essere al massimo un'ombra o un riflesso e non dovrebbe crearmi dei grossi problemi.... credo:stordita:

xirc85
17-10-2007, 08:13
ho provato a mettere in scala di grigi l'immagine, eseguendo l'algoritmo suggeritomi...
Ora però ho un piccolo problema, per la creazione dell'immagine. Infatti per la creazione di un'oggetto Image devo passare al metodo(oltre ad altri parametri che non sono un problema....) un array contenente una serie di valori ARGB e quindi riportarlo nella forma originaria...
La mia domanda è quindi questa: posso ottenere un'immagine in scala di grigi mettendo come coordiante rgb le percentuali date??
Cioè una cosa del tipo AA(rr*30/100)(gg*59/100)(bb*11/100) mi fa ottenere la stessa immagine in scala di grigi oppure scombino tutto?????:stordita:
Grazie!