738.435 temas | 5.156.402 mensajes | seremos forros, pero somos una bocha
Viejo scrub dijo: 23.08.10
Buenas, el tema es que quiero empezar un programa en Java estilo visor de imágenes con operaciones matemáticas simples, como por ejemplo sumar o restar imágenes mediante el uso del AND, OR, XOR, etc.
La cosa es que para hacer esto necesito subir una imágen a Java y guardarla pixel por pixel en un array, y no se como hacerlo. Estuve leyendo los tutoriales de Java, y lo sigo haciendo, pero todavía no encontré nada al respecto.
Agradecería si alguien me puede facilitar como hacerlo. Uso el NetBeans IDE 6.7.1, asi que si me pueden explicar con las herramientas comúnes de Java, y no de la versión FX o alguna otra, se los agradeceria muchísimo.
Al programa lo necesito para un final.
Si me pueden habilitar información o tutoriales sobre el tema también les estaría agradecido.

Cualquier cosa que encuentre la voy a subir acá por si algun futuro alguien necesita de esta ayuda.

EDITADO:

Finalicé el programa. Si alguien necesita ejemplos de procesamiento de imágenes me contacta por M.P. y con gusto les comparto lo que hice.

Editado por scrub: 19.12.10 a las 16:55

10 Comentarios | Registrate y participá

Viejo el_bot dijo: 23.08.10
http://www.dreamincode.net/forums/to...o-pixel-array/

Mira el 3er o 4to post; dice algo asi

If you use a BufferedImage object to store the image in java then there are methods associated with that class to convert the image to an array of RGB values.

For example

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

File file = new File("image.jpg");
BufferedImage img;
img = ImageIO.read(file);

Then you have methods like img.getRGB() which returns an integer array.
I guess that's what you need to manipulate the values to binary or integer.
ImageIO.read will read most common imagefile-types (BMP, JPG, et.c)

I hope this was useful.
Esto es, usas ImageIO para a partir de un archivo te genere una instancia de BufferedImage (una subclase de Image), despues usa alguno de los metodos getRGB (hay dos, uno que te retorna un solo valor y otro una matriz; para este utlimo tenes que especificar que region te tiene que retornar). Investiga un poco estas clases yy en particualas relacionadas : Raster y ColorModel.
(fijate que getRGB en BufferedImge retonra un solo int por pixel; ese int lo tenes que "partir" en componente R, G y B y posiblemente, el indice de transparencia; pero como se tienen que interpretar estos valores exactamente dependen del ColorModel)

http://download.oracle.com/javase/1....eredImage.html
Viejo scrub dijo: 23.08.10
Originalmente publicado por el_bot Ver mensaje
http://www.dreamincode.net/forums/to...o-pixel-array/

Mira el 3er o 4to post; dice algo asi


Esto es, usas ImageIO para a partir de un archivo te genere una instancia de BufferedImage (una subclase de Image), despues usa alguno de los metodos getRGB (hay dos, uno que te retorna un solo valor y otro una matriz; para este utlimo tenes que especificar que region te tiene que retornar). Investiga un poco estas clases yy en particualas relacionadas : Raster y ColorModel.
(fijate que getRGB en BufferedImge retonra un solo int por pixel; ese int lo tenes que "partir" en componente R, G y B y posiblemente, el indice de transparencia; pero como se tienen que interpretar estos valores exactamente dependen del ColorModel)

http://download.oracle.com/javase/1....eredImage.html
Si, hoy encontré algo parecido, un flaco en un foro tiro un par de algorítmos usando el getRGB y el BufferedImage. Y también como cargarlo en un arreglo, que lo voy a necesitar para hacer la comparación con las dos imagenes. Igual voy a usar blanco y negro y escala de grises, sino es un viaje implementarlo, por el tema de las funciones.
Si lo saco andando lo subo, no quiero poner algo que al final no ande. Gracias por la info.
Viejo scrub dijo: 02.12.10
Pido ayuda de nuevo.
El tema es que quiero con el JFileChooser elegir una imagen y manipularla, osea, guardarla en una variable tipo file, y después poder usarla. Si alguien me puede dar una mano, estaría agradecido.
Viejo el_bot dijo: 02.12.10
siempre busca en la documentación oficial; en el caso de Java esta bastante bien hecha, y en general hay buenos ejemplos.
http://download.oracle.com/javase/1....leChooser.html

