Extractor.csusing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing ;
using System.Drawing.Imaging;namespace CaptchaExtractor
{
    /// <summary>
    /// 解析器
    /// </summary>
    public static class Extractor
    {
        public static String Run(Bitmap value)
        {
            String Res = "";
            Bitmap Resultbit = null;
            Bitmap Resultbit1 = null;
            Bitmap Resultbit2 = null;
            Bitmap Resultbit3 = null;
            Bitmap Resultbit4 = null;
            List<Bitmap> Resultbit5 = null;
            Bitmap Resultbit6 = null;
            int ColorOffset = 5;
            int SplitColorNum = 150;
            Run(value, ColorOffset, SplitColorNum, out Res,
                out Resultbit, out Resultbit1, out Resultbit2, out Resultbit3, out Resultbit4, out Resultbit5, out Resultbit6, "");
            return Res;
        }
        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="value">图片内容</param>
        /// <param name="colorOffset">颜色偏移量</param>
        /// <param name="ResultText">返回文本内容</param>
        /// <param name="ResultImage">返回最终图片</param>
        /// <param name="LearnText">学习模式下图片内容的实际的值,非学习模式下为空</param>
        public static String Run(Bitmap value,int colorOffset,int SplitColorNum,out String ResultText,out Bitmap ResultImage,
            out Bitmap Image1,out Bitmap Image2,out Bitmap Image3,out Bitmap Image4,out List<Bitmap> Image5,out Bitmap Image6,
            String LearnText)
        {
            /*方法
             * 1、灰度
             * 2、降色
             * 3、计算
             * 3、滤色
             * 5、匹配
            */
            #region 第一步,灰度
            Bitmap GrayscaleBit = new Bitmap(value.Width, value.Height);
            GrayscaleBit.SetResolution(value.HorizontalResolution, value.VerticalResolution);            Graphics GrayG = Graphics.FromImage(GrayscaleBit);
            Point sp1 = new Point (0,0);
            Point sp2 = new Point (value.Width ,0);
            Point sp3 = new Point (0,value.Height );            ImageAttributes newia = new ImageAttributes();
            ColorMatrix colorMatrix = new System.Drawing.Imaging.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}
              });
            newia.SetColorMatrix(colorMatrix);
            GrayG.DrawImage(value, new Rectangle(0, 0, value.Width, value.Height), 0, 0, value.Width, value.Height, GraphicsUnit.Pixel, newia);            #endregion
            //第三步的计算的颜色统计
            //Dictionary<int, int> ColorCollection = new Dictionary<int, int>();
            List<int> ColorList = new List<int> ();
            #region 第二步,降色,并丢色
            Bitmap LessColorbit = new Bitmap(GrayscaleBit);
            int ColorNum = 50;
            for (int i = 0; i < LessColorbit.Width; i++)
            {
                for (int j = 0; j < LessColorbit.Height; j++)
                {
                    //降色了
                    Color CurrColor = LessColorbit.GetPixel(i, j);
                    int ColorR = 0;
                    //直接丢色
                    #region 丢色
                    if (CurrColor.R > SplitColorNum)
                    {
                        //全白
                        ColorR = 255;
                    }
                    else
                    {
                        //全黑
                        ColorR = 0;
                    }
                    CurrColor = Color.FromArgb(255, ColorR, ColorR, ColorR);
                    LessColorbit.SetPixel(i, j, CurrColor);
                    #endregion
                    #region 降色
                    //if (CurrColor.R % ColorNum  != 0)
                    //{
                    //    //不是5的余数时
                    //    ColorR = CurrColor.R / ColorNum  * ColorNum ;
                    //    CurrColor = Color.FromArgb(255, ColorR, ColorR, ColorR);
                    //    LessColorbit.SetPixel(i, j, CurrColor );
                    //}
                    #endregion                    if (CurrColor .R != 255&& !ColorList.Exists(c => c == CurrColor.R))
                    {
                        ColorList.Add(CurrColor.R);
                    }
                    //if (ColorCollection.ContainsKey(CurrColor.R))
                    //{
                    //    ColorCollection[CurrColor.R] += 1;
                    //}
                    //else
                    //{
                    //    ColorCollection.Add(CurrColor.R, 1);
                    //}
                }
            }
            #endregion            #region 第三步,计算
            //主要是为了计算深色           
            
            #endregion
            #region 滤色
            //颜色从深到浅,从左到右,逐步匹配
            //List<int> ColorList = from ss in ColorCollection 
            //                      select ss.Key 
            ColorList.Sort();
            //存储被匹配掉之后的图片
            Bitmap Matchbit = new Bitmap(LessColorbit);
            //存储被匹配出来的图片
            Bitmap Filterbit = new Bitmap(LessColorbit);
            Graphics MatchG = Graphics.FromImage(Matchbit);            Graphics FilterG = Graphics.FromImage(Filterbit);
            FilterG.Clear(Color.FromArgb(255, 255, 255, 255));
           // Bitmap FindImage = new Bitmap (5,5);
           // FindImage.SetResolution (72,72);
           // Graphics FindG = Graphics.FromImage (FindImage );
           // FindG.Clear (Color.FromArgb (255,188,167,20));
            //MatchG.Clear(Color.FromArgb(0, 0, 0, 0));

解决方案 »

  1.   


                //颜色偏移量
                int OffsetValue = colorOffset ;            //现在只有两个颜色了,不需要用Dic来进行存储了
                //Dictionary<Point, List<Point>> FilterPointCollection = new Dictionary<Point, List<Point>>();
                List<List<Point>> OriginalPoint = new List<List<Point>>();
                List<List<Point>> DynamicPoint = new List<List<Point>>();
                for (int i = 0; i < ColorList.Count;i++ )
                {
                    int MatchColor = ColorList[i];
                    Boolean IsError = false;
                    int LostNum = -999;
                    //遍历颜色,从深往浅
                    Point TopLeftP = new Point(LessColorbit.Width, LessColorbit.Height);
                    Point BottomRightP = new Point(0, 0);                List<Point> findPoint = new List<Point>();
                    //从左往右寻找 
                    for (int x = 0; x < LessColorbit.Width; x++)
                    {
                        Boolean IsFind = false;
                        for (int y = 0; y < LessColorbit.Height; y++)
                        {
                            if ((x == 37 || x == 36)&&
                                (y==9||y==8))
                            {                        }
                            //好了
                            if (ContrastColor(LessColorbit.GetPixel(x, y).R, MatchColor, OffsetValue))
                            {
                                if (x < TopLeftP.X)
                                    TopLeftP.X = x;
                                if (y < TopLeftP.Y)
                                    TopLeftP.Y = y;
                                if (x > BottomRightP.X)
                                    BottomRightP.X = x;
                                if (y > BottomRightP.Y)
                                    BottomRightP.Y = y;
                                findPoint .Add (new Point (x,y));
                                IsFind = true;
                            }
                        }
                        if (IsFind)
                        {
                            if (LostNum == -999)
                                LostNum = 0;
                            //如果太宽,则错了
                            if (((BottomRightP.X - TopLeftP.X) > LessColorbit.Width / 4) ||
                                ((BottomRightP.Y - TopLeftP.Y) > LessColorbit.Height * 0.8))
                            {
                                IsError = true;
                                break;
                            }
                        }
                        else
                        {
                            LostNum = 1;
                        }
                        if (LostNum == 1)
                        {
                            //如果太窄,则错了 
                            if (BottomRightP.X - TopLeftP.X >= 6)
                            {                            //这里说明,矩阵存在,并且当前已经到了边界
                                //好吧,去处理下 
                                //MatchG.DrawImage(FindImage, new Rectangle(TopLeftP.X + 1, TopLeftP.Y + 1, BottomRightP.X - TopLeftP.X, BottomRightP.Y - TopLeftP.Y), new Rectangle(0, 0, FindImage.Width, FindImage.Height), GraphicsUnit.Pixel);
                                //goto ffff;
                                //fillPointColor(Matchbit,Filterbit , findPoint);
                                //if (FilterPointCollection.ContainsKey(TopLeftP))
                                //{
                                    //foreach (Point FP in findPoint)
                                    //{
                                    //    if (!FilterPointCollection[TopLeftP].Exists(c => c.Equals(FP)))
                                    //    {
                                    //        FilterPointCollection[TopLeftP].Add(FP);
                                    //    }
                                    //}
                                //}
                                //else
                                //{
                                //    FilterPointCollection.Add(TopLeftP, findPoint);
                                //}
                                //保存在图片中的原像素点,以及相对相素点
                                OriginalPoint.Add(findPoint);
                                DynamicPoint.Add(GetDynamicPoint (findPoint ));
                            }
                            findPoint = new List<Point>();
                            LostNum = -999;
                            TopLeftP = new Point(Matchbit.Width, Matchbit.Height);
                            BottomRightP = new Point(0, 0);
                        }
                        if (IsError)
                            break;
                    }
                }
            ffff:
                #endregion            Bitmap Findbit = new Bitmap(LessColorbit,new Size (800,60) );
          
            //Findbit.SetResolution(72, 72);
            Graphics FindG = Graphics.FromImage(Findbit);
            FindG.Clear(Color.FromArgb(255, 255, 255, 255));        int DrawIndex = 0;
            int CurrHei = 0;
            int CurrWid = 0;
            List<Bitmap> ResolveImages = new List<Bitmap>();
            Boolean IsLearn = !String.IsNullOrEmpty (LearnText );
            List<CaptchaValue> TextMatch = CaptchTextManager.GetAll();
            String Text = "";
            //foreach (KeyValuePair<Point, List<Point>> tmpValue in FilterPointCollection)
            foreach (List<Point> tmpValue in DynamicPoint )
            {
                if (IsLearn)
                {
                    if (String.IsNullOrEmpty(LearnText))
                        break;
                    String CurrText = LearnText[0].ToString();
                    if (CurrText != " ")
                    {
                        CaptchTextManager.Learn(tmpValue, CurrText );
                    }
                    if (LearnText.Length == 1)
                    {
                        LearnText = "";
                    }
                    else
                    {
                        LearnText = LearnText.Substring(1, LearnText.Length - 1);
                    }
                }
                else
                {
                    //遍历结果
                    Bitmap tmpbit = new Bitmap(LessColorbit);
                    Graphics tmpg = Graphics.FromImage(tmpbit);
                    tmpg.Clear(Color.FromArgb(255, 255, 255, 255));
                    Point TopLeft = new Point(tmpbit.Width, tmpbit.Height);
                    Point BottomRight = new Point(0, 0);
                    foreach (Point tmpP in tmpValue)
                    {
                        tmpbit.SetPixel(tmpP.X, tmpP.Y, Color.FromArgb(255, 0, 0, 0));
                        if (tmpP.X < TopLeft.X)
                            TopLeft.X = tmpP.X;
                        if (tmpP.Y < TopLeft.Y)
                            TopLeft.Y = tmpP.Y;
                        if (tmpP.X > BottomRight.X)
                            BottomRight.X = tmpP.X;
                        if (tmpP.Y > BottomRight.Y)
                            BottomRight.Y = tmpP.Y;
                    }
                    //好了,结束
                    int wid = BottomRight.X - TopLeft.X + 1;
                    int hei = BottomRight.Y - TopLeft.Y + 1;
                    if (CurrWid + wid > 800)
                    {
                        CurrWid = 0;
                        CurrHei += 20;
                    }
                    FindG.DrawImage(tmpbit, new Rectangle(CurrWid, CurrHei, wid, hei), new Rectangle(TopLeft.X, TopLeft.Y, wid, hei), GraphicsUnit.Pixel);
                    CurrWid += wid + 5;
                }            //好了,解码
                Text += ResloveCodebyDic(TextMatch, tmpValue, 3);            //ResolveImages.Add(ResolveCode(tmpValue.Value));
            }
                ResultText = Text ;
                ResultImage = LessColorbit ;
                Image1 = GrayscaleBit;
                Image2 = LessColorbit;
                Image3 = Matchbit;
                Image4 = Filterbit;
                Image5 = ResolveImages;
                Image6 = Findbit;
                return Text;
            }        private static  void fillPointColor(Bitmap b,Bitmap f, List<Point> value)
            {
                //Graphics ddd = Graphics.FromImage(b);
                foreach (Point pp in value)
                {
                    b.SetPixel(pp.X, pp.Y , Color.FromArgb(255, 255, 255, 255));
                    f.SetPixel(pp.X, pp.Y, Color.FromArgb(255, 0, 0, 0));
                }
            }
            /// <summary>
            /// 匹配颜色
            /// </summary>
            /// <param name="CurrCol">当前的颜色</param>
            /// <param name="MatchCol">参照颜色</param>
            /// <param name="OffsetValue">偏移量</param>
            /// <returns></returns>
            private static Boolean ContrastColor(int CurrCol, int MatchCol, int OffsetValue)
            {
                if (( CurrCol == MatchCol )||
                    (CurrCol < MatchCol &&CurrCol + OffsetValue >=MatchCol )||
                    (CurrCol > MatchCol && CurrCol - OffsetValue <= MatchCol ))
                {
                    return true;
                }
                return false;
            }
      

  2.   

            /// <summary>
            /// 把取得的像素点,重置到左上角
            /// </summary>
            /// <param name="value"></param>
            /// <returns></returns>
            private static List<Point> GetDynamicPoint(List<Point> value)
            {
                Point TopLeft = new Point(1000, 1000);
                //Point BottomRight = new Point(0, 0);
                //第一步,找出顶点
                foreach (Point tmpv in value)
                {
                    if (tmpv.X < TopLeft.X)
                        TopLeft.X = tmpv.X;
                    if (tmpv.Y < TopLeft.Y)
                        TopLeft.Y = tmpv.Y;
                }
                List<Point> res = new List<Point>();
                for (int i = 0; i < value.Count;i++ )
                {
                    Point tmpv = value[i];
                    res.Add (new Point(tmpv.X - TopLeft.X, tmpv.Y - TopLeft.Y));
                }
                return res;
            }        /// <summary>
            /// 智能解码,不用了
            /// </summary>
            /// <param name="value"></param>
            /// <returns></returns>
            private static Bitmap ResolveCode(List<Point> value)
            {
                Font newf = new Font("宋体",18);
                //第一步,计算长宽
                Bitmap Drawbit = new Bitmap(1500, 30);
                Drawbit.SetResolution(72, 72);
                Graphics DrawG = Graphics.FromImage(Drawbit);
                DrawG.Clear(Color.FromArgb(255, 255, 255, 255));            int DrawWidth = 0;            Point TopLeft = new Point(200,200);
                Point BottomRight = new Point(0, 0);
                foreach (Point tmpP in value )
                {
                    Drawbit.SetPixel(tmpP.X, tmpP.Y, Color.FromArgb(255, 0, 0, 0));
                    if (tmpP.X < TopLeft.X)
                        TopLeft.X = tmpP.X;
                    if (tmpP.Y < TopLeft.Y)
                        TopLeft.Y = tmpP.Y;
                    if (tmpP.X > BottomRight.X)
                        BottomRight.X = tmpP.X;
                    if (tmpP.Y > BottomRight.Y)
                        BottomRight.Y = tmpP.Y;
                }
                //好了,结束
                int wid = BottomRight.X - TopLeft.X + 1;
                int hei = BottomRight.Y - TopLeft.Y + 1;            DrawWidth = TopLeft .X + wid + 1;
                String Dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                for (int i = 0; i < Dic.Length;i++ )
                {
                    char tmpC = Dic[i];
                    Bitmap newB = new Bitmap(200, 200);
                    newB.SetResolution(72, 72);
                    Graphics newG = Graphics.FromImage(newB);
                    newG.Clear(Color.FromArgb(255, 255, 255, 255));
                    newG.DrawString(tmpC.ToString (), newf, new SolidBrush(Color.FromArgb(255, 0, 0, 0)), new RectangleF(TopLeft, new SizeF(wid, hei)));
                    //好了,来比比
                    //取百分比吧
                    int DonePointNum = 0;
                    foreach (Point tmpP in value)
                    {
                        if (newB.GetPixel(tmpP.X, tmpP.Y).R != 255)
                        {
                            //成了
                            newB.SetPixel(tmpP.X, tmpP.Y, Color.FromArgb(255, 128, 128, 128));
                            DonePointNum++;
                        }
                    }
                    DrawG.DrawImage(newB, new Rectangle(DrawWidth, TopLeft.Y, wid, hei), new Rectangle(TopLeft.X, TopLeft.Y, wid, hei), GraphicsUnit.Pixel);
                    DrawWidth += wid + 1;
                }            return Drawbit;
            }        /// <summary>
            /// 字典解码
            /// </summary>
            /// <param name="dic"></param>
            /// <param name="value"></param>
            /// <param name="Offset"></param>
            /// <returns></returns>
            private static String ResloveCodebyDic(List<CaptchaValue> dic, List<Point> value,int Offset)
            {
                String Text = "¤";
                if (dic != null && dic.Count > 0 && value != null && value.Count > 0)
                {
                    //Dictionary<String, int> Result = new Dictionary<string, int>();                
                    int allMaxNum = 0;
                    foreach (CaptchaValue tmpV in dic)
                    {
                        //Result.Add(tmpV.Text, 0);
                        int MaxNum = 0;
                        //值有效,可以继续 
                        for (int i = -1*Offset ; i <= Offset; i++)
                        {
                            for (int j = -1*Offset ; j <= Offset; j++)
                            {
                                int MatchNum = MatchPoint(tmpV.Value, value, i, j);
                                if (MatchNum > MaxNum)
                                    MaxNum = MatchNum;
                            }
                        }
                        if (MaxNum > allMaxNum )
                        {
                            allMaxNum = MaxNum ;
                            if (MaxNum * 2 >= tmpV.Value.Count )
                            {
                                Text = tmpV.Text;
                            }
                        }
                        //Result[tmpV.Text] = MaxNum;
                    }
                    //好了,执行完了                       
                }
                return Text;
            }
            private static int MatchPoint(List<Point> p1, List<Point> p2, int xOffset, int yOffset)
            {
                int MatchNum = 0;
                if (p1 != null && p1.Count > 0 &&
                    p2 != null && p2.Count > 0)
                {
                    foreach (Point tmpP in p1)
                    {
                        if (p2.Exists(c => c.X == tmpP.X + xOffset && c.Y == tmpP.Y + yOffset))
                        {
                            //能找到,说明成功了
                            MatchNum++;
                        }
                    }
                }
                return MatchNum;
            }
        }
    }
      

  3.   

    这个好东西,不过楼主能不能上传个网盘,或者csdn资源什么的,这么发太散了。
      

  4.   

    楼主把项目上传到CSDN的下载频道,然后在分享一下下载链接。
      

  5.   

    只能识别普通的验证码我这有一份java版的,思路都一样。
    http://www.zuidaima.com/share/1631472847784960.htm