zoukankan      html  css  js  c++  java
  • (转)感知哈希算法

    /// <summary>
    /// 感知哈希算法
    /// </summary>
    public class ImageComparer
    {
    /// <summary>
    /// 获取图片的Hashcode
    /// </summary>
    /// <param name="imageName"></param>
    /// <returns></returns>
    public static string GetImageHashCode(string imageName)
    {
    int width = 8;
    int height = 8;

    // 第一步
    // 将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,
    // 只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
    Bitmap bmp = new Bitmap(Thumb(imageName));
    int[] pixels = new int[width * height];

    // 第二步
    // 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
    for (int i = 0; i < width; i++)
    {
    for (int j = 0; j < height; j++)
    {
    Color color = bmp.GetPixel(i, j);
    pixels[i * height + j] = RGBToGray(color.ToArgb());
    }
    }

    // 第三步
    // 计算所有64个像素的灰度平均值。
    int avgPixel = Average(pixels);

    // 第四步
    // 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
    int[] comps = new int[width * height];
    for (int i = 0; i < comps.Length; i++)
    {
    if (pixels[i] >= avgPixel)
    {
    comps[i] = 1;
    }
    else
    {
    comps[i] = 0;
    }
    }

    // 第五步
    // 将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。
    StringBuilder hashCode = new StringBuilder();
    for (int i = 0; i < comps.Length; i += 4)
    {
    int result = comps[i] * (int)Math.Pow(2, 3) + comps[i + 1] * (int)Math.Pow(2, 2) + comps[i + 2] * (int)Math.Pow(2, 1) + comps[i + 2];
    hashCode.Append(BinaryToHex(result));
    }
    bmp.Dispose();
    return hashCode.ToString();
    }

    /// <summary>
    /// 计算"汉明距离"(Hamming distance)。
    /// 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
    /// </summary>
    /// <param name="sourceHashCode"></param>
    /// <param name="hashCode"></param>
    /// <returns></returns>
    public static int HammingDistance(String sourceHashCode, String hashCode)
    {
    int difference = 0;
    int len = sourceHashCode.Length;

    for (int i = 0; i < len; i++)
    {
    if (sourceHashCode[i] != hashCode[i])
    {
    difference++;
    }
    }
    return difference;
    }

    /// <summary>
    /// 缩放图片 www.2cto.com
    /// </summary>
    /// <param name="imageName"></param>
    /// <returns></returns>
    private static Image Thumb(string imageName)
    {
    return Image.FromFile(imageName).GetThumbnailImage(8, 8, () => { return false; }, IntPtr.Zero);
    }

    /// <summary>
    /// 转为64级灰度
    /// </summary>
    /// <param name="pixels"></param>
    /// <returns></returns>
    private static int RGBToGray(int pixels)
    {
    int _red = (pixels >> 16) & 0xFF;
    int _green = (pixels >> 8) & 0xFF;
    int _blue = (pixels) & 0xFF;
    return (int)(0.3 * _red + 0.59 * _green + 0.11 * _blue);
    }

    /// <summary>
    /// 计算平均值
    /// </summary>
    /// <param name="pixels"></param>
    /// <returns></returns>
    private static int Average(int[] pixels)
    {
    float m = 0;
    for (int i = 0; i < pixels.Length; ++i)
    {
    m += pixels[i];
    }
    m = m / pixels.Length;
    return (int)m;
    }

    private static char BinaryToHex(int binary)
    {
    char ch = ' ';
    switch (binary)
    {
    case 0:
    ch = '0';
    break;
    case 1:
    ch = '1';
    break;
    case 2:
    ch = '2';
    break;
    case 3:
    ch = '3';
    break;
    case 4:
    ch = '4';
    break;
    case 5:
    ch = '5';
    break;
    case 6:
    ch = '6';
    break;
    case 7:
    ch = '7';
    break;
    case 8:
    ch = '8';
    break;
    case 9:
    ch = '9';
    break;
    case 10:
    ch = 'a';
    break;
    case 11:
    ch = 'b';
    break;
    case 12:
    ch = 'c';
    break;
    case 13:
    ch = 'd';
    break;
    case 14:
    ch = 'e';
    break;
    case 15:
    ch = 'f';
    break;
    default:
    ch = ' ';
    break;
    }
    return ch;
    }
    }

  • 相关阅读:
    MyBatis操作数据库(基本增删改查)
    CSS和jQuery分别实现图片无缝滚动效果
    jQuery学习
    ORACLE PL、SQL编程
    JavaScript_DOM详解
    JavaScript_DOM(文件对象模型)
    JavaScript 基础
    用javascript编写猜拳游戏(函数)
    用javascript编写简单银行取钱存钱流程(函数)
    用Java编写银行存钱取钱
  • 原文地址:https://www.cnblogs.com/xiaoni/p/3083295.html
Copyright © 2011-2022 走看看