 
View Full Version : [JAVA]: acquisizione punti!
Buongiorno a tutti !! :help: 
Devo acquisire dei punti da un'immagine; devono essere equidistanziati, e considerando che l'immagine è di N colonne ed M righe, la distanza tra i punti sull'asse x è di N/k, sull'asse y di M/k; con k il numero di punti che l'utente vuole prendere.
Come posso fare? :confused: 
Grazie  in anticipo!!
Se carichi l'immagine come BufferedImage (ImageIO.read) puoi accedere ai singoli pixel in base alle loro coordinate:
Color p = image.getRGB(x, y)
X sarebbe la colonna e Y la riga. Non ti resta quindi che stabilire quali siano le X e le Y dei pixel che vuoi prendere (considare che le dimensioni dell'immagine in pixel le hai con image.getWidth() e image.getHeight())
Se invece i punti da acquisire non sono pixel ma figure geometriche rappresentate dalle immagini allora ti serve un algoritmo di riconoscimento di quelle figure (ma dalla descrizione propenderei per i pixel).
Esatto l'immagine la prendo con un BufferedImage.. in questo caso non mi serve accedere ai pixel come rgb, perchè è già classificata in urbano e non urbano quindi bianco e nero.
Il problema è riuscire a prenderli equidistanziati. Se l'immagine è di dimensione M righe per N colonne e ad esempio l'utente prende k^2 punti, sò che il punto kij avrà coordinate [N/(2k)+(i-1)*(N/k), M/(2k)+(j-1)*(M/k)]
Be', sei a cavallo, quelle due equazioni le puoi usare direttamente.
N è image.getWidth(), M è image.getHeight(), la prima ti da la X, la seconda la Y.
Prima ho sbagliato a dire:
Color p = image.getRGB(x, y)
in realtà è
int colore = image.getRGB(x, y)
Nel tuo caso se colore == zero sai che il pixel indica una zona extraurbana.
Giusto ora l'ho fatto.. ;)  (tra l'altro l'immagine è tiff e ho dovuto installare il plug-in apposta) .. comunque ottengo :
run:
k=numero punti per righe 2
z=numero punti per colonne 2
distanza in verticale 2053 
distanza in orizz 1990
1021865 -1021865 
-1020870 1020870
le prime cose le ho stampate solo per vedere se funzionava tutto.. la distanza in verticale si intende tra i punti (equidistanziati), così come quella in orizzontale.. ma i valori che mi trova 1021865 ... ? porta pazienza..hanno senso?
ripeto, l'immagine è in bianco e nero perchè è già classificata in urbano e non urbano..quindi faccio come mi hai detto sopra..ma questi valori sono la posizione quindi?!
I valori sono giusti, nel senso di giusto che può darci un PC: matematicamente inoppugnabile. Che poi siano quelli che ci servono è tutto un altro paio di maniche.
I valori non hanno senso se dovrebbero essere quelli delle coordinate dei pixel e sforano dall'area dell'immagine.
Già il fatto che siano negativi dovrebbe farci drizzare le orecchie.
Siamo sicuri della logica di quelle equazioni?
Le coordinate dei punti sono corrette (le ho già fatte vedere al prof di telerilevamento); comunque l'immagine è di 4107 di altezza x 3980di larghezza.
 .. allego solo il metodo actionPerformed del pulsante acquisisci che l'utente vede a video  ..se hai tempo di dare un'occhiata
Quando parliamo di coordinate corrette parliamo di questi valori?
1021865 -1021865 
-1020870 1020870
Se la risposta è NO, allora mi sono perso.
Se fosse Sì allora direi che parliamo di uno spazio di coordinate diverso da quello dell'immagine. Nel secondo caso basta applicare alle coordinate la matrice di trasformazione che faccia coincidere l'origine del loro spazio con quello dei pixel dell'immagine. Cioè devi fare una divisione e una somma ma "matrice di trasformazione" fa molto più profescional.
Sono proprio quei valori che non mi piacciono :nono: 
Intanto provo ad andare avanti, in caso scrivo più tardi o domani
GRAZIE mille!!
Cioè in pratica io devo prendere il numero di punti che dice l'utente .. ad esempio 2x2 quindi 4 punti totali, ma come può essere anche 3x5 ..
una volta presi devo sapere se quei punti sono urbani o non urbani..per dopo poterli utilizzare nel programma! questi valori non mi servono
N.B. : urbano=255, non urbano= 0
Sicuro di dover usare z?
Cioè, non è che devi dire:
k = altezza * larghezza
e poi:
puntox = (righe / (2*k)) + ((i -1) * distanzaX)
puntoy = (colonne / (2*k)) + ((j-1) * distanzaY)
Perchè non vedo "z" nelle equazioni.
Non ci avevo pensato, ho provato ma mi dà comunque dei valori negativi.
Domani riguardo questo problema da capo e vediamo cosa mi salta in mente; sulle coordinate del punto sono sicurA perché le ho fatte controllare prima di iniziare. 
Grazie di nuovo :)
Carta e penna alla mano, era tutto giusto.
Giusto dividere k in k e z, giusta la formula. L'intoppo è negli indici (in matematica si dice di solito "per ogni Y da 1 a N", in Java si parte (di solito) da 0.
Nella formula il "-1" sta lì proprio perchè "si parte da 1".
Il tutto scoperto con carta e penna quadrettata ovviamente, io la formula la leggo come "piripicchio pacchio paccchio -1".
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication76;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Scanner;
/**
 *
 * @author pgi
 */
