Comparar imágenes Java - formas

¿Hola experto como estas? Espero que todo bien,me sirvio muchisimo la explicacion que me diste de mi anterior pregunta (http://www.todoexpertos.com/mitodoexpertos/user/questions/view/2055999/comparar-imagenes-en-java) es por ello que vuelvo nuevamentea traerte un pequeño problema. Lo que necesito hacer es comparar 2 imágenes, es decir comparar una porción de una imagen (A) con cualquier otra porción de una imagen (B) y determinar si se parecen, con la anterior pregunta que me respondiste me diste una solución comparando pixeles, ahora necesito saber como puedo hacer para comparar objetos que se encuentren en la imagen es decir si en la imagen (A) en la izq superior izq tengo un caballo o cualquier otro "objeto", que la compare con la imagen (B) en la cual en el centro de la misma se encuentra el mismo "objeto" en ese caso esa porciones de imágenes serian iguales. Mi idea es que tengo que hacer algo parecido a lo que seria un sistema experto de diagnostico de imágenes, la parte de educcion del experto ya lo tengo estoy viendo como hacer la parte de comparación de las imágenes, para que dicha comparación sea lo más exacta posible, nuevamente muchas gracias por responder mi anterior pregunta y espero tu respuesta. Un abrazo Fernando
P/D: espero haberme explicado bien, caso contrario no dudes en pedirme que me explaye más. Gracias...

1 respuesta

Respuesta
1
Gracias por tu confianza en mi para ayudarte con tu problema... tengo una pregunta: ¿Las porciones de las 2 imágenes A y B están definidas? (Es decir, ¿el usuario te dice de alguna forma cuales son las porciones A y B donde quieres comparar) o tu programa tiene que escanear todas las posibles áreas de la imagen A para buscar si se parece a cualquier otra porción de la imagen B?
Hola experto, como lo había pensado en un principio era que el programa se encargue de escanear todo, es decir que se encargue de hacer todo el trabajo, esa era la intención pero con tu pregunta surgió otra posibilidad (que el usuario seleccione un área para comparar), me inclino a la primera opción pero te agradecería que me explicaras como hacer ambas, para tener más opciones para el usuario. Desde ya muchas gracias por tu ayuda. Un abrazo Fernando
Lo que quieres hacer es bastante complicado... Tu pregunta entraría más en el área de la inteligencia artificial, ya que lograr eso requiere de un algoritmo complejo. Pues muchas áreas de una imagen podrías ser indenticas a otras áreas de otra imagen, por ejemplo si amabas tienen el mismo color de fondo... así que escanear toda la imagen para encontrar patrones no creo que sea la mejor solución... Seria más fácil si el usuario indicara un rectángulo de la imagen A y buscar si ese mismo rectángulo es encontrado en la imagen B... en ese caso en la respuesta (http://www.todoexpertos.com/mitodoexpertos/user/questions/view/2055999/comparar-imagenes-en-java) tienes la solución... lo único que tienes que cambiar es que tienes que leer dos imágenes diferentes y pedir al usuario que especifique el rectángulo 1 para buscarlo en la imagen B.
Hola experto nuevamente estas en lo correcto, con respecto a lo de la IA estuve leyendo bastante y creo encarar el tema por el lado de las redes bayesianas (con lo cual me sirve muchísimo tu anterior explicación), me incline a hacerlo como dijiste que el usuario seleccione una porción de imagen y de ahí se realize la comparación, ahora mi pregunta es como puedo hacer para que un usuario una vez cargada la imagen (A) este pueda seleccionar una porción de la imagen (A) mediante el mouse y utilizar esa porción para la comparación con la imagen (B), y como puedo hacer para rotar una imagen en el caso de que las porciones sean iguales pero estén en diferentes ángulos, lo que quiero hacer es rotar la imagen (suponiendo que se encuentra en un eje de coordenadas cartesianas) un grado por vez, hasta que las porciones de imágenes comparadas estén en el mismo angulo o sentido y el programa me devuelva que son idénticas. Espero no molestarte con mis preguntas, estoy investigando como se hace lo que te pido que me expliques, pero la verdad no entiendo muy bien como hacerlo es por ello que te pido ayuda. Desde ya muchas gracias nuevamente y espero tu respuesta. Un abrazo Fernando
Disculpa la demora... estaba en un viaje.. ¿aun necesitas ayuda?
Hola experto, todavía necesito ayuda y te agradecería que me dieras una mano, estuve bastante ocupado con el tema de la IA y me esta saliendo bien por ahora je je, espero tu respuesta un abrazo Fernando
Este programa permite seleccionar con el mouse un rectángulo dentro de la imagen:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class SaveImage extends Component {
// Doble buffer para mejor rendimiento
private BufferedImage bi, biFiltered;
int w, h;
JSpinner campoX = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1));
JSpinner campoY = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1));
JSpinner campoWidth = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1));
JSpinner campoHeight = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1));
public SaveImage() {
this.addMouseMotionListener(createMouseMotionListener());
this.addMouseListener(createMouseListener());
try {
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(this);
bi = ImageIO.read(jfc.getSelectedFile());
w = bi.getWidth(null);
h = bi.getHeight(null);
if (bi.getType() != BufferedImage.TYPE_INT_RGB) {
BufferedImage bi2 =
new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics big = bi2.getGraphics();
big.drawImage(bi, 0, 0, null);
biFiltered = bi = bi2;
}
} catch (Exception e) {
System.out.println("Image could not be read");
System.exit(1);
}
}
private MouseListener createMouseListener() {
MouseAdapter adapter = new MouseAdapter(){
public void mouseReleased(MouseEvent e){
esModoSeleccion = false;
}
public void mousePressed(MouseEvent e){
esModoSeleccion = true;
seleccion.setLocation(e.getPoint());
seleccion.setSize(0, 0);
initialPoint = e.getPoint();
}
};
return adapter;
}
private Rectangle seleccion = new Rectangle(0,0,0,0);
private boolean esModoSeleccion = false;
private Point initialPoint = new Point(0,0);
private MouseMotionListener createMouseMotionListener() {
MouseMotionListener adapter = new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
if ( esModoSeleccion ){
if ( e.getPoint().x > initialPoint.x ) seleccion.width = e.getPoint().x - initialPoint.x;
if ( e.getPoint().y > initialPoint.y ) seleccion.height = e.getPoint().y - initialPoint.y;
if ( e.getPoint().x < initialPoint.x ) {
seleccion.width = initialPoint.x - e.getPoint().x;
seleccion.x = e.getPoint().x;
}
if ( e.getPoint().y < initialPoint.y ){
seleccion.height = initialPoint.y - e.getPoint().y;
seleccion.y = e.getPoint().y;
}
campoX.setValue(new Integer(seleccion.x));
campoY.setValue(new Integer(seleccion.y));
campoHeight.setValue(new Integer(seleccion.height));
campoWidth.setValue(new Integer(seleccion.width));
repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
};
return adapter;
}
public Dimension getPreferredSize() {
return new Dimension(w, h);
}
public void paint(Graphics g) {
g.drawImage(biFiltered, 0, 0, null);
Graphics2D g2d = (Graphics2D)g;
Rectangle2D rectangle = new Rectangle2D.Double(seleccion.getX(),seleccion.getY(),seleccion.getWidth(),seleccion.getHeight());
g2d.setColor (Color.blue);
g2d.setStroke (new BasicStroke(
1f,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND,
1f,
new float[] {2f},
0f));
g2d.draw (rectangle);
}
public static void main(String s[]) {
JFrame f = new JFrame("Save Image Sample");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
SaveImage si = new SaveImage();
f.add("Center", si);
f.add("East",si.createSidePanel());
f.pack();
f.setVisible(true);
}
private JPanel createSidePanel(){
JPanel sidePanel = new JPanel();
JLabel label = new JLabel("Selected rectangle:");
sidePanel.add(label);
sidePanel.add(createLineBreak());
label = new JLabel("X:");
sidePanel.add(label);
sidePanel.add(campoX);
sidePanel.add(createLineBreak());
label = new JLabel("Y:");
sidePanel.add(label);
sidePanel.add(campoY);
sidePanel.add(createLineBreak());
label = new JLabel("Width:");
sidePanel.add(label);
sidePanel.add(campoWidth);
sidePanel.add(createLineBreak());
label = new JLabel("Height:");
sidePanel.add(label);
sidePanel.add(campoHeight);
sidePanel.add(createLineBreak());
JButton boton = new JButton("
<html>
Actualizar<br />rectangulo
</html>
");
boton.addActionListener(createActionListener());
sidePanel.add(boton);
sidePanel.add(createLineBreak());
sidePanel.setPreferredSize(new Dimension(150,500));
return sidePanel;
}
private ActionListener createActionListener() {
ActionListener adapter = new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
seleccion.height = ((Integer)campoHeight.getValue()).intValue();
seleccion.width = ((Integer)campoWidth.getValue()).intValue();
seleccion.x = ((Integer)campoX.getValue()).intValue();
seleccion.y = ((Integer)campoY.getValue()).intValue();
repaint();
}
};
return adapter;
}
private static Component createLineBreak(){
return Box.createRigidArea(new Dimension(150, 0));
}
}
Y este otro te permite seleccionar una imagen y rotarla en un angulo de 45 grados... combinando estos dos programas tendrías todo lo que necesitas para resolver tu problema:
/*
Java Media APIs: Cross-Platform Imaging, Media and Visualization
Alejandro Terrazas
Sams, Published November 2002,
ISBN 0672320940
*/
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
/**
* RotateImage45Degrees.java - 1. scales an image's dimensions by a factor of
* two 2. rotates it 45 degrees around the image center 3. displays the
* processed image
*/
public class RotationTest extends JFrame {
private Image inputImage;
private BufferedImage sourceBI;
private BufferedImage destinationBI = null;
private Insets frameInsets;
private boolean sizeSet = false;
public RotationTest() {
addNotify();
frameInsets = getInsets();
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(this);
String imageFile = jfc.getSelectedFile().getAbsolutePath();
inputImage = Toolkit.getDefaultToolkit().getImage(imageFile);
MediaTracker mt = new MediaTracker(this);
mt.addImage(inputImage, 0);
try {
mt.waitForID(0);
} catch (InterruptedException ie) {
}
sourceBI = new BufferedImage(inputImage.getWidth(null), inputImage
.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) sourceBI.getGraphics();
g.drawImage(inputImage, 0, 0, null);
AffineTransform at = new AffineTransform();
// scale image
//at.scale(2.0, 2.0);
// rotate 45 degrees around image center
at.rotate(45.0 * Math.PI / 180.0, sourceBI.getWidth() / 2.0, sourceBI
.getHeight() / 2.0);
/*
* translate to make sure the rotation doesn't cut off any image data
*/
AffineTransform translationTransform;
translationTransform = findTranslation(at, sourceBI);
at.preConcatenate(translationTransform);
// instantiate and apply affine transformation filter
BufferedImageOp bio;
bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
destinationBI = bio.filter(sourceBI, null);
int frameInsetsHorizontal = frameInsets.right + frameInsets.left;
int frameInsetsVertical = frameInsets.top + frameInsets.bottom;
setSize(destinationBI.getWidth() + frameInsetsHorizontal, destinationBI
.getHeight()
+ frameInsetsVertical);
setVisible(true);
}
/*
* find proper translations to keep rotated image correctly displayed
*/
private AffineTransform findTranslation(AffineTransform at, BufferedImage bi) {
Point2D p2din, p2dout;
p2din = new Point2D.Double(0.0, 0.0);
p2dout = at.transform(p2din, null);
double ytrans = p2dout.getY();
p2din = new Point2D.Double(0, bi.getHeight());
p2dout = at.transform(p2din, null);
double xtrans = p2dout.getX();
AffineTransform tat = new AffineTransform();
tat.translate(-xtrans, -ytrans);
return tat;
}
public void paint(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
if (destinationBI != null)
g.drawImage(destinationBI, frameInsets.left, frameInsets.top, this);
}
public static void main(String[] args) {
new RotationTest();
}
}
Espero que esto te sirva y no olvides finalizar la pregunta.
Hola experto muchísimas gracias nuevamente por responderme tan rapido, me surgió una duda con respecto al programa donde selecciono una porción de la imagen con el mouse, funciona perfectamente salvo cuando selecciono con el mouse la porción de la imagen que deseo, hago click en el botón actualizar rectángulo y no sucede nada, lo que deseo es que se actualize la imagen cargada(entera) con la porción que determine con la selección y poder guardar la nueva imagen es decir guardar (en archivo JPG) la porción de la imagen seleccionada. Espero tu respuesta, nuevamente gracias. Un abrazo Fernando
Seria bueno que finalizaras esta respuesta y crearas otra pregunta para guardar la imagen seleccionada por el rectángulo ya que eso es otro tema diferente.
Muchas gracias experto como siempre me sacaste del problema que tenia, y muchas gracias por compartir tus conocimimientos de java con el resto de nosotros! Espero que sigas así...

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas