Bild in einem anderen Bild suchen

keksdose132

Mitglied
Guten Morgen/Mittag/Abend,
ich möchte überprüfen ob sich ein Bild in einem andren Bild befindet und wenn ja, dessen Koordinaten im anderen Bild auslesen.
Also ob z.B. ein bestimmtes Icon auf dem Desktop vorhanden ist und wenn ja an welcher Stelle.

Dieser Ordner zum Beispiel:

12198

Ist er auf dem Desktop vorhanden?
An welcher Stelle befindet er sich?

keksdose132.
 
ich möchte überprüfen ob sich ein Bild in einem andren Bild befindet und wenn ja, dessen Koordinaten im anderen Bild auslesen.
Also ob z.B. ein bestimmtes Icon auf dem Desktop vorhanden ist und wenn ja an welcher Stelle.
Willst du wirklich untersuchen, ob sich ein Bild in einem anderen Bild befindet? Oder willst du nur überprüfen - wie es dein Beispiel suggeriert - , ob sich ein Icon (unter Windows) auf dem Desktop befindet (dazu könntest du beispielsweise einfach in C:\Users\Peter\Desktop\ nachgucken).
 
Wie ich ihn verstanden habe, will er ein (gleiches oder ähnliches) Bild in einem Bild suchen... und das ist kein leichter Tobak.
 
Willst du wirklich untersuchen, ob sich ein Bild in einem anderen Bild befindet? Oder willst du nur überprüfen - wie es dein Beispiel suggeriert - , ob sich ein Icon (unter Windows) auf dem Desktop befindet (dazu könntest du beispielsweise einfach in C:\Users\Peter\Desktop\ nachgucken).

Ich möchte wirklich nach Bildern bzw. Grafiken suchen und dessen Position ermitteln, um dann z.B. die Distanz zwischen diesen Objekten zu berechnen. Bzw. vielleicht gibt es ja sogar eine bessere Methode um die Distanzen zu berechen, ohne nach Grafiken zu suchen, nur kenne ich keine andere.

Also das ich beispielsweise diese eingezeichnete Distanz in Mario ermitteln kann:

12219
 
Bibs die das können sind hunderte an Megabyte groß, ich denke nicht dass Du in der Lage dazu wärst.
Außerdem wäre es vielmals einfacher das Spiel zu hacken 😀
 
Hat da jemand eine Idee, wie man das ganze umsetzten könnte?
Zähl halt einfach von unten die blauen Pixel.

Java:
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import javax.imageio.ImageIO;
import javax.swing.*;

public class Test {
    private BufferedImage img;
    private Line2D line;

    private class ImagePanel extends JComponent {
        public Dimension getPreferredSize() { return new Dimension(img.getWidth(), img.getHeight()); }
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.drawImage(img, 0, 0, null);
            if (line != null) {
                g2.draw(line);
            }
        }
    }

    public Test(BufferedImage img) { this.img = img; }

    public void run() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        ImagePanel p = new ImagePanel();
        AtomicInteger x = new AtomicInteger();

        Timer t = new Timer(100, e -> {
            Timer tmr = (Timer) e.getSource();
            int cx = x.getAndIncrement();
            if (cx >= img.getWidth()) {
                tmr.stop();
                line = null;
                frame.dispose();
            } else {
                measure(new Point(cx, img.getHeight()));
            }
            p.repaint();
        });
        t.setRepeats(true);

        frame.add(p);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
        t.start();
    }

    public void measure(Point p) {
        int y1 = find(p.x, img.getHeight(), equalColor(new Color(0x63, 0x86, 0xfb), 4));
        int y2 = find(p.x, y1, equalColor(new Color(0x63, 0x86, 0xfb), 4).negate());
        line = new Line2D.Float(p.x, y2, p.x, y1);
    }

    private int find(int x, int bottom, Predicate<Integer> p) {
        for (int y = bottom - 1; y >= 0; y--) {
            if (p.test(img.getRGB(x, y))) {
                return y;
            }
        }
        return -1;
    }

    private Predicate<Integer> equalColor(Color c, double tolerance) {
        return color -> {
            int redDiff = ((color & 0xff0000) >>> 16) - c.getRed();
            int greenDiff = ((color & 0xff00) >>> 8) - c.getGreen();
            int blueDiff = (color & 0xff) - c.getBlue();

            double err = Math.sqrt(redDiff*redDiff + blueDiff*blueDiff + greenDiff*greenDiff);
            return err <= tolerance;
        };
    }
   
    public static void main(String[] args) throws Exception {
        Test app = new Test(ImageIO.read(Test.class.getResource("mario.png")));
        SwingUtilities.invokeLater(() -> app.run());
    }
}
 
