我现在继续来研究验证码的识别之类的话题,现在要研究的是针对有倾斜的验证码,比如一张验证码上面有4个字符。每个字符都是有一定角度的偏移(这个偏移是小于90°的),我想知道这个字符是向左偏,还是向右偏,偏移量是多少,不知道各位高手有什么见解?

解决方案 »

  1.   

    先谢谢各位捧场,我在网上看到一些代码如下:
     Bitmap curBitmap = new Bitmap(pictureBox2.Image.Width, pictureBox2.Image.Height);
                Graphics g = Graphics.FromImage(curBitmap);
                Matrix X = new Matrix();
                //  X.Rotate(30);
                X.Shear((float)0.16666666667, 0);   //  2/12
                //X.Shear((float)0, 0);   //  2/12
                g.Transform = X;
                // Draw image
                //Rectangle cloneRect = GetPicValidByValue(128);  //Get Valid Pic Rectangle
                Rectangle cloneRect = new Rectangle(6, 5, 40, 12);
                //Rectangle cloneRect = new Rectangle(0,0, curBitmap.Width, curBitmap.Height);
                Bitmap tmpBmp = ((Bitmap)pictureBox2.Image).Clone(cloneRect, pictureBox2.Image.PixelFormat);
                g.DrawImage(tmpBmp,
                    new Rectangle(6, 5, 40, 12),
                    //cloneRect,
                    0, 0, tmpBmp.Width,
                    tmpBmp.Height,
                     GraphicsUnit.Pixel);            pictureBox3.Image = curBitmap;
    其中  X.Shear((float)0.16666666667, 0);   //  2/12
    这里的偏移量的设置是固定的,也就是要自己不断的一个一个的试。而且也不知道到底是左偏移,还是右偏移。所以就想到要是有能直接的求偏移量的算法就好了,而且能求出是左偏移还是有便宜的。
      另外我想问个问题就是怎么可以在这里插入图片呢?不是插入外部的,是我电脑上的。我想给图片放上来让高手看看,并给小弟一些宝贵的建议!
      

  2.   

    你想的太复杂了,只要能分割开单个字符,再学习一下,基本什么样的验证码都是识别出来。识别部分的代码参加:http://www.cnblogs.com/mobydick/archive/2010/01/20/1652204.html截张图
      

  3.   

    我已经完成这一步骤了。已经将图片  画到32x32的中间了。主要还是对  那4步不是很明白。第2,3,4步返回的double值  是不是要循环32次后相加呢?
      

  4.   

    没明白哈。还请各位指导。
     主调方法:
           /// <summary>
            /// 返回识别结果
             /// </summary>
            /// <param name="maps"></param>
            /// <param name="dgGrayValue"></param>
            /// <returns></returns>
            public string get_checkResult(Bitmap[] maps, int dgGrayValue)
            {
                string result = "";
                for (int i = 0; i < maps.Length; i++)
                {
                    Bitmap bmp = maps[i];
                    result += Similarity_calculation(bmp, dgGrayValue);
                }
                return result;
            }Similarity_calculation 方法:
     /// <summary>
            /// 计算图片的相似度
            /// </summary>
            /// <param name="maps"></param>
            /// <param name="dgGrayValue"></param>
            /// <returns></returns>
            public string Similarity_calculation(Bitmap map, int dgGrayValue)
            {
                string result = "";
                if (map != null)
                {                #region 第一步:1.将每张图片按像素存放到一个长度为32的32位整型数组里面,每个整数存放一行,整数的每位存放一个像素值(0或者1)
                    //将当前的图片转化成 0 1码  
                    int[] charCode = GetTraitCode_array(map, dgGrayValue);//一共是1024位
                    List<Int32[]> recList = new List<Int32[]>();//要是别的图片 长度为32的 32位整型数组
                    int tempIndex = 0;
                    for (int i = 0; i < 32; i++)
                    {
                        Int32[] rec_bmp = new Int32[32];
                        for (int j = 0; j < 32; j++)
                        {                        rec_bmp[j] = charCode[tempIndex];
                            tempIndex++;
                        }
                        recList.Add(rec_bmp);                }
                    #endregion
                    //将要识别的
                    foreach (DictionaryEntry de in TraitCodeHT)//逐条记录对比
                    {
                        double res = 0d;//对比结果
                        string[] valueArray = de.Value.ToString().Split(',');//当前key下面的value集合
                        for (int s = 0; s < valueArray.Length; s++)//循环每个value
                        {
                            List<Int32[]> traitList = new List<Int32[]>();//将要作为参照对比的    长度为32的 32位整型数组
                            tempIndex = 0;
                            for (int i = 0; i < 32; i++)
                            {
                                Int32[] trait_bmp = new Int32[32];
                                for (int j = 0; j < 32; j++)
                                {
                                    trait_bmp[j] = valueArray[s].ToString()[tempIndex];
                                }
                                traitList.Add(trait_bmp);
                            }
                            //在此刻已经得到  两个 List<Int32[]> 了
                            //循环求余弦对比
                           
                            for (int i = 0; i < 32; i++)
                            {                           
                                res += GetCosine((int[])traitList[i],(int[])recList[i]);
                            }
                            if (res > 0.7)
                            {
                                break;
                            }                                           }                    if (res > 0.7)
                        {
                            result = de.Key.ToString();
                            break;
                        }
                    }            }            return result;
            }GetTraitCode_array  方法:
     /// <summary>
            /// 返回灰度图片的0或1特征码,1表示灰点,0表示背景       32×32
            /// </summary>
            /// <param name="singlepic">灰度图</param>
            /// <param name="dgGrayValue">背前景灰色界限</param>
            /// <returns>特征码</returns>
            public int[] GetTraitCode_array(Bitmap bmp, int dgGrayValue)
            {
                Color piexl;
                int[] code = new int[bmp.Width * bmp.Height];
                int temp = 0;
                if (bmp != null && bmp.Width != 0 && bmp.Height != 0)
                {
                    for (int posy = 0; posy < bmp.Height; posy++)
                    {
                        for (int posx = 0; posx < bmp.Width; posx++)
                        {
                           
                                piexl = bmp.GetPixel(posx, posy);
                                if (piexl.R < dgGrayValue)    // Color.Black )
                                {                                code[temp] = 1;
                                }
                                else
                                {                                code[temp] = 0;
                                }
                           
                            temp++;
                        }
                    }
                }
                return code;
            }GetCosine  方法:
     /// <summary>
            /// 计算相似度(相似度越高,图片相同的概率越大)
            /// 2.计算分子时,将两个这样的数组中的整数按照对应的索引分别按位与,然后将计算结果按位相加;
            /// 3.计算分母时,将每个数组中的所有整数按位相加,然后开根号,最后相乘;
            /// 4.分子除以分母,得出余弦值。
            /// </summary>
            /// <param name="e1"></param>
            /// <param name="e2"></param>
            /// <returns></returns>
            public double GetCosine(int[] e1, int[] e2)
            {
                int a = 0;//分母1
                int b = 0;//分母2
                int c = 0;//分子
                for (int y = 0; y < 32; ++y)
                {
                    //两个数组中的整数按位与
                    int i = e2[y] & e1[y];
                    //按位加
                    for (int x = 1; x < 33; ++x)
                    {
                        c += (i >> x) & 1;
                        a += (e2[y] >> x) & 1;
                        b += (e1[y] >> x) & 1;
                    }
                }            //计算分母
                int d = a * b;
                return d == 0 ? 0 : c / Math.Sqrt(d);
            }
      

  5.   

    for (int i = 0; i < 32; i++) 
    {                          
        res += GetCosine((int[])traitList[i],(int[])recList[i]); 

    你没理解博客里面写的内容,仔细再看看。
      

  6.   

    楼上的楼上的朋友,呵呵,我终于弄出来了。真是太感谢你了。同时也要感谢所有的朋友参与。还要感谢http://googlechinablog.com/2006/07/12.html这篇文章。要不是好好看了这篇文章,我想我也不会理解。
    要接分的朋友们赶快来哦。明天上午我就结贴。呵呵。