Código:
      JFileChooser chooser = new JFileChooser();
      // Note: source for ExampleFileFilter can be found in  FileChooserDemo,
      // under the demo/jfc directory in the Java 2 SDK, Standard Edition.
      ExampleFileFilter filter = new ExampleFileFilter();
      filter.addExtension("jpg");
      filter.addExtension("gif");
      filter.setDescription("JPG & GIF Images");
      chooser.setFileFilter(filter);
      int returnVal = chooser.showOpenDialog(parent);
      if(returnVal == JFileChooser.APPROVE_OPTION) {
          System.out.println("You chose to open this file: " +
              chooser.getSelectedFile().getName());
    }
para cada uno de los metodos mira la documentación de los mimos , pero básicamente, "parent" es la ventana actual que invoca al dialogo (por ej lo general una JFrame), pero puede ser tranquilamente null (mira los otros constructories).
Los filtros que no son estrictamente necesarios, pero en el caso de imagenes tiene sentido. Fijaque en el ejemplo utiliza una clase ExampleFilterFile que esta definida en otro ejemplo de la documentacion.... Aca tenes el codigo http://download.oracle.com/javase/tu...ooserDemo.java ; y aca la documentación general de como usar FileChooser http://download.oracle.com/javase/tu...lechooser.html
Desde ahi podes llegar directamente a un ejemplo de filter un que funciona solo para imagenes http://download.oracle.com/javase/tu...ageFilter.java

Ok, con o sin filtros, una vez que el dialogo retorna y una vez chequeado que el valor de retorno esta bien (APPROVE_ACTION); mediante el método getSelectedFile obtenes el archivo seleccionada (una instancia de File) ; y mediante getSelectedFiles obtenes un arreglo con todos archivos seleccionados, si que la opción de múltiple selección estaba activada.
Viejo scrub dijo: 03.12.10
Si, los ví a esos ejemplos, y traté de implementar el filter pero me tiraba un error. Igual creo que fue culpa mía porque hice un poco de quilombo y mezclé códigos.
Ya logré pasar una foto a un arreglo y logré mostrarla en un JPanel (con dirección inmediata). Ahora me fijo si con el getSelectedFile me lo acepta y me lo muestra en pantalla.
Viejo scrub dijo: 17.12.10
Nuevamente necesito ayuda, me está constando un huevo esta. La cosa es que hice un algoritmo que hace una resta entre imagenes, resta pixels uno por uno, si es menor a 0 lo iguala a 0, entonces si a una foto blanca le resto una con un circulo negro en el medio deberian invertirse los colores. El problema es con el Raster. Cunado hago la resta obtengo un array que es de tipo float[] conteniendo los pixels. Pero no sé como setearlo ahora! Tengo que setear el raster y los pixels, por favor estaría agradecido si alguien em da una mano:

public BufferedImage resta(URL url1, URL url2) throws IOException{


BufferedImage imagenBuffer1 = new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );
BufferedImage imagenBuffer2 = new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );
BufferedImage restado= new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );

// RenderedImage rendImage = crearImagen();

File imagenResta=new File("c:/imagenResta.jpg");

// ImageIO.write(rendImage, "jpg", imagenResta);

WritableRaster r;


imagenBuffer1 = ImageIO.read(url1);
imagenBuffer1.getRaster().getPixels(0, 0, 256, 256, pixels1);
imagenBuffer2 = ImageIO.read(url2);
imagenBuffer1.getRaster().getPixels(0, 0, 256, 256, pixels2);


for (int x = 0; x <3*65536 ; x++) {
transitorio[x]=pixels1[x]-pixels2[x];
if(transitorio[x]<0){
transitorio[x]=0;
}
pixelsResta[x]=transitorio[x];
}


