static bool[,] Binarize(double[,] input, double[,] baseline, bool[,] mask, BlockMap blocks) { var size = Point.SizeOf(input); var binarized = size.Allocate <bool>(); for (int blockY = 0; blockY < blocks.AllBlocks.Height; ++blockY) { for (int blockX = 0; blockX < blocks.AllBlocks.Width; ++blockX) { if (mask[blockY, blockX]) { Rectangle rect = blocks.BlockAreas[blockY, blockX]; for (int y = rect.Bottom; y < rect.Top; ++y) { for (int x = rect.Left; x < rect.Right; ++x) { if (input[y, x] - baseline[y, x] > 0) { binarized[y, x] = true; } } } } } } return(binarized); }
static double[,] SmoothByOrientation(double[,] input, byte[,] orientation, bool[,] mask, BlockMap blocks, byte angle, Point[][] lines) { double[,] output = new double[input.GetLength(0), input.GetLength(1)]; foreach (var block in blocks.AllBlocks) { if (block.Get(mask)) { Point[] line = lines[Angle.Quantize(Angle.Add(orientation[block.Y, block.X], angle), lines.Length)]; foreach (Point linePoint in line) { Rectangle target = blocks.BlockAreas[block]; Rectangle source = target.GetShifted(linePoint); source.Clip(new Rectangle(blocks.PixelCount)); target = source.GetShifted(-linePoint); for (int y = target.Bottom; y < target.Top; ++y) { for (int x = target.Left; x < target.Right; ++x) { output[y, x] += input[y + linePoint.Y, x + linePoint.X]; } } } Rectangle blockArea = blocks.BlockAreas[block]; for (int y = blockArea.Bottom; y < blockArea.Top; ++y) { for (int x = blockArea.Left; x < blockArea.Right; ++x) { output[y, x] *= 1.0 / line.Length; } } } } return(output); }
static PointF[,] SmoothOutOrientationMap(PointF[,] orientation, bool[,] mask) { const int radius = 1; var size = Point.SizeOf(mask); PointF[,] smoothed = size.Allocate <PointF>(); for (int y = 0; y < size.Y; ++y) { for (int x = 0; x < size.X; ++x) { if (mask[y, x]) { Rectangle neighbors = Rectangle.Between( new Point(Math.Max(0, x - radius), Math.Max(0, y - radius)), new Point(Math.Min(size.X, x + radius + 1), Math.Min(size.Y, y + radius + 1))); PointF sum = new PointF(); for (int ny = neighbors.Bottom; ny < neighbors.Top; ++ny) { for (int nx = neighbors.Left; nx < neighbors.Right; ++nx) { if (mask[ny, nx]) { sum += orientation[ny, nx]; } } } smoothed[y, x] = sum; } } } return(smoothed); }
static PointF[,] AverageBlockOrientations(PointF[,] orientation, BlockMap blocks, bool[,] mask) { PointF[,] sums = new PointF[blocks.BlockCount.Y, blocks.BlockCount.X]; foreach (var block in blocks.AllBlocks) { if (block.Get(mask)) { PointF sum = new PointF(); Rectangle area = blocks.BlockAreas[block]; for (int y = area.Bottom; y < area.Top; ++y) { for (int x = area.Left; x < area.Right; ++x) { sum += orientation[y, x]; } } sums[block.Y, block.X] = sum; } } return(sums); }
static bool[,] ApplyVotingFilter(bool[,] input, int radius = 1, double majority = 0.51, int borderDist = 0) { var size = Point.SizeOf(input); Rectangle rect = new Rectangle(new Point(borderDist, borderDist), new Point(size.X - 2 * borderDist, size.Y - 2 * borderDist)); var output = size.Allocate <bool>(); for (int y = rect.RangeY.Begin; y < rect.RangeY.End; ++y) { for (int x = rect.Left; x < rect.Right; ++x) { Rectangle neighborhood = Rectangle.Between( new Point(Math.Max(x - radius, 0), Math.Max(y - radius, 0)), new Point(Math.Min(x + radius + 1, size.X), Math.Min(y + radius + 1, size.Y))); int ones = 0; for (int ny = neighborhood.Bottom; ny < neighborhood.Top; ++ny) { for (int nx = neighborhood.Left; nx < neighborhood.Right; ++nx) { if (input[ny, nx]) { ++ones; } } } double voteWeight = 1.0 / neighborhood.TotalArea; if (ones * voteWeight >= majority) { output[y, x] = true; } } } return(output); }