5

Qt 4.5 を使用してグラフィックス アプリケーションを開発しており、画像を QPixmapCache に入れています。これを最適化し、ユーザーが既にキャッシュにある画像を挿入すると、それが使用されるようにしたいと考えました。

現在、各画像には一意の ID があり、ペイント イベントでの最適化に役立ちます。ただし、画像のハッシュを計算できれば、キャッシュを検索して、それが既に存在するかどうかを確認し、それを使用できることに気付きました (もちろん、オブジェクトの重複にはもっと役立ちます)。

私の問題は、その大きな QPixmap のハッシュ計算が遅くなるか、より速い方法があるかということです。

4

4 に答える 4

3

誰かがこの問題に遭遇した場合に備えて (特に画像のようなものをハッシュするのにあまり経験がありません)、QPixmap をハッシュし、後で比較するためにそれらをルックアップ テーブルに入力するために使用した非常に単純なソリューションを次に示します。

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;
}

これはハッシュ関数自体です (衝突を減らしたい場合は、qint64 にハッシュすることができます)。ご覧のとおり、pixmap を QImage に変換し、その次元をたどり、各ピクセルに対して一度に 1 つずつ非常に単純なハッシュを実行し、最終結果を返します。この実装を改善する方法はたくさんありますが (この質問に対する他の回答を参照してください)、これが何をする必要があるかの基本的な要点です。

OPは、このハッシュ関数を使用して、後で画像を比較するためのルックアップテーブルを作成する方法について言及しました. これには、次のような非常に単純なルックアップ初期化関数が必要です。

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...
}

ここでは、クラスで宣言する必要がある imageTable という QMap を使用しています。

QMap<qint32, QString> imageTable;

そして最後に、ルックアップ テーブル内の画像と画像を比較したい場合 (つまり、「私が知っている画像のうち、この特定の画像は何ですか?」)、ハッシュ関数を呼び出すだけです。画像(QPixmapでもあると想定しています)と戻りQString値により、それを理解できます。次のようなものが機能します。

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.
}

それでおしまい。これが誰かの役に立てば幸いです。時間を節約できたはずですが、それを理解する経験ができてうれしかったです。

于 2012-08-22T15:49:00.030 に答える
3

これに関するいくつかのコメント:

  1. ピックスマップのハッシュ/キャッシュ キーを生成する場合は、QPixmapCache をスキップして QCache を直接使用することをお勧めします。これにより、QStrings をキーとして使用するオーバーヘッドがいくらか解消されます (ファイル パスを使用してアイテムを検索する場合を除きます)。

  2. Qt4.4 の時点で、QPixmap には「ハッシュ」値が関連付けられています ( QPixmap::cacheKey()を参照)。ドキュメントには、「異なる QPixmap オブジェクトは、同じコンテンツを参照する場合にのみ、同じキャッシュ キーを持つことができる」と主張されています。ただし、Qt は共有データ コピーを使用するため、これはコピーされたピックスマップにのみ適用され、同じイメージからロードされた 2 つの異なるピックスマップには適用されません。少しテストすると、それが機能するかどうかがわかります。機能する場合は、ハッシュ値を簡単に取得できます。

  3. 重複を削除して、かなり迅速なキャッシュを作成したい場合は、サイズ、色深度、画像の種類などに応じて並べ替える独自のデータ構造を確認することをお勧めします。次に、同じサイズ、ビット深度などの同じタイプの画像を見つけた後、実際の画像データをハッシュするだけで済みます。もちろん、ユーザーが一般的に同じもので多くの画像を開く場合、まったく役に立ちません。

  4. パフォーマンス: Qt が 4.5 で追加したベンチマーク機能を忘れないでください。これにより、さまざまなハッシュのアイデアを比較し、どれが最も速く実行されるかを確認できます。まだチェックしていませんが、かなり綺麗です。

于 2009-03-05T17:33:01.087 に答える