簡體   English   中英

一種便宜/快速的散列位圖的方法?

[英]A cheap/fast way to hash Bitmaps?

我有一個應用程序需要一個圖片庫(全部在Jpeg中),並給出每個可能的對之間的相似度分數。 在每個時間點只能選擇一對,並顯示其相似度分數。

比較兩個圖像的算法具有一定的性能成本,因此比較一對圖像需要花費幾秒鍾。

選擇兩張圖片時:

  1. 如果從未比較過該對,則分數顯示為“尚未評分”。 用戶可以單擊“得分”按鈕,該對將被發送到對要計算分數的隊列進行排隊。 示例: http//db.tt/gb1Yk6yx
  2. 如果該對當前在要計算的隊列中,則分數字段顯示“正在計算...”。 示例: http//db.tt/OvS1qGP3
  3. 如果已比較該對,則會顯示該對的分數。 示例: http//db.tt/m2OQGybW

示例(進行批處理時): http : //db.tt/iD67SdCp

如果從未計算過分數,並且用戶單擊“分數”,則該字段將切換為“計算...”,然后在計算完成時顯示分數。

在顯示分數字段中的任何內容之前,選中兩對后,會將其附加的位圖發送到HashMap,以驗證這兩個位圖是否已具有附加的分數,在這種情況下,它會簡單地將其返回。 如果沒有分數,則將作業發送到隊列中。

要知道分數是否存在於緩存中,我需要找到一種哈希對對的方法,以便可以使用生成的鍵來查找緩存。 那就是我的問題所在。 有意義的是,兩個位圖的散列應該很快。 否則,我只是添加了另一層計算。 但是,到目前為止,我對兩個位圖進行哈希處理的方法是將它們發送到字節數組中並獲取其MD5校驗和。 像這樣:

private Long getHashKey(Bitmap first, Bitmap second){

    // TODO this IS costly, it render useless the cache optimization.
    // also, it doesn't detect that comp(A,B) is the same as comp(B,A).
    // much work to do here.

    if(D) Profiling.start(TAG, "getHashKey");

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    first.compress(Bitmap.CompressFormat.JPEG, 100, stream);

    byte[] firstArray = stream.toByteArray();
    second.compress(Bitmap.CompressFormat.JPEG, 100, stream);

    byte[] secondArray = stream.toByteArray();
    byte[] bitmapBuffer = new byte[firstArray.length + secondArray.length];

    System.arraycopy(firstArray, 0, bitmapBuffer, 0, firstArray.length);

    System.arraycopy(secondArray, 0, bitmapBuffer, 
            firstArray.length, secondArray.length);

    Adler32 md5Hash = new Adler32();
    md5Hash.update(bitmapBuffer);
    long hashKey = md5Hash.getValue();

    if(D) Profiling.stop();

    return hashKey;
}

但是,根據我所做的分析,此方法需要大約53毫秒的運行時間,這會導致UI出現非常不舒服的延遲。 在更詳細的性能分析中,我發現大約95%的計算時間是通過compress方法完成的。 但是,我還沒有找到其他方法來獲取支持位圖的字節。

05-26 17:56:13.220: D/Profiling(9458): Profile for ImageCompareActivity.getHashKey:
05-26 17:56:13.220: D/Profiling(9458): >          Count : 1996 calls
05-26 17:56:13.220: D/Profiling(9458): >  Total runtime : 105765140 us
05-26 17:56:13.220: D/Profiling(9458): >    Avg runtime : 52988 us

我知道我對位圖進行哈希處理的方式非常殘酷。 但是我對散列函數以及我可以用來唯一標識文件的位圖的哪些部分知之甚少。 我不想使用文件名或類似的名稱,因為我想最終將這些位圖發送到數據庫中。

[更新1]我不了解Object.hashCode()。 現在,我修改了這樣的方法:

private Integer getHashKey(Bitmap first, Bitmap second){

    if(D) Profiling.start(TAG, "getHashKey");

    Integer hashKey = new Integer(
            1013 * (first.hashCode()) ^ 1009 * (second.hashCode()) ); 

    if(D) Profiling.stop();

    return hashKey;
}

平均運行時間約為18 us。

是有關散列的最新問題。 Adler可能是JRE中內置的最快的方法。 您是否考慮過預先計算哈希並將其與圖像一起存儲,或者存儲在數據庫中?

如何使用android的sameAs?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM