static NeighborhoodType[] NeighborhoodTypes() { var types = new NeighborhoodType[256]; for (uint mask = 0; mask < 256; ++mask) { bool TL = (mask & 1) != 0; bool TC = (mask & 2) != 0; bool TR = (mask & 4) != 0; bool CL = (mask & 8) != 0; bool CR = (mask & 16) != 0; bool BL = (mask & 32) != 0; bool BC = (mask & 64) != 0; bool BR = (mask & 128) != 0; uint count = Integers.PopulationCount(mask); bool diagonal = !TC && !CL && TL || !CL && !BC && BL || !BC && !CR && BR || !CR && !TC && TR; bool horizontal = !TC && !BC && (TR || CR || BR) && (TL || CL || BL); bool vertical = !CL && !CR && (TL || TC || TR) && (BL || BC || BR); bool end = (count == 1); if (end) { types[mask] = NeighborhoodType.Ending; } else if (!diagonal && !horizontal && !vertical) { types[mask] = NeighborhoodType.Removable; } } return(types); }
static bool IsWithinGapLimits(SkeletonMinutia end1, SkeletonMinutia end2) { int distanceSq = (end1.Position - end2.Position).LengthSq; if (distanceSq <= Integers.Sq(Parameters.MaxRuptureSize)) { return(true); } if (distanceSq > Integers.Sq(Parameters.MaxGapSize)) { return(false); } double gapDirection = DoubleAngle.Atan(end1.Position, end2.Position); double direction1 = DoubleAngle.Atan(end1.Position, AngleSampleForGapRemoval(end1)); if (DoubleAngle.Distance(direction1, DoubleAngle.Opposite(gapDirection)) > Parameters.MaxGapAngle) { return(false); } double direction2 = DoubleAngle.Atan(end2.Position, AngleSampleForGapRemoval(end2)); if (DoubleAngle.Distance(direction2, gapDirection) > Parameters.MaxGapAngle) { return(false); } return(true); }
public BlockMap(int width, int height, int maxBlockSize) { Pixels = new IntPoint(width, height); Primary = new BlockGrid(new IntPoint( Integers.RoundUpDiv(Pixels.X, maxBlockSize), Integers.RoundUpDiv(Pixels.Y, maxBlockSize))); for (int y = 0; y <= Primary.Blocks.Y; ++y) { Primary.Y[y] = y * Pixels.Y / Primary.Blocks.Y; } for (int x = 0; x <= Primary.Blocks.X; ++x) { Primary.X[x] = x * Pixels.X / Primary.Blocks.X; } Secondary = new BlockGrid(Primary.Corners); Secondary.Y[0] = 0; for (int y = 0; y < Primary.Blocks.Y; ++y) { Secondary.Y[y + 1] = Primary.Block(0, y).Center.Y; } Secondary.Y[Secondary.Blocks.Y] = Pixels.Y; Secondary.X[0] = 0; for (int x = 0; x < Primary.Blocks.X; ++x) { Secondary.X[x + 1] = Primary.Block(x, 0).Center.X; } Secondary.X[Secondary.Blocks.X] = Pixels.X; }
public EdgeShape(ImmutableMinutia reference, ImmutableMinutia neighbor) { IntPoint vector = neighbor.Position - reference.Position; double quadrant = 0; int x = vector.X; int y = vector.Y; if (y < 0) { x = -x; y = -y; quadrant = Math.PI; } if (x < 0) { int tmp = -x; x = y; y = tmp; quadrant += DoubleAngle.HalfPi; } int shift = 32 - (int)Integers.LeadingZeros(((uint)x | (uint)y) >> PolarCacheBits); int offset = (y >> shift) * PolarCacheRadius + (x >> shift); Length = PolarDistanceCache[offset] << shift; double angle = PolarAngleCache[offset] + quadrant; ReferenceAngle = DoubleAngle.Difference(reference.Direction, angle); NeighborAngle = DoubleAngle.Difference(neighbor.Direction, DoubleAngle.Opposite(angle)); }
static void RemoveMinutiaClouds(List <MutableMinutia> minutiae) { var radiusSq = Integers.Sq(Parameters.MinutiaCloudRadius); var removed = new HashSet <MutableMinutia>(minutiae.Where(minutia => Parameters.MaxCloudSize < minutiae.Where(neighbor => (neighbor.Position - minutia.Position).LengthSq <= radiusSq).Count() - 1)); minutiae.RemoveAll(minutia => removed.Contains(minutia)); }
static BooleanMatrix Vote(BooleanMatrix input, BooleanMatrix mask, int radius, double majority, int borderDistance) { var size = input.Size; var rect = new IntRect(borderDistance, borderDistance, size.X - 2 * borderDistance, size.Y - 2 * borderDistance); int[] thresholds = new int[Integers.Sq(2 * radius + 1) + 1]; for (int i = 0; i < thresholds.Length; ++i) { thresholds[i] = (int)Math.Ceiling(majority * i); } var counts = new IntMatrix(size); var output = new BooleanMatrix(size); for (int y = rect.Top; y < rect.Bottom; ++y) { int superTop = y - radius - 1; int superBottom = y + radius; int yMin = Math.Max(0, y - radius); int yMax = Math.Min(size.Y - 1, y + radius); int yRange = yMax - yMin + 1; for (int x = rect.Left; x < rect.Right; ++x) { if (mask == null || mask[x, y]) { int left = x > 0 ? counts[x - 1, y] : 0; int top = y > 0 ? counts[x, y - 1] : 0; int diagonal = x > 0 && y > 0 ? counts[x - 1, y - 1] : 0; int xMin = Math.Max(0, x - radius); int xMax = Math.Min(size.X - 1, x + radius); int ones; if (left > 0 && top > 0 && diagonal > 0) { ones = top + left - diagonal - 1; int superLeft = x - radius - 1; int superRight = x + radius; if (superLeft >= 0 && superTop >= 0 && input[superLeft, superTop]) { ++ones; } if (superLeft >= 0 && superBottom < size.Y && input[superLeft, superBottom]) { --ones; } if (superRight < size.X && superTop >= 0 && input[superRight, superTop]) { --ones; } if (superRight < size.X && superBottom < size.Y && input[superRight, superBottom]) { ++ones; } } else { ones = 0; for (int ny = yMin; ny <= yMax; ++ny) { for (int nx = xMin; nx <= xMax; ++nx) { if (input[nx, ny]) { ++ones; } } } } counts[x, y] = ones + 1; if (ones >= thresholds[yRange * (xMax - xMin + 1)]) { output[x, y] = true; } } } } return(output); }