Tja, dann musst Du wohl Bilder vergleichen.
Java:
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.beans.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import javax.imageio.ImageIO;
import javax.swing.*;

import java.util.ArrayList;
import java.util.List;

public class Test {
    private BufferedImage template;
    private BufferedImage img;
    private List<Point> positions = new ArrayList<>();

    private class ImagePanel extends JComponent {
        public Dimension getPreferredSize() { return new Dimension(img.getWidth(), img.getHeight()); }
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.drawImage(img, 0, 0, null);

            g2.setColor(Color.GREEN);
            g2.setStroke(new  BasicStroke(2));

            for (Point p : positions) {
                Rectangle2D r = new Rectangle2D.Float(p.x, p.y, 
                        template.getWidth(), template.getHeight());
                g2.draw(r);
            }
        }
    }

    public Test(BufferedImage img, BufferedImage template) {
        this.img = img;
        this.template = template;
    }

    public void run() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        ImagePanel p = new ImagePanel();
        JButton button = new JButton("Find");
        JProgressBar pbar = new JProgressBar();
        button.addActionListener(e -> 
            new Thread(() -> find(p, ev-> pbar.setValue((int)ev.getNewValue()))).start());

        JPanel controls = new JPanel();
        controls.add(pbar);
        controls.add(button);
        
        frame.add(p);
        frame.add(controls, BorderLayout.SOUTH);
        frame.pack();
        frame.setResizable(false);
        frame.setVisible(true);
    }

    private void find(JComponent c, PropertyChangeListener l) {
        int maxX = img.getWidth() - template.getWidth();
        int maxY = img.getHeight() - template.getHeight();

        int oldProgress = 0;
        for (int i = 0; i < maxY; i++) {
            for (int j = 0; j < maxX; j++) {
                int progress = (i*maxX+j)*100/(maxY*maxX);
                if (oldProgress != progress && progress % 10 == 0) {
                    final int old = oldProgress;
                    SwingUtilities.invokeLater(() -> l.propertyChange(
                            new PropertyChangeEvent(this, "progress", old, progress)));
                }
                oldProgress = progress;

                if (matchesTemplate(j, i)) {
                    Point p = new Point(j, i);
                    SwingUtilities.invokeLater(() -> positions.add(p));
                    j += template.getWidth() - 1;
                }
            }
        }
        final int old = oldProgress;
        SwingUtilities.invokeLater(() -> l.propertyChange(
                new PropertyChangeEvent(this, "progress", old, 100)));
    
        SwingUtilities.invokeLater(() -> c.repaint());
    }

    private boolean matchesTemplate(int x, int y) {
        int maxY = template.getHeight();
        int maxX = template.getWidth();
        int n = maxX * maxY;
        int maxMisses = 8*n / 100;
        int misses = 0;        

        for (int cy = 0; cy < maxY; cy++) {
            for (int cx = 0; cx < maxX; cx++) {
                int templateCol = template.getRGB(cx, cy);
                int imgCol = img.getRGB(x + cx, y + cy);
                if (!similarColor(imgCol, templateCol, 25.0)) {
                    misses++;
                    if (misses > maxMisses) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    private boolean similarColor(int c1, int c2, double maxErr) {
        int redDiff = ((c1 & 0xff0000) >>> 16) - ((c2 & 0xff0000) >>> 16);
        int greenDiff = ((c1 & 0xff00) >>> 8) - ((c2 & 0xff00) >>> 8);
        int blueDiff = (c1 & 0xff) - (c2 & 0xff);

        double err = Math.sqrt(redDiff*redDiff + blueDiff*blueDiff + greenDiff*greenDiff);
        return err <= maxErr;
    }
   
    public static void main(String[] args) throws Exception {
        BufferedImage img = ImageIO.read(Test.class.getResource("mario.png"));
        BufferedImage template = img.getSubimage(378, 27, 80, 69); 
        Test app = new Test(img, template);
        SwingUtilities.invokeLater(() -> app.run());
    }
}
 
Hallo keksdose132.

Habe das Problem zwar nicht richtig verstanden. Aber fuer image classification Machine Learning , also Gesichter in Bildern erkennen etc,
gibt es tolle Algorithmen und Software. Je nachdem, kann dies sehr schnell und genau sein. Man beachtet dann nur ein paar features.
Wenn man nach genug Tests und Anpassungen die Fehlerrate gering genug ist, sollte es auch ausreichen (z.B. in welchem Bereich des Bildes es sich befindet).

Gruß

Axel Pfennig, Duesseldorf
 

Zurück
Oben