让代码更简单

C#图像相似度算法——汉明距离

重要:本文最后更新于2018-11-13 13:52:59,某些文章具有时效性,若有错误或已失效,请在下方留言或联系代码狗

这两天在折腾验证码识别,各种查资料,真心累。

下面是效果:

C#图像相似度算法——汉明距离

C#图像相似度算法——汉明距离

C#图像相似度算法——汉明距离

C#图像相似度算法——汉明距离

C#图像相似度算法——汉明距离

C#图像相似度算法——汉明距离

6和8有点分不清,可能是因为去噪去干扰处理得不够好,不过大部分都能识别出来。注意用到了二值化和图像相似度算法,相似度算法有网友说用灰度直方图就行,我测试过识别成功率太低,汉明距离识别率比较高,目前没有找到更好的办法,分享下汉明距离计算方式。

下面是C#汉明距离计算代码:

复制
/// <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;
 }

感觉很棒!可以赞赏支持我哟~

0 打赏

评论 (0)

登录后评论
QQ咨询 邮件咨询 狗哥推荐