4

私はSHA-256アルゴリズムを使用して、データベース内の同一の画像を検出しています。さまざまな画像形式を使用しているため、ファイルで直接ハッシュを計算したくありません。代わりに、ピクセルデータを抽出し、その上でハッシュを計算したいと思います。

残念ながら、ランダムな衝突がたくさん発生しています。6000枚の画像から同じピクセル抽出(下記)を使用して同じバイトを持たない68枚の画像は、同じ値にハッシュされます。これは非常に多くの衝突のように感じます。さらに、計算したバイトをピクセルデータからファイルにダンプしてから、次のことを試しました。

echo -n [byteDumpFile] | sha256sum

その結果、ダンプされた画像のハッシュ値が異なり、MessageDigestを使用するときに何か間違ったことをしていると思います。

ピクセルデータを取得する方法は次のとおりです。

    imageBytes = new byte[4 * width * height];
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {

            // grab color information
            int argb = image.getRGB(x, y);

            // a,r,g,b ordered bytes per this pixel. the values are always 0-255 so the byte cast is safe
            int offset = y * width;
            int pushX = x * 4;
            imageBytes[pushX + offset] = (byte) ((argb >> 24) & 0xff);
            imageBytes[pushX + 1 + offset] = (byte) ((argb >> 16) & 0xff);
            imageBytes[pushX + 2 + offset] = (byte) ((argb >> 8) & 0xff);
            imageBytes[pushX + 3 + offset] = (byte) (argb & 0xff);

        }
    }

次に、MessageDigestクラスを使用してハッシュを計算します。

    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.reset();


    for (int i = 0; i < imageBytes.length; i++)
    {
        digest.update(imageBytes[i]);
    }

    String hashString = new String(encodeHex(digest.digest()));

ここで、encodeHexは次のとおりです。

   private static String encodeHex(byte data[])
    {
        StringBuilder hex = new StringBuilder(2 * data.length);
        for (byte b : data)
        {
            hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
        }

    return hex.toString();
}
4

3 に答える 3

2

offset計算が間違っていると思います。そのはず:

int offset = y * width * 4;

を作成するためのより良い方法は;imageBytesかもしれません。インデックスを計算せずに、各バイトを順番ByteBufferに単純化できます。さらに、 MessageDigestputで直接使用できます。

于 2012-06-14T19:50:08.330 に答える
1

試す

digest.update(imageBytes);
于 2012-06-14T19:40:03.897 に答える
0

私はこれを思いついた。上記のコメントに基づく:

private String calculateHash(BufferedImage img) throws NoSuchAlgorithmException {
    final int width = img.getWidth();
    final int height = img.getHeight();
    final ByteBuffer byteBuffer = ByteBuffer.allocate(4 * width * height);
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            // grab color information
            int argb = img.getRGB(x, y);

            // a,r,g,b ordered bytes per this pixel. the values are always 0-255 so the byte cast is safe
            byteBuffer.put((byte) ((argb >> 24) & 0xff));
            byteBuffer.put((byte) ((argb >> 16) & 0xff));
            byteBuffer.put((byte) ((argb >> 8) & 0xff));
            byteBuffer.put((byte) (argb & 0xff));
        }
    }


    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.reset();

    byte[] hashBytes = digest.digest(byteBuffer.array());
    return Base64Utils.encodeToString(hashBytes);
}
于 2015-11-13T21:56:56.627 に答える