restado.getRaster().setPixels(0, 0, 255, 255, pixelsResta); //Esto es lo que yo hacia pero me parece que esta mal.

ImageIO.write(restado, "jpg", imagenResta);

return restado;
}

Editado por scrub: 17.12.10 a las 12:37
Viejo el_bot dijo: 17.12.10
Originalmente publicado por scrub Ver mensaje
Nuevamente necesito ayuda, me está constando un huevo esta. La cosa es que hice un algoritmo que hace una resta entre imagenes, resta pixels uno por uno, si es menor a 0 lo iguala a 0, entonces si a una foto blanca le resto una con un circulo negro en el medio deberian invertirse los colores. El problema es con el Raster. Cunado hago la resta obtengo un array que es de tipo float[] conteniendo los pixels. Pero no sé como setearlo ahora! Tengo que setear el raster y los pixels, por favor estaría agradecido si alguien em da una mano:

public BufferedImage resta(URL url1, URL url2) throws IOException{


BufferedImage imagenBuffer1 = new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );
BufferedImage imagenBuffer2 = new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );
BufferedImage restado= new BufferedImage(256,256,BufferedImage.TYPE_BYTE_GRAY );

// RenderedImage rendImage = crearImagen();

File imagenResta=new File("c:/imagenResta.jpg");

// ImageIO.write(rendImage, "jpg", imagenResta);

WritableRaster r;


imagenBuffer1 = ImageIO.read(url1);
imagenBuffer1.getRaster().getPixels(0, 0, 256, 256, pixels1);
imagenBuffer2 = ImageIO.read(url2);
imagenBuffer1.getRaster().getPixels(0, 0, 256, 256, pixels2);


for (int x = 0; x <3*65536 ; x++) {
transitorio[x]=pixels1[x]-pixels2[x];
if(transitorio[x]<0){
transitorio[x]=0;
}
pixelsResta[x]=transitorio[x];
}


restado.getRaster().setPixels(0, 0, 255, 255, pixelsResta); //Esto es lo que yo hacia pero me parece que esta mal.

ImageIO.write(restado, "jpg", imagenResta);

return restado;
}
En ese codigo hay algo coneptualmente mal... Por un lado definis y crear dos BufferedImages, de cierto tipo (TYPE_BYTE_GRAY; esto es, escala de grises), pero despues esta referenia queda apuntado a otro tipo de BufferedImage, no necesariamente con ese modelo color (el modelo de color a su vez determina el tipo de Raster y el tipo de SampleModel; estos a su vez son los que determinan que es lo que es retornado por getPixel, lo cual no necesariamente es un arreglo RGB por cada pixel; ademas, los valores retorandos por estos no necesariamente son positivos....). La clase especifica a la que va a pertenecer los objetos referenciados por estas variables termina siendo definido por ImageIO.read (lo cual vaya a saber uno que tipo de BufferedImage y SampleModel y ColorModel y Raster crea; seguro que lo infiere del tipo de imagen; por ej, una jpg seguro que no va parar en un BufferedImage de tipo BYTE_GRAY)

Como se debería hacer la verdad que no se, pero como mínimo o tenes que saber que tipo de BufferedImage es retornado desde ImageIO.read (y actuar de acuerdo a esto) o forzar a que la lectura sea generada de tal manera que la imageBuffered final sea de un tipo determinado (o alguna forma de convertir entre distintos tipos de BufferedImage).
Viejo scrub dijo: 17.12.10
Originalmente publicado por el_bot Ver mensaje
En ese codigo hay algo coneptualmente mal... Por un lado definis y crear dos BufferedImages, de cierto tipo (TYPE_BYTE_GRAY; esto es, escala de grises), pero despues esta referenia queda apuntado a otro tipo de BufferedImage, no necesariamente con ese modelo color (el modelo de color a su vez determina el tipo de Raster y el tipo de SampleModel; estos a su vez son los que determinan que es lo que es retornado por getPixel, lo cual no necesariamente es un arreglo RGB por cada pixel; ademas, los valores retorandos por estos no necesariamente son positivos....). La clase especifica a la que va a pertenecer los objetos referenciados por estas variables termina siendo definido por ImageIO.read (lo cual vaya a saber uno que tipo de BufferedImage y SampleModel y ColorModel y Raster crea; seguro que lo infiere del tipo de imagen; por ej, una jpg seguro que no va parar en un BufferedImage de tipo BYTE_GRAY)

