Пример #1
0
        /// <summary>
        ///获取指定区域下黑色像素的竖直投影
        /// </summary>
        /// <param name="leftdown">待处理区域的左下角坐标</param>
        /// <param name="rightUp">待处理区域的右上角坐标</param>
        /// <param name="flg">参考线,1:baseline为参考线,2:meanline为参考线,0:无参考线</param>
        /// <param name="srcArray">待处理的二值化数组</param>
        /// <returns>返回指定区域投影信息</returns>
        public static VerPro VerticalProjection(Point leftdown, Point rightUp, byte flg, Byte[,] srcArray)
        {
            int tmpNum = CaptchaSegment.CaptchaSegment.ImageWidth;

            Int32[] vProjection = new Int32[tmpNum];

            Array.Clear(vProjection, 0, tmpNum);

            Point guideP = CaptchaSegment.CaptchaSegment.GuidePoint;

            //记录当前投影区域的区块数目,相关信息在区块中以Point的形式存在,Point.x为区块数目,Point.y为该区块的起始位置
            ArrayList vpArea = new ArrayList();

            VerPro infoPro = new VerPro();

            Point vPoint     = new Point();
            Point interPoint = new Point();

            int x = 0;
            int y = 0;

            //获取指定区域的竖直投影
            for (y = leftdown.Y; y < rightUp.Y; y++)
            {
                if (2 == flg)
                {
                    x = leftdown.X;
                }
                else
                {
                    x = leftdown.X + 1;
                }
                for (x = leftdown.X; x < rightUp.X; x++)
                {
                    if (0 == srcArray[x, y])
                    {
                        vProjection[y]++;
                    }
                }
            }

            //获取竖直投影的区块
            int k = leftdown.Y;

            while (k < rightUp.Y)
            {
                int tmpMax = 0;

                if (vProjection[k] != 0)
                {
                    vPoint.X = k - 1;

                    while ((vProjection[k] != 0) && (k < rightUp.Y))
                    {
                        k++;
                    }

                    vPoint.Y = k;

                    if (2 == flg)
                    {
                        tmpMax = rightUp.X;
                        //若meanline为基准线,则找到当前区域字符像素X值最小的点
                        for (y = vPoint.X; y < vPoint.Y; y++)
                        {
                            for (x = leftdown.X; x < rightUp.X; x++)
                            {
                                if ((0 == srcArray[x, y]) && (tmpMax > x))
                                {
                                    tmpMax = x;
                                    break;
                                }
                            }
                        }
                    }
                    else if (1 == flg)
                    {
                        tmpMax = leftdown.X;
                        //若baseline为基准线,则找到当前区域字符像素X值最大的点
                        for (y = vPoint.X; y < vPoint.Y; y++)
                        {
                            for (x = rightUp.X; x > leftdown.X; x--)
                            {
                                if ((0 == srcArray[x, y]) && (tmpMax < x))
                                {
                                    tmpMax = x;
                                    break;
                                }
                            }
                        }
                    }

                    //在meanline或baseline之外2个像素的区域被记录,否则被认定为无效区域
                    if ((((tmpMax - guideP.X) > 1) && (1 == flg)) || (((guideP.Y - tmpMax) > 2)) && (2 == flg) || (0 == flg))
                    {
                        vpArea.Add(vPoint);
                    }
                }
                k++;
            }

            if ((flg != 0) && (vpArea.Count > 0))
            {
                if (2 == flg)
                {
                    tmpNum = guideP.Y;
                }
                else
                {
                    tmpNum = guideP.X;
                }

                //从第一个有效投影区域开始从左至右找字符与参考线的左侧交点
                vPoint = (Point)vpArea[0];
                y      = vPoint.X;
                while (y < vPoint.Y)
                {
                    if (0 == srcArray[tmpNum, y])
                    {
                        interPoint.X = y;
                        break;
                    }
                    y++;
                }


                //从最后一个有效投影区域开始从右至左找字符与参考线的右侧交点
                vPoint = (Point)vpArea[vpArea.Count - 1];
                y      = vPoint.Y;
                while (y > vPoint.X)
                {
                    if (0 == srcArray[tmpNum, y])
                    {
                        interPoint.Y = y;
                        break;
                    }
                    y--;
                }
            }

            infoPro.vRange = vpArea;
            infoPro.vInter = interPoint;
            return(infoPro);
        }
        /// <summary>
        ///获取指定区域下黑色像素的竖直投影
        /// </summary>
        /// <param name="leftdown">待处理区域的左下角坐标</param>
        /// <param name="rightUp">待处理区域的右上角坐标</param>
        /// <param name="flg">参考线,1:baseline为参考线,2:meanline为参考线,0:无参考线</param>
        /// <param name="srcArray">待处理的二值化数组</param>
        /// <returns>返回指定区域投影信息</returns>
        public static VerPro VerticalProjection(Point leftdown, Point rightUp, byte flg, Byte[,] srcArray)
        {
            int tmpNum = CAPTCHA.Program.Width;

            Int32[] vProjection = new Int32[tmpNum];

            Array.Clear(vProjection, 0, tmpNum);

            Point guideP = CaptchaSegment.CaptchaSegment.GuidePoint;

            //记录当前投影区域的区块数目,相关信息在区块中以Point的形式存在,Point.x为区块数目,Point.y为该区块的起始位置
            ArrayList vpArea = new ArrayList();

            VerPro infoPro = new VerPro();

            Point vPoint = new Point();
            Point interPoint = new Point();

            int x = 0;
            int y = 0;

            //获取指定区域的竖直投影
            for (y = leftdown.Y; y < rightUp.Y; y++)
            {
                if(2 == flg)
                {
                    x = leftdown.X;
                }
                else
                {
                    x = leftdown.X + 1;
                }
                for (x = leftdown.X; x < rightUp.X; x++)
                {
                    if (0 == srcArray[x, y])
                    {
                        vProjection[y]++;
                    }
                }
            }

            //获取竖直投影的区块
            int k = leftdown.Y;

            while (k < rightUp.Y)
            {
                int tmpMax = 0;

                if (vProjection[k] != 0)
                {
                    vPoint.X = k - 1;

                    while ((vProjection[k] != 0) && (k < rightUp.Y))
                    {
                        k ++;
                    }

                    vPoint.Y = k;

                    if(2 == flg)
                    {
                        tmpMax = rightUp.X;
                        //若meanline为基准线,则找到当前区域字符像素X值最小的点
                        for (y = vPoint.X; y < vPoint.Y; y++)                
                        {
                            for (x = leftdown.X; x < rightUp.X; x++)
                            {
                                if ((0 == srcArray[x, y]) && (tmpMax > x))
                                {
                                    tmpMax = x;
                                    break;
                                }
                            }
                        }
                    }
                    else if(1 == flg)
                    {
                        tmpMax = leftdown.X;
                        //若baseline为基准线,则找到当前区域字符像素X值最大的点
                        for (y = vPoint.X; y < vPoint.Y; y++)
                        {
                            for (x = rightUp.X; x > leftdown.X; x--)
                            {
                                if ((0 == srcArray[x, y]) && (tmpMax < x))
                                {
                                    tmpMax = x;
                                    break;
                                }
                            }
                        }
                    }

                    //在meanline或baseline之外2个像素的区域被记录,否则被认定为无效区域
                    if ((((tmpMax - guideP.X) > 1) && (1 == flg)) || (((guideP.Y - tmpMax) > 2)) && (2 == flg) || (0 == flg))
                    {
                        vpArea.Add(vPoint);
                    }
                }
                k ++;
            }

            if ((flg != 0) && (vpArea.Count > 0))
            {
                if (2 == flg)
                {
                    tmpNum = guideP.Y;
                }
                else
                {
                    tmpNum = guideP.X;
                }

                //从第一个有效投影区域开始从左至右找字符与参考线的左侧交点
                vPoint = (Point)vpArea[0];
                y = vPoint.X;
                while (y < vPoint.Y)
                {
                    if (0 == srcArray[tmpNum,y])
                    {
                        interPoint.X = y;
                        break;
                    }
                    y++;
                }


                //从最后一个有效投影区域开始从右至左找字符与参考线的右侧交点
                vPoint = (Point)vpArea[vpArea.Count - 1];
                y = vPoint.Y;
                while (y > vPoint.X)
                {
                    if (0 == srcArray[tmpNum, y])
                    {
                        interPoint.Y = y;
                        break;
                    }
                    y--;
                }
            }

            infoPro.vRange = vpArea;
            infoPro.vInter = interPoint;
            return infoPro;
        }
        public static bool SegByMeanRight(Point segP, VerPro meanArr, Boundary mBoundary, int bThVal, int newPos)
        {
            bool bValid = false;

            ArrayList pathListA = dropFallUp(segP);

            ArrayList pathListB = dropFallDown(segP);

            int k = 0;

            for (k = 0; k < pathListA.Count; k++)
            {
                pathListB.Add(pathListA[k]);
            }

            pathListA.Clear();

            for (k = mBoundary.leftDownPoint.X; k < mBoundary.rightUpPoint.X; k++)
            {
                Point tmpP = new Point();

                tmpP.X = k;
                tmpP.Y = mBoundary.rightUpPoint.Y;

                pathListA.Add(tmpP);
            }

            SegAreaInfo tmpInfo = GetSegInfo(pathListB, pathListA);

            if (tmpInfo.blackPixCount > bThVal)//当前分割路径为有效路径
            {
                //SegAreaList.Add(tmpInfo);
                SegPathList.Insert(newPos, pathListB);

                bValid = true;
            }

            return bValid;
        }
        public static bool SegByBaseLine(Point segP, VerPro baseArr, Boundary mBoundary, int bThVal, int newPos, bool bLeft)
        {
            bool bValid = false;

            //以交点为起点分别执行向上滴落和向下滴落
            ArrayList pathListA = dropFallUp(segP);

            ArrayList pathListB = dropFallDown(segP);

            SegAreaInfo tmpInfo = new SegAreaInfo();

            int k = 0;

            for (k = 0; k < pathListA.Count; k++)
            {
                pathListB.Add(pathListA[k]);
            }

            //按字符的规则而言,符合该条件的可能是字符y,j,那么分割完成后,左侧区域有一定几率没有有效字符
            //确认按照该规则分割出的左侧区域是否包含有效字符像素
            pathListA.Clear();

            //当前粘连区域左侧竖线作为判断基准
            if (bLeft)
            {
                for (k = mBoundary.leftDownPoint.X; k < mBoundary.rightUpPoint.X; k++)
                {
                    Point tmpP = new Point();

                    tmpP.X = k;
                    tmpP.Y = mBoundary.leftDownPoint.Y;

                    pathListA.Add(tmpP);
                }

                tmpInfo = GetSegInfo(pathListA, pathListB);
            }
            else
            {
                for (k = mBoundary.leftDownPoint.X; k < mBoundary.rightUpPoint.X; k++)
                {
                    Point tmpP = new Point();

                    tmpP.X = k;
                    tmpP.Y = mBoundary.rightUpPoint.Y;

                    pathListA.Add(tmpP);
                }

                tmpInfo = GetSegInfo(pathListB, pathListA);
            }

            if (tmpInfo.blackPixCount > bThVal)//当前分割路径为有效路径
            {
                //SegAreaList.Add(tmpInfo);
                SegPathList.Insert(newPos, pathListB);

                bValid = true;
            }

            return bValid;
        }
        public static bool SegByMeanLeft(Point segP, VerPro meanArr, Boundary mBoundary, int bThVal, int newPos)
        {
            bool bValid = false;

            //此类交点仅执行从上向下滴落,取meanline以上区域均归为左侧区域
            ArrayList pathListA = dropFallUp(segP);

            ArrayList pathListB = new ArrayList();

            Point point1 = (Point)meanArr.vRange[0];

            int k = 0;

            //从meanline以上区域第一个区块的左下角至与meanline交点在竖直方向以竖直线分割
            for (k = mBoundary.leftDownPoint.X; k < GuidePoint.Y; k++)
            {
                Point tmpP = new Point();

                tmpP.X = k;
                tmpP.Y = point1.X;

                pathListB.Add(tmpP);
            }

            //从从meanline以上区域第一个区块的左下角至meanline交点处在水平方向以横线分割
            for (k = point1.X; k < meanArr.vInter.X; k++)
            {
                Point tmpP = new Point();

                tmpP.X = GuidePoint.Y;
                tmpP.Y = k;

                pathListB.Add(tmpP);
            }

            for (k = 0; k < pathListA.Count; k++)
            {
                pathListB.Add(pathListA[k]);
            }

            //按字符的规则而言,符合该条件的可能是字符A,Z,7,若为字符Z/7,那么分割完成后,左侧区域有一定几率没有有效字符
            //确认按照该规则分割出的左侧区域是否包含有效字符像素
            pathListA.Clear();

            //当前粘连区域左侧竖线作为判断基准
            for (k = mBoundary.leftDownPoint.X; k < mBoundary.rightUpPoint.X; k++)
            {
                Point tmpP = new Point();

                tmpP.X = k;
                tmpP.Y = mBoundary.leftDownPoint.Y;

                pathListA.Add(tmpP);
            }

            SegAreaInfo tmpInfo = GetSegInfo(pathListA, pathListB);

            if (tmpInfo.blackPixCount > bThVal)//当前分割路径为有效路径
            {
                //SegAreaList.Add(tmpInfo);
                SegPathList.Insert(newPos, pathListB);

                bValid = true;
            }

            return bValid;
        }