• 图片相似性 d-hash算法 C#实践


    参考:

    https://github.com/maccman/dhash

    http://blog.iconfinder.com/detecting-duplicate-images-using-python/ 讲的很详细

    http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html 各种图片相似性算法比较

    namespace PictureSimilarity
    {
        public class ImageDHash
        {
            /// <summary>
            /// 获取图片的D-hash值
            /// </summary>
            /// <param name="image"></param>
            /// <returns></returns>
            public static ulong GetHash(Image image)
            {
                int hashSize = 8;
                //图片缩小到9*8的尺寸
                var thumbImage = Resize(image, hashSize + 1, hashSize);
                //获取灰度图片,灰度图片即把rgb转换成0~255的值
                var grayImage = GetGrayScaleVersion(thumbImage);
    
                ulong hash = 0;
    
                //遍历9*8像素点,记录相邻像素之间的对边关系,产生8*8=64个对比关系,对应ulong的64位
                for (int x = 0; x < hashSize; x++)
                {
                    for (int y = 0; y < hashSize; y++)
                    {
                        //比较当前像素点与下一个像素点的对比关系,如果当前像素点值较大则为1,否则为0
                        var largerThanNext = Math.Abs(grayImage.GetPixel(y, x).R) > Math.Abs(grayImage.GetPixel(y + 1, x).R);
                        if (largerThanNext)
                        {
                            var currentIndex = x * hashSize + y;
                            hash |= (1UL << currentIndex);
                        }
                        
                    }
                }
    
                return hash;
            }
    
            /// <summary>
            /// 计算两个hash值之间的汉明距离
            /// </summary>
            /// <param name="hash1"></param>
            /// <param name="hash2"></param>
            /// <returns></returns>
            public static double GetSimilarity(ulong hash1, ulong hash2)
            {
                return (64 - BitCount(hash1 ^ hash2)) / 64.0;
            }
    
            /// <summary>
            /// Bitcounts array used for BitCount method (used in Similarity comparisons).
            /// Don't try to read this or understand it, I certainly don't. Credit goes to
            /// David Oftedal of the University of Oslo, Norway for this. 
            /// http://folk.uio.no/davidjo/computing.php
            /// </summary>
            private static byte[] bitCounts = {
                0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,
                2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,
                4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,
                3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
            };
            /// <summary>
            /// 计算ulong中位值为1的个数
            /// </summary>
            /// <param name="num"></param>
            /// <returns></returns>
            private static uint BitCount(ulong num)
            {
                uint count = 0;
                for (; num > 0; num >>= 8)
                    count += bitCounts[(num & 0xff)];
                return count;
            }
    
            /// <summary>
            /// 修改图片尺寸
            /// </summary>
            /// <param name="originalImage"></param>
            /// <param name="newWidth"></param>
            /// <param name="newHeight"></param>
            /// <returns></returns>
            public static Image Resize(Image originalImage, int newWidth, int newHeight)
            {
                Image smallVersion = new Bitmap(newWidth, newHeight);
                using (Graphics g = Graphics.FromImage(smallVersion))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    g.DrawImage(originalImage, 0, 0, newWidth, newHeight);
                }
    
                return smallVersion;
            }
    
            private static ColorMatrix ColorMatrix = new ColorMatrix(
              new float[][]
              {
                 new float[] {.3f, .3f, .3f, 0, 0},
                 new float[] {.59f, .59f, .59f, 0, 0},
                 new float[] {.11f, .11f, .11f, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {0, 0, 0, 0, 1}
              });
    
            /// <summary>
            /// 获取灰度图片
            /// </summary>
            /// <param name="original"></param>
            /// <returns></returns>
            public static Bitmap GetGrayScaleVersion(Image original)
            {
                //http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale
                //create a blank bitmap the same size as original
                Bitmap newBitmap = new Bitmap(original.Width, original.Height);
    
                //get a graphics object from the new image
                using (Graphics g = Graphics.FromImage(newBitmap))
                {
                    //create some image attributes
                    ImageAttributes attributes = new ImageAttributes();
    
                    //set the color matrix attribute
                    attributes.SetColorMatrix(ColorMatrix);
    
                    //draw the original image on the new image
                    //using the grayscale color matrix
                    g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                       0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
                }
                return newBitmap;
            }
        }
    }
  • 相关阅读:
    2017年度最具商业价值人工智能公司TOP50 榜单发布
    滑动swipe的妙用
    UE3优化
    UE4 框架
    制作HUD
    Component概念
    手游记事
    C++与UnrealScript脚本交互
    unreal Script(US)一些注意事项
    UDK游戏打包详解
  • 原文地址:https://www.cnblogs.com/xiao123/p/7162225.html
Copyright © 2020-2023  润新知