Anzeige

 BufferedImage -> create hash


Freak2k

Erfahrenes Mitglied
#1
Hey,

ich suche eine schnelle Moeglichkeit zwei bilder zu vergleichen.
Der Vergleich soll als ergebnis nur zurueckgeben, ob die bilder gleich oder nicht gleich sind.
Habe den Ansatz gefunden, ein Hash des Images zu erzeugen und diese zu vergleichen.
Ein Pixelvergleich ist uninteressant, da mehrere bilder pro sekunde vergleichen werden sollen.

Meine Frage: wie kann ich einen hash wert eines BufferedImages erstellen?

danke
 
#2
Hallo!

Also hiermit:
Java:
/**
 * 
 */
package de.tutorials;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;

import javax.imageio.ImageIO;

/**
 * @author tom
 * 
 */
public class ImageHashExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        BufferedImage imageA = ImageIO.read(new File("c:/screenCapture.jpg"));
        BufferedImage imageB = ImageIO.read(new File("c:/screenCapture.jpg"));

        long time = -System.currentTimeMillis();

        int[] pixelOfA = new int[imageA.getWidth() * imageA.getHeight()];
        imageA.getData().getPixel(0, 0, pixelOfA);

        int[] pixelOfB = new int[imageB.getWidth() * imageB.getHeight()];
        imageB.getData().getPixel(0, 0, pixelOfB);

        System.out.println(Arrays.equals(pixelOfA, pixelOfB));

        System.out.println(time + System.currentTimeMillis() + " ms");

    }
}
Brauche ich fuer den Vergleich von 2 gleichen JPEG Bildern mit der Aufloesung 1280*1024 96 DPI Horizontal, 96 DPI Vertikal und 24bit Farbtiefe 200ms. (hierbei wurden ALLE Pixel verglichen). Je frueher bei den beiden int[] unterschiede auftreten desto frueher kann die Vergleichslogik terminieren.

Ein hashcode Vergleich saehe dann so aus:
Java:
System.out.println(Arrays.hashCode(pixelOfA) == Arrays.hashCode(pixelOfB));
Wenn die Bilder alle die selbe Groesse haben, kann man die int[] vorher entsprechend initialisieren.
Bei 1000 Durchlaeufen brauche ich da im Schnitt nur 144ms pro Vergleich und dass mit zwei komplett uebereinstimmenden Bildern der oben genannten Groesse -> Worst case.

Gruss Tom
 
#3
Hallo Thomas!
Mache ich was falsch? Dein Beispiel vergleicht jeweils nur die ersten Pixel der Beiden Bilder!? Oder ist es nur ein Ansatz... den man um eine Schleife erweitern muss um das ganze Array zu vergleichen?
 
#4
Hallo!

huch... da hab ich mich wohl vertippt... sollte wohl getPixels heißen anstatt getPixel.. ;-)

Besser gings aber eh so:
Java:
   BufferedImage srcImage = ImageIO.read(new File("c:/winter.jpg"));
    //DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
    byte[] data = ((DataBufferByte) srcImage.getData().getDataBuffer()).getData();
    System.out.println(Arrays.hashCode(data));
Gruß Tom
 
#5
zum Tom´s Beispiel :)
Java:
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.util.Arrays;
import javax.imageio.ImageIO;

public class ZweiBilderVergleichen {
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {

        //   middleA.gif === middleB.gif !== middleC.gif
        BufferedImage imageA = ImageIO.read(new File("middleA.gif"));
        BufferedImage imageB = ImageIO.read(new File("middleB.gif"));
        BufferedImage imageC = ImageIO.read(new File("middleC.gif"));
       
        long time = -System.currentTimeMillis();

        int[] pixelOfA = new int[imageA.getWidth() * imageA.getHeight()];
        imageA.getData().getPixels(0, 0, 0, 0, pixelOfA);
     
        int[] pixelOfB = new int[imageB.getWidth() * imageB.getHeight()];
        imageB.getData().getPixels(0, 0, 0, 0, pixelOfB);
     
        int[] pixelOfC = new int[imageC.getWidth() * imageC.getHeight()];
        imageC.getData().getPixels(0, 0, 0, 0, pixelOfC);

        System.out.println("Sind A und B gleich? Antwort: " + Arrays.equals(pixelOfA, pixelOfB));
        System.out.println("Sind A und C gleich? Antwort: " + Arrays.equals(pixelOfA, pixelOfC));
        System.out.println("Sind B und C gleich? Antwort: " + Arrays.equals(pixelOfB, pixelOfC));

        //    DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataA = ((DataBufferByte) imageA.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataA));
         
        //   DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataB = ((DataBufferByte) imageB.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataB));
         
        //   DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataC = ((DataBufferByte) imageC.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataC));
       
        System.out.println(time + System.currentTimeMillis() + " ms");
    }
}
 
Zuletzt bearbeitet:
#7
zum Tom´s Beispiel :)
Verbesserung der 18. Zeile;)

@vfl_freak klape zu ! :D

Java:
package de.tutorials.bilder
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.util.Arrays;
import javax.imageio.ImageIO;
public class ZweiBilderVergleichen {
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
       
        //   middleA.gif === middleB.gif !== middleC.gif
        BufferedImage imageA = ImageIO.read(new File("middleA.gif"));
        BufferedImage imageB = ImageIO.read(new File("middleB.gif"));
        BufferedImage imageC = ImageIO.read(new File("middleC.gif"));
   
        long time = System.currentTimeMillis();

        int[] pixelOfA = new int[imageA.getWidth() * imageA.getHeight()];
        imageA.getData().getPixels(0, 0, 0, 0, pixelOfA);
 
        int[] pixelOfB = new int[imageB.getWidth() * imageB.getHeight()];
        imageB.getData().getPixels(0, 0, 0, 0, pixelOfB);
 
        int[] pixelOfC = new int[imageC.getWidth() * imageC.getHeight()];
        imageC.getData().getPixels(0, 0, 0, 0, pixelOfC);

        System.out.println("Sind A und B gleich? Antwort: " + Arrays.equals(pixelOfA, pixelOfB));
        System.out.println("Sind A und C gleich? Antwort: " + Arrays.equals(pixelOfA, pixelOfC));
        System.out.println("Sind B und C gleich? Antwort: " + Arrays.equals(pixelOfB, pixelOfC));

        //    DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataA = ((DataBufferByte) imageA.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataA));
     
        //   DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataB = ((DataBufferByte) imageB.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataB));
     
        //   DataBufferInt -> bei BufferedImage.TYPE_INT_RGB -> getData() -> int[]
        byte[] dataC = ((DataBufferByte) imageC.getData().getDataBuffer()).getData();
        System.out.println(Arrays.hashCode(dataC));
   
        System.out.println(time + System.currentTimeMillis() + " ms");
    }
}
 
Anzeige
Anzeige