一种便宜/快速的方式来散列位图?

我有一个应用程序,需要一个图片库(所有在JPEG中),并给每个可能的对之间的相似性得分。 在每个时间点,只能select一对,并显示其相似性分数。

比较两个图像的algorithm具有一定的性能成本,因此比较一对需要花费几秒钟的时间。

当select两张照片时:

  1. 如果从未比较过,则得分显示“尚未计分”。 用户可以点击“分数”button,这个配对将被发送到排队计分的线程。 例如: http : //db.tt/gb1Yk6yx
  2. 如果该对目前在队列中计算,则分数字段显示“计算…”。 例如: http : //db.tt/OvS1qGP3
  3. 如果对比较了,则会显示附在该对中的分数。 例如: http : //db.tt/m2OQGybW

示例(进行批处理时): http : //db.tt/iD67SdCp

如果一个分数从未被计算出来,并且用户点击“分数”,该字段将切换到“计算…”,然后在计算完成时显示分数。

在分数字段中显示任何内容之前,当select两个对时,它们附加的位图将被发送到一个HashMap,以validation这两个Bitmaps是否已经有附加分数,在这种情况下,它只是返回它。 如果没有得分,那么这个工作将被排队。

要知道分数是否存在于caching中,我需要find一种散列方式,以便我可以使用所得到的密钥来查找caching。 那是我的问题所在。 有意义的是,两个Bitmap的哈希应该是快的。 否则,我只是添加另一层计算。 但是,到目前为止,散列两个Bitmap的方式是将它们发送到一个字节数组中,并获取它们的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; } 

但是,根据我所做的分析,这种方法的运行花费了大约53ms,这导致UI的滞后,这是相当不愉快的。 在更详细的分析中,我发现大约95%的计算时间是在compress方法中完成的。 但是,我还没有find另一种方法来获取支持Bitmap的字节。

 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 

我知道我的方式散列位图是相当粗暴的。 但是我不太了解哈希函数,以及Bitmap的哪些部分可以用来唯一标识这些文件。 我不想使用文件名或类似的东西,因为我最终将这些位图发送到数据库中。

[Update 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我们。

Solutions Collecting From Web of "一种便宜/快速的方式来散列位图?"