3 Stimmen

Schnellste Methode zur Berechnung der Differenz zwischen zwei ARGB-Ints in Java?

Gegeben ein int aus einem DataBuffer, der ARGB-Daten mit den Masken gepackt hat

A = 0xFF000000 R = 0xFF0000 G = 0xFF00 B = 0xFF

Ich mache Folgendes, frage mich aber, ob es in Java nicht eine schnellere Methode gibt?

        DataBuffer db1 = img1.getData().getDataBuffer();
        DataBuffer db2 = img2.getData().getDataBuffer();

        int x, y;
        int totalDiff = 0;
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                       + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                       + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ));
        }

3voto

Arne Deutsch Punkte 14327

Wenn Sie die höhere Geschwindigkeit wirklich brauchen, sollten Sie den Typ der DataBuffer und stellen Sie optimierten Code für den konkreten Typ bereit, so dass Sie sich die Aufrufe an getElem(i) . Dadurch wird Ihr Code ein wenig schneller.

Etwa so:

    DataBuffer db1 = img1.getData().getDataBuffer();
    DataBuffer db2 = img2.getData().getDataBuffer();

    int totalDiff = 0;
    int x, y;
    if (db1 instanceof DataBufferInt && db2 instanceof DataBufferInt) {
        int[] data1 = ((DataBufferInt) db1).getData();
        int[] data2 = ((DataBufferInt) db2).getData();
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = data1[i];
            y = data2[i];

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    } else {
        for (int i = 0; i < WIDTH * HEIGHT; ++i) {
            x = db1.getElem(i);
            y = db2.getElem(i);

            totalDiff += Math.abs((x & 0xFF) - (y & 0xFF))
                    + Math.abs(((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8))
                    + Math.abs(((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16));
        }
    }

Editer : Eine weitere Idee, die Ihnen eine viel höhere Geschwindigkeit bringen würde. Wenn dies nur eine Heuristik ist, könnte es ausreichen, den Unterschied einer etwas "heruntergerechneten" Version Ihrer Bilder zu berechnen. Ersetzen Sie ++i über i+=10 und erhalten eine um den Faktor 10 höhere Geschwindigkeit. Ob dies sinnvoll ist, hängt natürlich von der Art Ihrer Bilder ab.

Editer : In einem Kommentar erwähnten Sie, dass es sich um eine Fitnessfunktion für ein GA handelt ... in diesem Fall könnte es ausreichen, 100 (oder nur 10?) zufällige Positionen aus Ihren Bildern zu nehmen und die Pixel an diesen Positionen zu vergleichen. Der Geschwindigkeitsgewinn wird höchstwahrscheinlich den Genauigkeitsverlust aufwiegen.

1voto

Adrian Regan Punkte 2240

Stimme mit @Arne überein.

Sie können auch die Umschaltrechte entfernen

(x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 ). 

Sie wissen, dass abs(XX0000 - YY0000) wird nur im Bereich von 0-255 liegen.

Es wäre hilfreich, wenn Sie sagen könnten, was Sie herauszufinden versuchen?

Das heißt, können die Pixelinformationen in einer Weise gespeichert werden, die dem entspricht, was Sie erreichen wollen, zum Beispiel als Chrominanz (YUV, YCrCb)?

0voto

Maurice Perry Punkte 32127

Wenn die Berechnung der Summe der Quadrate für Sie akzeptabel ist, ist sie schneller:

    for (int i = 0; i < WIDTH * HEIGHT; ++i) {
        x = db1.getElem(i);
        y = db2.getElem(i);
        int dr = ((x & 0xFF0000) >> 16) - ((y & 0xFF0000) >> 16 );
        int dg = ((x & 0xFF00) >> 8) - ((y & 0xFF00) >> 8);
        int db = (x & 0xFF) - (y & 0xFF);
        totalDiff += dr*dr + dg*dg + db*db;
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X