文章目录
原文地址:
http://www.cnblogs.com/technology/archive/2012/07/12/Perceptual-Hash-Algorithm.html
原文中算法是c++实现。贴一个改了的andoird/bitmap的实现
public class BitmapUtils { private static int sum = 0; public static String getHash(Bitmap bitmap){ Bitmap temp = Bitmap.createScaledBitmap(bitmap, 8, 8, false); int[] grayValues = reduceColor(temp); int average = sum/grayValues.length; String reslut = computeBits(grayValues, average); return reslut; } private static String computeBits(int[] grayValues, int average) { char[] result = new char[grayValues.length]; for (int i = 0; i < grayValues.length; i++) { if (grayValues[i] < average) result[i] = '0'; else result[i] = '1'; } return new String(result); } private static int[] reduceColor(Bitmap bitmap) { sum = 0; int width = bitmap.getWidth(); int height = bitmap.getHeight(); Log.i("th", "scaled bitmap's width*heith:" + width + "*" + height); int[] grayValues = new int[width * height]; int[] pix = new int[width * height]; bitmap.getPixels(pix, 0, width, 0, 0, width, height); for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) { int x = j * width + i; int r = (pix[x] >> 16) & 0xff; int g = (pix[x] >> 8) & 0xff; int b = pix[x] & 0xff; int grayValue = (r * 30 + g * 59 + b * 11) / 100; sum+=grayValue; grayValues[x] = grayValue; } return grayValues; } public static void saveToFile(Bitmap ...bitmaps ){ int i=0; for (Bitmap bitmap : bitmaps) { String path = Environment.getExternalStorageDirectory().getPath(); File file = new File(path+"/"+(i++)+".jpg"); FileOutputStream fos = null; try { fos = new FileOutputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } bitmap.compress(CompressFormat.JPEG, 100, fos ); try { fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
但是在原算法步骤的第二步是:
第二步 转为灰度图片
将缩小后的图片, 转为64级灰度图片.
我看了下c++的那个是实现没有做转64级灰度,只是单纯的转为了灰度图。这个估计对算法的准确度有一定影响。
现在写的andoird实现跟c++的算法一样也没有转,谁无聊了可以补充下。
结合现在做的这个项目,觉得这个算法没什么用。。。。。
有个更好的phash算法,可以去看看号称能接受20%的变形,贴上地址: