public float[,] Smooth(float[,] input, byte[,] orientation, BinaryMap mask, BlockMap blocks) { Point[][] lines = Lines.Construct(); float[,] output = new float[input.GetLength(0), input.GetLength(1)]; Parallel.ForEach(blocks.AllBlocks, delegate(Point block) { if (mask.GetBit(block)) { Point[] line = lines[Angle.Quantize(Angle.Add(orientation[block.Y, block.X], AngleOffset), lines.Length)]; foreach (Point linePoint in line) { RectangleC target = blocks.BlockAreas[block]; RectangleC source = target.GetShifted(linePoint); source.Clip(new RectangleC(blocks.PixelCount)); target = source.GetShifted(Calc.Negate(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]; } RectangleC 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] *= 1f / line.Length; } }); Logger.Log(output); return output; }
public void Remove(BinaryMap input) { BinaryMap sw2ne = new BinaryMap(input.Size); BinaryMap se2nw = new BinaryMap(input.Size); BinaryMap positions = new BinaryMap(input.Size); BinaryMap squares = new BinaryMap(input.Size); while (true) { sw2ne.Copy(input, new RectangleC(0, 0, input.Width - 1, input.Height - 1), new Point()); sw2ne.And(input, new RectangleC(1, 1, input.Width - 1, input.Height - 1), new Point()); sw2ne.AndNot(input, new RectangleC(0, 1, input.Width - 1, input.Height - 1), new Point()); sw2ne.AndNot(input, new RectangleC(1, 0, input.Width - 1, input.Height - 1), new Point()); se2nw.Copy(input, new RectangleC(0, 1, input.Width - 1, input.Height - 1), new Point()); se2nw.And(input, new RectangleC(1, 0, input.Width - 1, input.Height - 1), new Point()); se2nw.AndNot(input, new RectangleC(0, 0, input.Width - 1, input.Height - 1), new Point()); se2nw.AndNot(input, new RectangleC(1, 1, input.Width - 1, input.Height - 1), new Point()); positions.Copy(sw2ne); positions.Or(se2nw); if (positions.IsEmpty()) break; squares.Copy(positions); squares.Or(positions, new RectangleC(0, 0, positions.Width - 1, positions.Height - 1), new Point(1, 0)); squares.Or(positions, new RectangleC(0, 0, positions.Width - 1, positions.Height - 1), new Point(0, 1)); squares.Or(positions, new RectangleC(0, 0, positions.Width - 1, positions.Height - 1), new Point(1, 1)); input.AndNot(squares); } Logger.Log(input); }
void Combine(BinaryMap source, RectangleC area, Point at, CombineFunction function) { int shift = (int)((uint)area.X & WordMask) - (int)((uint)at.X & WordMask); int vectorSize = (area.Width >> WordShift) + 2; Parallel.For(0, area.Height, () => new CombineLocals { Vector = new uint[vectorSize], SrcVector = new uint[vectorSize] }, delegate(int y, ParallelLoopState state, CombineLocals locals) { LoadLine(locals.Vector, new Point(at.X, at.Y + y), area.Width); source.LoadLine(locals.SrcVector, new Point(area.X, area.Y + y), area.Width); if (shift >= 0) { ShiftLeft(locals.SrcVector, shift); } else { ShiftRight(locals.SrcVector, -shift); } function(locals.Vector, locals.SrcVector); SaveLine(locals.Vector, new Point(at.X, at.Y + y), area.Width); return(locals); }, locals => { }); }
float[,] PerformEqualization(BlockMap blocks, byte[,] image, float[, ,] equalization, BinaryMap blockMask) { float[,] result = new float[blocks.PixelCount.Height, blocks.PixelCount.Width]; Parallel.ForEach(blocks.AllBlocks, delegate(Point block) { if (blockMask.GetBit(block)) { RectangleC area = blocks.BlockAreas[block]; for (int y = area.Bottom; y < area.Top; ++y) for (int x = area.Left; x < area.Right; ++x) { byte pixel = image[y, x]; float bottomLeft = equalization[block.Y, block.X, pixel]; float bottomRight = equalization[block.Y, block.X + 1, pixel]; float topLeft = equalization[block.Y + 1, block.X, pixel]; float topRight = equalization[block.Y + 1, block.X + 1, pixel]; PointF fraction = area.GetFraction(new Point(x, y)); result[y, x] = Calc.Interpolate(topLeft, topRight, bottomLeft, bottomRight, fraction); } } }); Logger.Log(result); return result; }
public BinaryMap DetectLowContrast(byte[,] contrast, BlockMap blocks) { List<byte> sortedContrast = new List<byte>(); foreach (byte contrastItem in contrast) sortedContrast.Add(contrastItem); sortedContrast.Sort(); sortedContrast.Reverse(); int pixelsPerBlock = Calc.GetArea(blocks.PixelCount) / blocks.AllBlocks.TotalArea; int sampleCount = Math.Min(sortedContrast.Count, SampleSize / pixelsPerBlock); int consideredBlocks = Math.Max(Convert.ToInt32(sampleCount * SampleFraction), 1); int averageContrast = 0; for (int i = 0; i < consideredBlocks; ++i) averageContrast += sortedContrast[i]; averageContrast /= consideredBlocks; byte limit = Convert.ToByte(averageContrast * RelativeLimit); BinaryMap result = new BinaryMap(blocks.BlockCount.Width, blocks.BlockCount.Height); for (int y = 0; y < result.Height; ++y) for (int x = 0; x < result.Width; ++x) if (contrast[y, x] < limit) result.SetBitOne(x, y); Logger.Log(result); return result; }
public BinaryMap Filter(BinaryMap input) { RectangleC rect = new RectangleC(new Point(BorderDistance, BorderDistance), new Size(input.Width - 2 * BorderDistance, input.Height - 2 * BorderDistance)); BinaryMap output = new BinaryMap(input.Size); Parallel.For(rect.RangeY.Begin, rect.RangeY.End, delegate(int y) { for (int x = rect.Left; x < rect.Right; ++x) { RectangleC neighborhood = new RectangleC( new Point(Math.Max(x - Radius, 0), Math.Max(y - Radius, 0)), new Point(Math.Min(x + Radius + 1, output.Width), Math.Min(y + Radius + 1, output.Height))); int ones = 0; for (int ny = neighborhood.Bottom; ny < neighborhood.Top; ++ny) for (int nx = neighborhood.Left; nx < neighborhood.Right; ++nx) if (input.GetBit(nx, ny)) ++ones; double voteWeight = 1.0 / neighborhood.TotalArea; if (ones * voteWeight >= Majority) output.SetBitOne(x, y); } }); Logger.Log(output); return output; }
public void And(BinaryMap source, RectangleC area, Point at) { Combine(source, area, at, delegate(uint[] target, uint[] srcVector) { for (int i = 0; i < target.Length; ++i) target[i] &= srcVector[i]; }); }
void ShrinkBy(BinaryMap temporary, BinaryMap inner, int amount) { temporary.Clear(); temporary.Copy(inner, new RectangleC(amount, 0, inner.Width - amount, inner.Height), new Point(0, 0)); temporary.And(inner, new RectangleC(0, 0, inner.Width - amount, inner.Height), new Point(amount, 0)); temporary.And(inner, new RectangleC(0, amount, inner.Width, inner.Height - amount), new Point(0, 0)); temporary.And(inner, new RectangleC(0, 0, inner.Width, inner.Height - amount), new Point(0, amount)); inner.Copy(temporary); }
List<Point> FindMinutiae(BinaryMap binary) { List<Point> result = new List<Point>(); for (int y = 0; y < binary.Height; ++y) for (int x = 0; x < binary.Width; ++x) if (binary.GetBit(x, y) && IsMinutia[binary.GetNeighborhood(x, y)]) result.Add(new Point(x, y)); return result; }
public void Trace(BinaryMap binary, SkeletonBuilder skeleton) { List<Point> minutiaPoints = FindMinutiae(binary); Dictionary<Point, List<Point>> linking = LinkNeighboringMinutiae(minutiaPoints); Dictionary<Point, SkeletonBuilder.Minutia> minutiaMap = ComputeMinutiaCenters(linking, skeleton); TraceRidges(binary, minutiaMap); FixLinkingGaps(skeleton); Logger.Log(skeleton); }
public BinaryMap Thin(BinaryMap input) { BinaryMap intermediate = new BinaryMap(input.Size); intermediate.Copy(input, new RectangleC(1, 1, input.Width - 2, input.Height - 2), new Point(1, 1)); BinaryMap border = new BinaryMap(input.Size); BinaryMap skeleton = new BinaryMap(input.Size); bool removedAnything = true; for (int i = 0; i < MaxIterations && removedAnything; ++i) { removedAnything = false; for (int j = 0; j < 4; ++j) { border.Copy(intermediate); switch (j) { case 0: border.AndNot(intermediate, new RectangleC(1, 0, border.Width - 1, border.Height), new Point(0, 0)); break; case 1: border.AndNot(intermediate, new RectangleC(0, 0, border.Width - 1, border.Height), new Point(1, 0)); break; case 2: border.AndNot(intermediate, new RectangleC(0, 1, border.Width, border.Height - 1), new Point(0, 0)); break; case 3: border.AndNot(intermediate, new RectangleC(0, 0, border.Width, border.Height - 1), new Point(0, 1)); break; } border.AndNot(skeleton); for (int odd = 0; odd < 2; ++odd) Parallel.For(1, input.Height - 1, delegate(int y) { if (y % 2 == odd) for (int xw = 0; xw < input.WordWidth; ++xw) if (border.IsWordNonZero(xw, y)) for (int x = xw << BinaryMap.WordShift; x < (xw << BinaryMap.WordShift) + BinaryMap.WordSize; ++x) if (x > 0 && x < input.Width - 1 && border.GetBit(x, y)) { uint neighbors = intermediate.GetNeighborhood(x, y); if (IsRemovable[neighbors] || IsEnding[neighbors] && IsFalseEnding(intermediate, new Point(x, y))) { removedAnything = true; intermediate.SetBitZero(x, y); } else skeleton.SetBitOne(x, y); } }); } } Logger.Log(skeleton); return skeleton; }
public byte[,] Detect(float[,] image, BinaryMap mask, BlockMap blocks) { PointF[,] accumulated = AccumulateOrientations(image, mask, blocks); PointF[,] byBlock = SumBlocks(accumulated, blocks, mask); PointF[,] smooth = Smooth(byBlock, mask); byte[,] angles = ToAngles(smooth, mask); Logger.Log(angles); return angles; }
void AddRidge(SkeletonBuilder skeleton, BinaryMap shadow, Gap gap, Point[] line) { SkeletonBuilder.Ridge ridge = new SkeletonBuilder.Ridge(); foreach (Point point in line) ridge.Points.Add(point); ridge.Start = gap.End1; ridge.End = gap.End2; foreach (Point point in line) shadow.SetBitOne(point); }
static bool IsFalseEnding(BinaryMap binary, Point ending) { foreach (Point relativeNeighbor in Neighborhood.CornerNeighbors) { Point neighbor = Calc.Add(ending, relativeNeighbor); if (binary.GetBit(neighbor)) return Calc.CountBits(binary.GetNeighborhood(neighbor)) > 2; } return false; }
public BinaryMap(BinaryMap other) { Width = other.Width; Height = other.Height; WordWidth = other.WordWidth; Map = new uint[other.Map.GetLength(0), other.Map.GetLength(1)]; for (int y = 0; y < Map.GetLength(0); ++y) for (int x = 0; x < Map.GetLength(1); ++x) Map[y, x] = other.Map[y, x]; }
public BinaryMap DetectLowContrast(byte[,] contrast) { BinaryMap result = new BinaryMap(contrast.GetLength(1), contrast.GetLength(0)); for (int y = 0; y < result.Height; ++y) for (int x = 0; x < result.Width; ++x) if (contrast[y, x] < Limit) result.SetBitOne(x, y); Logger.Log(result); return result; }
public void AndNot(BinaryMap source, RectangleC area, Point at) { Combine(source, area, at, delegate(uint[] target, uint[] srcVector) { for (int i = 0; i < target.Length; ++i) { target[i] &= ~srcVector[i]; } }); }
public void Draw(SkeletonBuilder skeleton, BinaryMap binary) { foreach (SkeletonBuilder.Minutia minutia in skeleton.Minutiae) { binary.SetBitOne(minutia.Position); foreach (SkeletonBuilder.Ridge ridge in minutia.Ridges) if (ridge.Start.Position.Y <= ridge.End.Position.Y) foreach (Point point in ridge.Points) binary.SetBitOne(point); } }
public BinaryMap(BinaryMap other) { Width = other.Width; Height = other.Height; WordWidth = other.WordWidth; Map = new uint[other.Map.GetLength(0), other.Map.GetLength(1)]; for (int y = 0; y < Map.GetLength(0); ++y) { for (int x = 0; x < Map.GetLength(1); ++x) { Map[y, x] = other.Map[y, x]; } } }
Range GetMaskLineRange(BinaryMap mask, int y) { int first = -1; int last = -1; for (int x = 0; x < mask.Width; ++x) if (mask.GetBit(x, y)) { last = x; if (first < 0) first = x; } if (first >= 0) return new Range(first, last + 1); else return new Range(); }
public BinaryMap FillCornerAreas(BlockMap blocks) { BinaryMap result = new BinaryMap(blocks.PixelCount); Parallel.For(0, blocks.CornerCount.Height, delegate(int cornerY) { for (int cornerX = 0; cornerX < blocks.CornerCount.Width; ++cornerX) { if (GetBit(cornerX, cornerY)) { result.Fill(blocks.CornerAreas[cornerY, cornerX]); } } }); return(result); }
public BinaryMap FillBlocks(BlockMap blocks) { BinaryMap result = new BinaryMap(blocks.PixelCount); Parallel.For(0, blocks.BlockCount.Height, delegate(int blockY) { for (int blockX = 0; blockX < blocks.BlockCount.Width; ++blockX) { if (GetBit(blockX, blockY)) { result.Fill(blocks.BlockAreas[blockY, blockX]); } } }); return(result); }
public BinaryMap Compute(BinaryMap outer) { BinaryMap inner = new BinaryMap(outer.Size); inner.Copy(outer, new RectangleC(1, 1, outer.Width - 2, outer.Height - 2), new Point(1, 1)); BinaryMap temporary = new BinaryMap(outer.Size); if (MinBorderDistance >= 1) ShrinkBy(temporary, inner, 1); int total = 1; for (int step = 1; total + step <= MinBorderDistance; step *= 2) { ShrinkBy(temporary, inner, step); total += step; } if (total < MinBorderDistance) ShrinkBy(temporary, inner, MinBorderDistance - total); Logger.Log(inner); return inner; }
float[, ,] ComputeEqualization(BlockMap blocks, short[, ,] histogram, BinaryMap blockMask) { float widthMax = RangeSize / 256f * MaxScaling; float widthMin = RangeSize / 256f * MinScaling; float[] limitedMin = new float[256]; float[] limitedMax = new float[256]; for (int i = 0; i < 256; ++i) { limitedMin[i] = Math.Max(i * widthMin + RangeMin, RangeMax - (255 - i) * widthMax); limitedMax[i] = Math.Min(i * widthMax + RangeMin, RangeMax - (255 - i) * widthMin); } float[, ,] equalization = new float[blocks.CornerCount.Height, blocks.CornerCount.Width, 256]; Parallel.ForEach(blocks.AllCorners, delegate(Point corner) { if (blockMask.GetBitSafe(corner.X, corner.Y, false) || blockMask.GetBitSafe(corner.X - 1, corner.Y, false) || blockMask.GetBitSafe(corner.X, corner.Y - 1, false) || blockMask.GetBitSafe(corner.X - 1, corner.Y - 1, false)) { int area = 0; for (int i = 0; i < 256; ++i) area += histogram[corner.Y, corner.X, i]; float widthWeigth = RangeSize / area; float top = RangeMin; for (int i = 0; i < 256; ++i) { float width = histogram[corner.Y, corner.X, i] * widthWeigth; float equalized = top + ToFloatTable[i] * width; top += width; float limited = equalized; if (limited < limitedMin[i]) limited = limitedMin[i]; if (limited > limitedMax[i]) limited = limitedMax[i]; equalization[corner.Y, corner.X, i] = limited; } } }); return equalization; }
public BinaryMap GetInverted() { BinaryMap result = new BinaryMap(Size); for (int y = 0; y < Map.GetLength(0); ++y) { for (int x = 0; x < Map.GetLength(1); ++x) { result.Map[y, x] = ~Map[y, x]; } } if (((uint)Width & WordMask) != 0u) { for (int y = 0; y < Map.GetLength(0); ++y) { result.Map[y, Map.GetLength(1) - 1] &= ~0u >> (WordSize - (int)((uint)Width & WordMask)); } } return(result); }
public BinaryMap Binarize(float[,] input, float[,] baseline, BinaryMap mask, BlockMap blocks) { BinaryMap binarized = new BinaryMap(input.GetLength(1), input.GetLength(0)); Parallel.For(0, blocks.AllBlocks.Height, delegate(int blockY) { for (int blockX = 0; blockX < blocks.AllBlocks.Width; ++blockX) { if (mask.GetBit(blockX, blockY)) { RectangleC 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.SetBitOne(x, y); } } }); Logger.Log(binarized); return binarized; }
public void Copy(BinaryMap source, RectangleC area, Point at) { int shift = (int)((uint)area.X & WordMask) - (int)((uint)at.X & WordMask); Parallel.For(0, area.Height, () => new uint[(area.Width >> WordShift) + 2], delegate(int y, ParallelLoopState state, uint[] vector) { source.LoadLine(vector, new Point(area.X, area.Y + y), area.Width); if (shift >= 0) { ShiftLeft(vector, shift); } else { ShiftRight(vector, -shift); } SaveLine(vector, new Point(at.X, at.Y + y), area.Width); return(vector); }, vector => { }); }
PointF[,] AccumulateOrientations(float[,] input, BinaryMap mask, BlockMap blocks) { List<List<NeighborInfo>> neighbors = PrepareNeighbors(); PointF[,] orientation = new PointF[input.GetLength(0), input.GetLength(1)]; Parallel.For(0, mask.Height, delegate(int 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 (NeighborInfo neighbor in neighbors[y % neighbors.Count]) { int radius = Math.Max(Math.Abs(neighbor.Position.X), Math.Abs(neighbor.Position.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) { float before = input[y - neighbor.Position.Y, x - neighbor.Position.X]; float at = input[y, x]; float after = input[y + neighbor.Position.Y, x + neighbor.Position.X]; float strength = at - Math.Max(before, after); if (strength > 0) orientation[y, x] = Calc.Add(orientation[y, x], Calc.Multiply(strength, neighbor.Orientation)); } } } } } }); Logger.Log("Raw", orientation); return orientation; }
public void OrNot(BinaryMap source) { OrNot(source, Rect, new Point()); }
public void Xor(BinaryMap source) { Xor(source, Rect, new Point()); }
public void AndNot(BinaryMap source) { AndNot(source, Rect, new Point()); }
public void OrNot(BinaryMap source) { OrNot(source, Rect, new Point()); }
public void Xor(BinaryMap source) { Xor(source, Rect, new Point()); }
public void Copy(BinaryMap source) { Copy(source, Rect, new Point()); }
public float[,] Equalize(BlockMap blocks, byte[,] image, short[, ,] histogram, BinaryMap blockMask) { float[, ,] equalization = ComputeEqualization(blocks, histogram, blockMask); return PerformEqualization(blocks, image, equalization, blockMask); }
public void AndNot(BinaryMap source) { AndNot(source, Rect, new Point()); }
byte[,] ToAngles(PointF[,] vectors, BinaryMap mask) { byte[,] angles = new byte[mask.Height, mask.Width]; Parallel.For(0, mask.Height, delegate(int y) { for (int x = 0; x < mask.Width; ++x) if (mask.GetBit(x, y)) angles[y, x] = Angle.ToByte(Angle.Atan(vectors[y, x])); }); return angles; }
PointF[,] Smooth(PointF[,] orientation, BinaryMap mask) { PointF[,] smoothed = new PointF[mask.Height, mask.Width]; Parallel.For(0, mask.Height, delegate(int y) { for (int x = 0; x < mask.Width; ++x) if (mask.GetBit(x, y)) { RectangleC neighbors = new RectangleC( new Point(Math.Max(0, x - SmoothingRadius), Math.Max(0, y - SmoothingRadius)), new Point(Math.Min(mask.Width, x + SmoothingRadius + 1), Math.Min(mask.Height, y + SmoothingRadius + 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.GetBit(nx, ny)) sum = Calc.Add(sum, orientation[ny, nx]); smoothed[y, x] = sum; } }); return smoothed; }
PointF[,] SumBlocks(PointF[,] orientation, BlockMap blocks, BinaryMap mask) { PointF[,] sums = new PointF[blocks.BlockCount.Height, blocks.BlockCount.Width]; Parallel.ForEach(blocks.AllBlocks, delegate(Point block) { if (mask.GetBit(block)) { PointF sum = new PointF(); RectangleC area = blocks.BlockAreas[block]; for (int y = area.Bottom; y < area.Top; ++y) for (int x = area.Left; x < area.Right; ++x) sum = Calc.Add(sum, orientation[y, x]); sums[block.Y, block.X] = sum; } }); return sums; }
void Combine(BinaryMap source, RectangleC area, Point at, CombineFunction function) { int shift = (int)((uint)area.X & WordMask) - (int)((uint)at.X & WordMask); int vectorSize = (area.Width >> WordShift) + 2; Parallel.For(0, area.Height, () => new CombineLocals { Vector = new uint[vectorSize], SrcVector = new uint[vectorSize] }, delegate(int y, ParallelLoopState state, CombineLocals locals) { LoadLine(locals.Vector, new Point(at.X, at.Y + y), area.Width); source.LoadLine(locals.SrcVector, new Point(area.X, area.Y + y), area.Width); if (shift >= 0) ShiftLeft(locals.SrcVector, shift); else ShiftRight(locals.SrcVector, -shift); function(locals.Vector, locals.SrcVector); SaveLine(locals.Vector, new Point(at.X, at.Y + y), area.Width); return locals; }, locals => { }); }
public BinaryMap Filter(BinaryMap input) { ////Testing Start //Count++; //var inFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "inputBinary" + Count + ".bin"); //var outFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "outputBinary" + Count + ".bin"); //var file = new FileStream(inFileDir, FileMode.CreateNew); //var binWrite = new BinaryWriter(file); //binWrite.Write(input.WordWidth); //Console.WriteLine(input.WordWidth); //binWrite.Write(input.Width); //Console.WriteLine(input.Width); //binWrite.Write(input.Height); //Console.WriteLine(input.Height); //foreach (var i in input.Map) //{ // binWrite.Write(i); // Console.WriteLine(i); //} //binWrite.Close(); //file.Close(); ////Testing Finish RectangleC rect = new RectangleC(new Point(BorderDistance, BorderDistance), new Size(input.Width - 2 * BorderDistance, input.Height - 2 * BorderDistance)); BinaryMap output = new BinaryMap(input.Size); Parallel.For(rect.RangeY.Begin, rect.RangeY.End, delegate (int y) { for (int x = rect.Left; x < rect.Right; ++x) { RectangleC neighborhood = new RectangleC( new Point(Math.Max(x - Radius, 0), Math.Max(y - Radius, 0)), new Point(Math.Min(x + Radius + 1, output.Width), Math.Min(y + Radius + 1, output.Height))); int ones = 0; for (int ny = neighborhood.Bottom; ny < neighborhood.Top; ++ny) for (int nx = neighborhood.Left; nx < neighborhood.Right; ++nx) if (input.GetBit(nx, ny)) ++ones; double voteWeight = 1.0 / neighborhood.TotalArea; if (ones * voteWeight >= Majority) output.SetBitOne(x, y); } }); Logger.Log(output); ////Testing //file = new FileStream(outFileDir, FileMode.CreateNew); //binWrite = new BinaryWriter(file); //binWrite.Write(output.WordWidth); //binWrite.Write(output.Width); //binWrite.Write(output.Height); //foreach (var i in output.Map) //{ // binWrite.Write(i); //} //binWrite.Close(); //file.Close(); ////Testing End return output; }