Como se debería hacer la verdad que no se, pero como mínimo o tenes que saber que tipo de BufferedImage es retornado desde ImageIO.read (y actuar de acuerdo a esto) o forzar a que la lectura sea generada de tal manera que la imageBuffered final sea de un tipo determinado (o alguna forma de convertir entre distintos tipos de BufferedImage).
Es que los bufferedImage leen dos fotos que están pasadas a escala de grises con el método toGray que trae la clase color, osea que el url1 y el url2 ya estan en tipo TYPE BYTE GRAY.
Supongo que cuando utilizo el read, ya determina que es de dicho tipo, sino como bien decís tendré que forzarla.
Viejo el_bot dijo: 17.12.10
Originalmente publicado por scrub Ver mensaje
Es que los bufferedImage leen dos fotos que están pasadas a escala de grises con el método toGray que trae la clase color, osea que el url1 y el url2 ya estan en tipo TYPE BYTE GRAY.
Supongo que cuando utilizo el read, ya determina que es de dicho tipo, sino como bien decís tendré que forzarla.
en cuanto al tamaño del arreglo del metoto getPixels, no necesariametne es ancho*alto*3; y en realidad no necesariamente te tiene que retornar un arreglo de tipo float; para el caso de escala de grises casi seguroq que retorna un arreglo de tamaño ancho*alto (la escala de grises no requiere tres bandas R, G y B); exiten tres versiones, una que retorna int, otra double y el tercer parametro es opcional; puede ser null (pero si no es null, los datos los almacena en al arreglo que le pasas, y por lo tanto tiene que tener tamaño suficiente de antemano; ademas, por la misma razón, no podes saber realemten cuando valores retorno).

El tema es que los métodos getPixels estan sobrecargados, y si queres pasar null en el tecer parámetro no te va compilar porque Java no va a saber a cual de los 3 estas estas invocando. La forma de forzar la invocación es castear null, como sigue:

Código:
//obtiene la informacion de 256*256 pixeles, pero no necesariamente un
//arreglo de 256*256*3 eleemntos; puede ser del tamaña 256*256, lo cual
//es casi seguro en el caso de BYTE_GRAY
int[] pixelsInt = img.getRaster().getPixels(0,0,256,256, (int[]) null);

//o si no:
double[] pixelsDouble =  img.getRaster().getPixels(0,0,256,256, (double[]) null);

//o si no
 float[] pixelsFloat = img.getRaster().getPixels(0,0,256,256, (float[]) null);
(el cast explicito en el ultimo parámetro es necesario, porque null se puede asignar a cualquier objeto).


la longitudes de los arreglos pixelsInt, pixelsDouble y pixelsFloat en teoria deben ser iguales. En caulquier caso, la logintud real la obtenes usando el campo length; por ej, para restar en 5 a la representación, asumiendo que proviene de una imagen en escala de grises (y también que la escala de grises utiliza un solo valor por pixel) seria algo asi

Código:
int[] pixelsInt = img.getRaster().getPixels(0,0,256,256, (int[]) null);

for (int i = 0; i < pixelsInt.length; i++)
{
   pixelsInt[i] = pixelsInt[i] - 5; 
  //aca podria chequear si es negativo, pero esto solo si los numeros
 //negativos no son validos en el tipo de imagen
}

Finalmente, setPixels, requiere un arreglo de datos cuya estructura sea concordante con la forma en que se almacena los datos en el tipo de la imagen final. Por ej, vos no podes mezclar directamente un arreglo que venga de getPixels de un imagen tipo TYPE_INT_RGB (la cual seguramente va a hacer que retorne 4 elemento por pixel) a una imagen de tipo TYPE_BYTE_GRAY (la cual seguramente espera 1 elemento por pixel).

Herramientas
Iniciar Sesion

Recordarme

Top de Usuarios