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