public class JavaApplication76 {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] commandLine) {
        Scanner in = new Scanner(System.in);
        System.out.println("Inserire il numero di colonne dell'immagine e premere invio");
        int n = Integer.parseInt(in.nextLine());
        System.out.println("Inserire il numero di righe dell'immagine e premere invio");
        int m = Integer.parseInt(in.nextLine());
        System.out.println("Inserire il numero di punti per riga da considerare e premere invio");
        int k = Integer.parseInt(in.nextLine());
        System.out.println("Inserire il numero di punti per colonna da considerare e premere invio");
        int z = Integer.parseInt(in.nextLine());
        Point2D[][] punti = new Point2D[k][z];
        for(int i = 1; i <= k; i++) {
            for(int j = 1; j <= z; j++) {
                Point punto = new Point();
                punto.x = (n / (2 * k) + (i-1) * (n / k));
                punto.y = (m / (2 * z) + (j-1) * (m / z));
                punti[i-1][j-1] = punto;
                System.out.println(punto);
            }
        }
    }
}
2 note. 
1) C'è un problema di divisioni intere che mina la precisione delle coordinate individuate: i conti dovresti farli in float o double, basterebbe dichiarare n ed m come float o double, le conversioni implicite fanno il resto, e poi andresti ad arrotondare quando dalle coordinate passi ai pixel.
2) Per ragioni di performance "punti" sarebbe meglio che fosse un array monodimensionale con accesso subscript anzichè un bidimensionale. Senza raccontarti la storia dell'orso, significa che:
        Point2D[][] punti = new Point2D[k][z];
        for(int i = 1; i <= k; i++) {
            for(int j = 1; j <= z; j++) {
                Point punto = new Point();
                punto.x = (n / (2 * k) + (i-1) * (n / k));
                punto.y = (m / (2 * z) + (j-1) * (m / z));
                punti[i-1][j-1] = punto;
                System.out.println(punto);
            }
        }
è come dire:
        Point2D[] ps = new Point2D[k*z];
        for(int w = 0; w < ps.length; w++) {
            int i = 1 + (w % k);
            int j = 1 + (w / k);
            Point punto = new Point();
            punto.x = (n / (2 * k) + (i-1) * (n / k));
            punto.y = (m / (2 * z) + (j-1) * (m / z));
            ps[w] = punto;
            System.out.println(punto);
        }
Ma il secondo "va più veloce" (anche se il primo può gestire matrici di dimensioni superiori).
banryu79
03-05-2012, 09:16
O.T.:
Scusate l'intrusione, ma ho una piccola curiosità personale da soddisfare:
2) Per ragioni di performance "punti" sarebbe meglio che fosse un array monodimensionale con accesso subscript anzichè un bidimensionale. Senza raccontarti la storia dell'orso, significa che:
PGI, che significa "accesso subscript"? Dove hai trovato questo modo di dire?
Kernighan & Ritchie, The C Programming Language (l'edizione che ho io è del 1453 d.C.)
Purtroppo oggi sono rimasta tutto il giorno in uni..e non ho avuto tempo di guardare il forum.. comunque.. devo provare il secondo metodo! ..è vero sulla prima cosa, il -1 non andava -.- .. 
Per l'array punto, proverò il secondo metodo, perchè oltretutto successivamente devo poter fare un getRGB() su ogni punto che prendo! per poi fare quel confronto che mi dicevi all'inizio.... che ora come ora ho qualche difficoltà ad applicare
Allora inserendo "punto" come array monodimensionale, come dici, l'output del programma è : 
run:
k=numero punti per righe 3
z=numero punti per colonne 3
distanza in verticale 1369
distanza in orizz 1326
java.awt.Point[x=684,y=663]
java.awt.Point[x=684,y=1989]
java.awt.Point[x=684,y=3315]
java.awt.Point[x=2053,y=663]
java.awt.Point[x=2053,y=1989]
java.awt.Point[x=2053,y=3315]
java.awt.Point[x=3422,y=663]
java.awt.Point[x=3422,y=1989]
java.awt.Point[x=3422,y=3315]
 
Questo se prendo appunto 3x3 punti sull'immagine! Perfetto il fatto che sono equidistanti, e ok la stampa ! grazie mille :) !! 
Successivamente una volta rilevati questi punti, SOLO di questi punti (che sono di volta in volta quanti ne chiede l'utente), devo sapere se sono 0 oppure 255 .... 
Grazie di nuovo! mi hai già dato un aiuto enorme! :)
P.S. : sono stata autorizzata ad usare l'immagine in formato bitmap e non tiff !! meglio !
Potresti andare a cercare lo 0 e il 255 ma c'è un metodo precotto in BufferedImage che, al costo di una conversione tra spazi di colore, ti permette di fare tutto con tre righe.
Definisci due costanti bianco e nero così:
final int BIANCO = Color.WHITE.getRGB();
final int NERO = Color.BLACK.getRGB();
Fatto questo per ogni punto pigli il pixel nell'immagine:
int pixelColor = immagine.getRGB(punto.x, punto.y);
e dal confronto con le costanti sai se è bianco o nero:
if(pixelColor == BIANCO) {
} else if(pixelColor == NERO) {
}
Altrimenti devi andare a frugare nel raster dell'immagine ma quello potrebbe non contenere valori da 0 a 255, dipende da come è salvata l'immagine. Siccome bianco e nero restano bianco e nero anche in spazi di colore diversi, usando getRGB le api fanno la conversione in sRGB e tu puoi sapere se il pixel sia bianco o nero a prescindere dalla profondità di colore con cui l'immagine in input è stata salvata.
Ovvero cosi mi svincoli dal fatto di guardare se all'interno dell'immagine ci sono int, char... ? 
Wow bell'idea domani provo! :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.