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); }
Point[][] ConstructOrientedLines(int resolution = 32, int radius = 7, double step = 1.5) { Point[][] result = new Point[resolution][]; for (int orientationIndex = 0; orientationIndex < resolution; ++orientationIndex) { List <Point> line = new List <Point>(); line.Add(new Point()); PointF direction = Angle.ToVector(Angle.ByBucketCenter(orientationIndex, 2 * resolution)); for (double r = radius; r >= 0.5; r /= step) { Point point = (r * direction).Round(); if (!line.Contains(point)) { line.Add(point); line.Add(-point); } } line.Sort(MathEx.CompareYX); result[orientationIndex] = line.ToArray(); } return(result); }
static PointF[,] ComputePixelwiseOrientation(double[,] input, bool[,] mask, BlockMap blocks) { List <List <ConsideredOrientation> > neighbors = GetTestedOrientations(); PointF[,] orientation = new PointF[input.GetLength(0), input.GetLength(1)]; for (int blockY = 0; blockY < blocks.BlockCount.Y; ++blockY) { Range validMaskRange = GetMaskLineRange(mask, blockY); if (validMaskRange.Length > 0) { Range validXRange = new Range(blocks.BlockAreas[blockY, validMaskRange.Begin].Left, blocks.BlockAreas[blockY, validMaskRange.End - 1].Right); for (int y = blocks.BlockAreas[blockY, 0].Bottom; y < blocks.BlockAreas[blockY, 0].Top; ++y) { foreach (ConsideredOrientation neighbor in neighbors[y % neighbors.Count]) { int radius = Math.Max(Math.Abs(neighbor.CheckLocation.X), Math.Abs(neighbor.CheckLocation.Y)); if (y - radius >= 0 && y + radius < input.GetLength(0)) { Range xRange = new Range(Math.Max(radius, validXRange.Begin), Math.Min(input.GetLength(1) - radius, validXRange.End)); for (int x = xRange.Begin; x < xRange.End; ++x) { double before = input[y - neighbor.CheckLocation.Y, x - neighbor.CheckLocation.X]; double at = input[y, x]; double after = input[y + neighbor.CheckLocation.Y, x + neighbor.CheckLocation.X]; double strength = at - Math.Max(before, after); if (strength > 0) { orientation[y, x] = orientation[y, x] + strength * neighbor.OrientationVector; } } } } } } } return(orientation); }
public static double Atan(PointF point) { return Atan(point.X, point.Y); }