public HexcellsSolver(HexPatternParameter pparam) { _patternParameter = pparam; Dictionary <string, Bitmap> refdic = new Dictionary <string, Bitmap>(); refdic.Add("-", Properties.Resources.pattern_dash); refdic.Add("{", Properties.Resources.pattern_Open); refdic.Add("}", Properties.Resources.pattern_Close); refdic.Add("?", Properties.Resources.pattern_QMark); refdic.Add("0", Properties.Resources.pattern_0); refdic.Add("1", Properties.Resources.pattern_1); refdic.Add("2", Properties.Resources.pattern_2); refdic.Add("3", Properties.Resources.pattern_3); refdic.Add("4", Properties.Resources.pattern_4); refdic.Add("5", Properties.Resources.pattern_5); refdic.Add("6", Properties.Resources.pattern_6); refdic.Add("7", Properties.Resources.pattern_7); refdic.Add("8", Properties.Resources.pattern_8); refdic.Add("9", Properties.Resources.pattern_9); refdic.Add("10", Properties.Resources.pattern_10); refdic.Add("12", Properties.Resources.pattern_12); refdic.Add("13", Properties.Resources.pattern_13); refdic.Add("14", Properties.Resources.pattern_14); refdic.Add("15", Properties.Resources.pattern_15); refdic.Add("16", Properties.Resources.pattern_16); refdic.Add("17", Properties.Resources.pattern_17); refdic.Add("18", Properties.Resources.pattern_18); refdic.Add("19", Properties.Resources.pattern_19); POCR = new PatternOCR(refdic, OCRCoupling.NORMAL_COUPLED_SEGMENTS); Cam = new HexCam(); OCR = new HexOCR(POCR); }
public bool[,] GetPattern(Bitmap shot, HexPatternParameter pparams, int ignore_x, int ignore_y) { BitmapData srcData = shot.LockBits(new Rectangle(0, 0, shot.Width, shot.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); IntPtr Scan0 = srcData.Scan0; int stride = srcData.Stride; int width = shot.Width; int height = shot.Height; bool[,] result = new bool[width, height]; ColorExt.Cache(HexagonCellImage.REAL_COLOR_CELL_ACTIVE); ColorExt.Cache(HexagonCellImage.REAL_COLOR_CELL_HIDDEN); ColorExt.Cache(HexagonCellImage.REAL_COLOR_CELL_INACTIVE); unsafe { byte *p = (byte *)(void *)Scan0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (x > ignore_x && y < ignore_y) { continue; } int idx = (y * stride) + x * 4; result[x, y] = false; if (pparams.UseActiveCellsInBinaryGridRecognition) { var ok = ((pparams.ActiveCellHueThreshold >= 255) || ColorExt.GetHueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_ACTIVE) < pparams.ActiveCellHueThreshold) && ((pparams.ActiveCellSatThreshold >= 255) || ColorExt.GetSaturationDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_ACTIVE) < pparams.ActiveCellSatThreshold) && ((pparams.ActiveCellValThreshold >= 255) || ColorExt.GetValueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_ACTIVE) < pparams.ActiveCellValThreshold); if (ok) { result[x, y] = true; continue; } } if (pparams.UseHiddenCellsInBinaryGridRecognition) { var ok = ((pparams.HiddenCellHueThreshold >= 255) || ColorExt.GetHueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_HIDDEN) < pparams.HiddenCellHueThreshold) && ((pparams.HiddenCellSatThreshold >= 255) || ColorExt.GetSaturationDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_HIDDEN) < pparams.HiddenCellSatThreshold) && ((pparams.HiddenCellValThreshold >= 255) || ColorExt.GetValueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_HIDDEN) < pparams.HiddenCellValThreshold); if (ok) { result[x, y] = true; continue; } } if (pparams.UseInactiveCellsInBinaryGridRecognition) { var ok = ((pparams.InactiveCellHueThreshold >= 255) || ColorExt.GetHueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_INACTIVE) < pparams.InactiveCellHueThreshold) && ((pparams.InactiveCellSatThreshold >= 255) || ColorExt.GetSaturationDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_INACTIVE) < pparams.InactiveCellSatThreshold) && ((pparams.InactiveCellValThreshold >= 255) || ColorExt.GetValueDistance(p[idx + 2], p[idx + 1], p[idx + 0], HexagonCellImage.REAL_COLOR_CELL_INACTIVE) < pparams.InactiveCellValThreshold); if (ok) { result[x, y] = true; continue; } } } } } shot.UnlockBits(srcData); return(result); }
public HexGridProperties FindHexPattern(Bitmap shot, HexPatternParameter pparams) { double CellRadius; double CellGap; double CorrectionHorizontal; double CorrectionVertical; double PaddingX; double PaddingY; double NoCellBar_TR_X; double NoCellBar_TR_Y; bool InitialSwap; Rect2i CounterArea; Rect2i CounterAreaInner; //################################## var counter = GetCounterArea(shot); bool[,] pattern = GetPattern(shot, pparams, counter.Item4, counter.Item5); var centers = GetHexPatternCenters(pattern, shot.Width, shot.Height, out _); var grid = GetHexPatternGrid(centers); double hexHeight = GetHexPatternHeight(pattern, shot.Height, centers) - 2; var distance = GetHexPatternDistance(grid); CellRadius = hexHeight * (Math.Sin(MathExt.ToRadians(90)) / Math.Sin(MathExt.ToRadians(60))); CellGap = distance.Item2 * 2 - hexHeight * 2; CorrectionVertical = 0; CorrectionHorizontal = distance.Item1 - (2 * hexHeight + CellGap) * Math.Cos(MathExt.ToRadians(30)); var anchor = centers.OrderBy(p => p.X).ThenBy(p => p.Y).First(); PaddingX = anchor.X; PaddingY = anchor.Y; InitialSwap = false; int offsetX = 0; while (PaddingX - (hexHeight * 2 + CellGap + CorrectionVertical) > CellRadius + CellGap) { PaddingX -= hexHeight * 2 + CellGap + CorrectionVertical; offsetX++; InitialSwap = !InitialSwap; } double calculatedPosX = PaddingX + ((hexHeight + CellGap + hexHeight) * (Math.Cos(MathExt.ToRadians(30))) + CorrectionHorizontal) * offsetX; PaddingX += anchor.X - calculatedPosX; int offsetY = 0; while (PaddingY - ((2 * hexHeight + CellGap) * Math.Cos(MathExt.ToRadians(30)) + CorrectionHorizontal) > CellRadius + CellGap) { PaddingY -= (2 * hexHeight + CellGap) * Math.Cos(MathExt.ToRadians(30)) + CorrectionHorizontal; offsetY++; } double calculatedPosY = PaddingY + (hexHeight + CellGap + hexHeight + CorrectionVertical) * offsetY; PaddingY += anchor.Y - calculatedPosY; NoCellBar_TR_X = 175; NoCellBar_TR_Y = 165; CounterArea = counter.Item2; CounterAreaInner = counter.Item3; //################################## return(new HexGridPropertiesBuilder() .SetCellRadius(CellRadius) .SetCellGap(CellGap) .SetCorrectionHorizontal(CorrectionHorizontal) .SetCorrectionVertical(CorrectionVertical) .SetPaddingX(PaddingX) .SetPaddingY(PaddingY) .SetNoCellBar_TR_X(NoCellBar_TR_X) .SetNoCellBar_TR_Y(NoCellBar_TR_Y) .SetInitialSwap(InitialSwap) .SetCounter_X(CounterArea.bl.X) .SetCounter_Y(CounterArea.bl.Y) .SetCounter_Width(CounterArea.Width) .SetCounter_Height(CounterArea.Height) .SetCounterInner_X(CounterAreaInner.bl.X) .SetCounterInner_Y(CounterAreaInner.bl.Y) .SetCounterInner_Width(CounterAreaInner.Width) .SetCounterInner_Height(CounterAreaInner.Height) .build()); }
public Bitmap DisplayBinPattern(Bitmap shot, HexOCR ocr, HexPatternParameter pparams) { shot = new Bitmap(shot); var counter = ocr.GetCounterArea(shot); bool[,] pattern = ocr.GetPattern(shot, pparams, counter.Item4, counter.Item5); var centers = ocr.GetHexPatternCenters(pattern, shot.Width, shot.Height, out var errs); var grid = ocr.GetHexPatternGrid(centers); BitmapData srcData = shot.LockBits(new Rectangle(0, 0, shot.Width, shot.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); IntPtr Scan0 = srcData.Scan0; int stride = srcData.Stride; int width = shot.Width; int height = shot.Height; unsafe { byte *p = (byte *)(void *)Scan0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int idx = (y * stride) + x * 4; bool on = pattern[x, y] || counter.Item1.Includes(x, y); if (errs[x, y]) { p[idx + 0] = 0; p[idx + 1] = 0; p[idx + 2] = 128; p[idx + 3] = 255; } else if (pattern[x, y]) { p[idx + 0] = 0; p[idx + 1] = 0; p[idx + 2] = 0; p[idx + 3] = 255; } else if (counter.Item1.Includes(x, y)) { p[idx + 0] = 128; p[idx + 1] = 0; p[idx + 2] = 0; p[idx + 3] = 255; } else { p[idx + 0] = 255; p[idx + 1] = 255; p[idx + 2] = 255; p[idx + 3] = 255; } } } } shot.UnlockBits(srcData); using (Graphics g = Graphics.FromImage(shot)) { Pen pen = new Pen(Color.Magenta); foreach (var center in centers) { g.DrawLine(pen, (int)(center.X - 5), (int)(center.Y - 5), (int)(center.X + 5), (int)(center.Y + 5)); g.DrawLine(pen, (int)(center.X + 5), (int)(center.Y - 5), (int)(center.X - 5), (int)(center.Y + 5)); } foreach (var row in grid.Item1) { g.DrawLine(pen, row, 0, row, shot.Height); } foreach (var col in grid.Item2) { g.DrawLine(pen, 0, col, shot.Width, col); } g.DrawRectangle(pen, counter.Item2.bl.X, counter.Item2.bl.Y, counter.Item2.Width, counter.Item2.Height); g.DrawRectangle(pen, counter.Item3.bl.X, counter.Item3.bl.Y, counter.Item3.Width, counter.Item3.Height); } return(shot); }