这两天在折腾验证码识别,各种查资料,真心累。
下面是效果:
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)