Frage

Ich bin eine Grafik-Anwendung Entwicklung mit Qt 4.5 und bin Putting Bilder in der QPixmapCache, wollte ich dies zu optimieren, so dass, wenn ein Benutzer ein Bild einfügt, die bereits im Cache ist es, dass verwenden.

Im Moment jedes Bild hat eine eindeutige ID, die auf Farbe Ereignisse optimiert sich hilft. Mir ist klar, aber dass, wenn ich einen Hash-Wert des Bildes berechnen konnte ich den Cache-Suche konnten, um zu sehen, ob es bereits vorhanden ist und verwenden, die (es wäre mehr für doppelte Objekte natürlich helfen).

Mein Problem ist, dass wenn ihr ein großer QPixmap wird eine Hash-Berechnung der es die Dinge verlangsamen oder gibt es einen schnelleren Weg?

War es hilfreich?

Lösung

Ein paar Kommentare dazu:

  1. Wenn Sie vorhaben, einen Hash / Cache-Schlüssel eines pixmap zu erzeugen, dann sollten Sie die QPixmapCache und überspringen verwenden QCache direkt . Dies würde einige Overhead mit QStrings als Schlüssel beseitigen (es sei denn, Sie auch den Dateipfad verwenden möchten, um die Elemente zu lokalisieren)

  2. Ab Qt4.4, QPixmap hat einen "Hash" -Wert mit ihm verbunden (siehe QPixmap :: CacheKey () ). Die Dokumentation behauptet, „Distinct QPixmap Objekte können nur den gleichen Cache-Schlüssel haben, wenn sie auf die gleichen Inhalte verweisen.“ Da jedoch Qt Shared-Kopieren von Daten verwendet, kann dies nur kopiert pixmaps anwenden und nicht auf zwei verschiedene pixmaps aus dem gleichen Bild geladen. Ein wenig getestet würden Sie sagen, wenn es funktioniert, und wenn ja, wäre es können Sie ganz einfach einen Hash-Wert erhalten.

  3. Wenn Sie wirklich eine gute, ziemlich schnell Cache mit dem Entfernen von Vervielfältigungen tun wollen, Sie können auf eigene Datenstruktur aussehen soll , dass sortiert nach Größen, Farbtiefen, Bildtypen und Dinge wie das. Dann würden Sie müssen nur die tatsächlichen Bilddaten auf Hash, nachdem Sie die gleiche Art von Bild mit den gleichen Abmessungen, Bittiefen finden usw. Natürlich, wenn Ihre Nutzer in der Regel eine Menge Bilder mit diesen Dingen öffnen Sie das gleiche, es wouldn ‚t überhaupt helfen.

  4. Performance: Vergessen Sie nicht über die Benchmarking Sachen Qt in 4.5 hinzugefügt, die Sie vergleichen Ihre verschiedene Hashing-Ideen und sehen lassen würden, die man am schnellsten läuft. Ich habe es noch nicht ausgecheckt, aber es sieht recht ordentlich.

Andere Tipps

Nur für den Fall, dass jemand über dieses Problem kommt (und auch nicht schrecklich mit Hashing Dinge erlebt, vor allem so etwas wie ein Bild), hier ist eine sehr einfache Lösung, die ich für Hashing QPixmaps verwendet und in einer Lookup-Tabelle für einen späteren Vergleich Eingabe :

qint32 HashClass::hashPixmap(QPixmap pix)
{
    QImage image = pix.toImage();
    qint32 hash = 0;

    for(int y = 0; y < image.height(); y++)
    {
        for(int x = 0; x < image.width(); x++)
        {
            QRgb pixel = image.pixel(x,y);

            hash += pixel;
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
    }

    return hash;
}

Hier ist die Hash-Funktion selbst (man kann es in einen qint64 Hash haben, wenn Sie weniger Kollisionen wünschen). Wie Sie sehen können konvertiere ich die Pixmap in eine QImage, und schon allein durch seine Dimensionen gehen und einen sehr einfachen One-at-a-time-Hash auf jedem Pixel und das Rück das Endergebnis führen. Es gibt viele Möglichkeiten, diese Umsetzung (siehe die anderen Antworten auf diese Frage) zu verbessern, aber das ist der grundlegende Kern von dem, was getan werden muss.

Die OP erwähnt, wie er diese Hash-Funktion für den späteren Vergleich Bilder eine Lookup-Tabelle, um dann zu konstruieren verwenden würde. Dies würde eine sehr einfache Lookup-Funktion zur Initialisierung erfordern - so etwas wie folgt aus:

void HashClass::initializeImageLookupTable()
{
    imageTable.insert(hashPixmap(QPixmap(":/Image_Path1.png")), "ImageKey1");
    imageTable.insert(hashPixmap(QPixmap(":/Image_Path2.png")), "ImageKey2");
    imageTable.insert(hashPixmap(QPixmap(":/Image_Path3.png")), "ImageKey2");
// Etc...
}

Ich bin mit einem QMap hier genannt imageTable, die als solche in der Klasse deklariert werden müßten:

QMap<qint32, QString> imageTable;

Dann, endlich, wenn Sie ein Bild zu den Bildern in Ihrer Lookup-Tabelle vergleichen mögen (zB: „Was Bild, aus den Bildern, die ich es wissen kann, ist diese besondere Bild“), rufen Sie einfach die Funktion auf das Bild Hashing (was ich nehme an, dass auch ein QPixmap sein) und die Rückkehr QString Wert ermöglicht es Ihnen, das herauszufinden. So etwas wie dies funktionieren würde:

void HashClass::compareImage(const QPixmap& pixmap)
{
    QString value = imageTable[hashPixmap(pixmap)];
    // Do whatever needs to be done with the QString value and pixmap after this point.
}

Das ist es. Ich hoffe, das hilft jemand - es mir etwas Zeit gerettet hätte, obwohl ich glücklich war die Erfahrung, um es herauszufinden,

.

Hash-Berechnungen sollten ziemlich schnell sein (irgendwo über 100 MB / s, wenn kein Disk-I / O beteiligt ist) je nachdem, welchen Algorithmus Sie verwenden. Vor Hashing, können Sie auch ein paar schnelle Tests machen potenzielle Kandidaten auszusortieren - F. E. Bilder müssen gleiche Breite und Höhe haben, sonst nutzlos es ist ihre Hash-Werte zu vergleichen.

Natürlich sollten Sie auch für eingefügte Bilder der Hash-Werte halten, so dass Sie nur einen Hash für neue Bilder berechnen und wird es nicht berechnen müssen wieder für die im Cache gespeicherten Bilder.

Wenn die Bilder unterschiedlich genug sind, wäre es vielleicht genug sein, um nicht das ganze Bild Hash, sondern ein kleiner Thumbnail oder ein Teil des Bildes (zB erste und letzte 10 Zeilen), dies wird schneller sein, aber zu mehr führen Kollisionen.

Ich gehe davon aus Sie reden tatsächlich einen Hash über die Daten des Bildes Berechnung anstatt die eindeutige ID von QT erzeugt bekommen.
Je nach Ihren Bildern, brauchen Sie wahrscheinlich nicht das ganze Bild gehen über einen Hash zu berechnen. Vielleicht lesen Sie nur die ersten 10 Pixel? erstes Abtastzeile?
Vielleicht eine Pseudo-Zufallsauswahl von Pixeln aus dem gesamten Bild? (Mit einem bekannten Samen, so dass Sie die Sequenz wiederholen konnten) Vergessen Sie nicht die Größe des Bildes auf das Hash als auch hinzuzufügen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top