示例#1
0
        static BooleanMatrix FilterRelativeContrast(DoubleMatrix contrast, BlockMap blocks)
        {
            var sortedContrast = new List <double>();

            foreach (var block in contrast.Size.Iterate())
            {
                sortedContrast.Add(contrast[block]);
            }
            sortedContrast.Sort();
            sortedContrast.Reverse();
            int    pixelsPerBlock   = blocks.Pixels.Area / blocks.Primary.Blocks.Area;
            int    sampleCount      = Math.Min(sortedContrast.Count, Parameters.RelativeContrastSample / pixelsPerBlock);
            int    consideredBlocks = Math.Max(Doubles.RoundToInt(sampleCount * Parameters.RelativeContrastPercentile), 1);
            double averageContrast  = 0;

            for (int i = 0; i < consideredBlocks; ++i)
            {
                averageContrast += sortedContrast[i];
            }
            averageContrast /= consideredBlocks;
            var limit  = averageContrast * Parameters.MinRelativeContrast;
            var result = new BooleanMatrix(blocks.Primary.Blocks);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                if (contrast[block] < limit)
                {
                    result[block] = true;
                }
            }
            // https://sourceafis.machinezoo.com/transparency/relative-contrast-mask
            FingerprintTransparency.Current.Log("relative-contrast-mask", result);
            return(result);
        }
示例#2
0
        static DoublePointMatrix SmoothOrientation(DoublePointMatrix orientation, BooleanMatrix mask)
        {
            var size     = mask.Size;
            var smoothed = new DoublePointMatrix(size);

            foreach (var block in size.Iterate())
            {
                if (mask[block])
                {
                    var neighbors = IntRect.Around(block, Parameters.OrientationSmoothingRadius).Intersect(new IntRect(size));
                    for (int ny = neighbors.Top; ny < neighbors.Bottom; ++ny)
                    {
                        for (int nx = neighbors.Left; nx < neighbors.Right; ++nx)
                        {
                            if (mask[nx, ny])
                            {
                                smoothed.Add(block, orientation[nx, ny]);
                            }
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/smoothed-orientation
            FingerprintTransparency.Current.Log("smoothed-orientation", smoothed);
            return(smoothed);
        }
示例#3
0
        static BooleanMatrix InnerMask(BooleanMatrix outer)
        {
            var size  = outer.Size;
            var inner = new BooleanMatrix(size);

            for (int y = 1; y < size.Y - 1; ++y)
            {
                for (int x = 1; x < size.X - 1; ++x)
                {
                    inner[x, y] = outer[x, y];
                }
            }
            if (Parameters.InnerMaskBorderDistance >= 1)
            {
                inner = ShrinkMask(inner, 1);
            }
            int total = 1;

            for (int step = 1; total + step <= Parameters.InnerMaskBorderDistance; step *= 2)
            {
                inner  = ShrinkMask(inner, step);
                total += step;
            }
            if (total < Parameters.InnerMaskBorderDistance)
            {
                inner = ShrinkMask(inner, Parameters.InnerMaskBorderDistance - total);
            }
            // https://sourceafis.machinezoo.com/transparency/inner-mask
            FingerprintTransparency.Current.Log("inner-mask", inner);
            return(inner);
        }
示例#4
0
        static BooleanMatrix Binarize(DoubleMatrix input, DoubleMatrix baseline, BooleanMatrix mask, BlockMap blocks)
        {
            var size      = input.Size;
            var binarized = new BooleanMatrix(size);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                if (mask[block])
                {
                    var rect = blocks.Primary.Block(block);
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        for (int x = rect.Left; x < rect.Right; ++x)
                        {
                            if (input[x, y] - baseline[x, y] > 0)
                            {
                                binarized[x, y] = true;
                            }
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/binarized-image
            FingerprintTransparency.Current.Log("binarized-image", binarized);
            return(binarized);
        }
示例#5
0
        static IntRange MaskRange(BooleanMatrix mask, int y)
        {
            int first = -1;
            int last  = -1;

            for (int x = 0; x < mask.Width; ++x)
            {
                if (mask[x, y])
                {
                    last = x;
                    if (first < 0)
                    {
                        first = x;
                    }
                }
            }
            if (first >= 0)
            {
                return(new IntRange(first, last + 1));
            }
            else
            {
                return(IntRange.Zero);
            }
        }
示例#6
0
 static void MaskMinutiae(List <MutableMinutia> minutiae, BooleanMatrix mask)
 {
     minutiae.RemoveAll(minutia =>
     {
         var arrow = (-Parameters.MaskDisplacement * DoubleAngle.ToVector(minutia.Direction)).Round();
         return(!mask.Get(minutia.Position + arrow, false));
     });
 }
 public BooleanMatrix(BooleanMatrix other)
     : this(other.Size)
 {
     for (int i = 0; i < Cells.Length; ++i)
     {
         Cells[i] = other.Cells[i];
     }
 }
示例#8
0
        static DoubleMatrix OrientationMap(DoubleMatrix image, BooleanMatrix mask, BlockMap blocks)
        {
            var accumulated = PixelwiseOrientation(image, mask, blocks);
            var byBlock     = BlockOrientations(accumulated, blocks, mask);
            var smooth      = SmoothOrientation(byBlock, mask);

            return(OrientationAngles(smooth, mask));
        }
示例#9
0
        BooleanMatrix Thin(BooleanMatrix input)
        {
            var neighborhoodTypes = NeighborhoodTypes();
            var mutable           = new BooleanMatrix(Size);

            for (int y = 1; y < Size.Y - 1; ++y)
            {
                for (int x = 1; x < Size.X - 1; ++x)
                {
                    mutable[x, y] = input[x, y];
                }
            }
            var  thinned         = new BooleanMatrix(Size);
            bool removedAnything = true;

            for (int i = 0; i < Parameters.ThinningIterations && removedAnything; ++i)
            {
                removedAnything = false;
                for (int evenY = 0; evenY < 2; ++evenY)
                {
                    for (int evenX = 0; evenX < 2; ++evenX)
                    {
                        for (int y = 1 + evenY; y < Size.Y - 1; y += 2)
                        {
                            for (int x = 1 + evenX; x < Size.X - 1; x += 2)
                            {
                                if (mutable[x, y] && !thinned[x, y] && !(mutable[x, y - 1] && mutable[x, y + 1] && mutable[x - 1, y] && mutable[x + 1, y]))
                                {
                                    uint neighbors = (mutable[x + 1, y + 1] ? 128u : 0u)
                                                     | (mutable[x, y + 1] ? 64u : 0u)
                                                     | (mutable[x - 1, y + 1] ? 32u : 0u)
                                                     | (mutable[x + 1, y] ? 16u : 0u)
                                                     | (mutable[x - 1, y] ? 8u : 0u)
                                                     | (mutable[x + 1, y - 1] ? 4u : 0u)
                                                     | (mutable[x, y - 1] ? 2u : 0u)
                                                     | (mutable[x - 1, y - 1] ? 1u : 0u);
                                    if (neighborhoodTypes[neighbors] == NeighborhoodType.Removable ||
                                        neighborhoodTypes[neighbors] == NeighborhoodType.Ending &&
                                        IsFalseEnding(mutable, new IntPoint(x, y)))
                                    {
                                        removedAnything = true;
                                        mutable[x, y]   = false;
                                    }
                                    else
                                    {
                                        thinned[x, y] = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/thinned-skeleton
            FingerprintTransparency.Current.Log(Prefix(Type) + "thinned-skeleton", thinned);
            return(thinned);
        }
示例#10
0
 public void Merge(BooleanMatrix other)
 {
     if (other.Width != Width || other.Height != Height)
     {
         throw new ArgumentException();
     }
     for (int i = 0; i < Cells.Length; ++i)
     {
         Cells[i] |= other.Cells[i];
     }
 }
示例#11
0
 static bool IsRidgeOverlapping(IntPoint[] line, BooleanMatrix shadow)
 {
     for (int i = Parameters.ToleratedGapOverlap; i < line.Length - Parameters.ToleratedGapOverlap; ++i)
     {
         if (shadow[line[i]])
         {
             return(true);
         }
     }
     return(false);
 }
示例#12
0
        static BooleanMatrix ShrinkMask(BooleanMatrix mask, int amount)
        {
            var size   = mask.Size;
            var shrunk = new BooleanMatrix(size);

            for (int y = amount; y < size.Y - amount; ++y)
            {
                for (int x = amount; x < size.X - amount; ++x)
                {
                    shrunk[x, y] = mask[x, y - amount] && mask[x, y + amount] && mask[x - amount, y] && mask[x + amount, y];
                }
            }
            return(shrunk);
        }
示例#13
0
        static DoubleMatrix OrientationAngles(DoublePointMatrix vectors, BooleanMatrix mask)
        {
            var size   = mask.Size;
            var angles = new DoubleMatrix(size);

            foreach (var block in size.Iterate())
            {
                if (mask[block])
                {
                    angles[block] = DoubleAngle.Atan(vectors[block]);
                }
            }
            return(angles);
        }
示例#14
0
        static BooleanMatrix Invert(BooleanMatrix binary, BooleanMatrix mask)
        {
            var size     = binary.Size;
            var inverted = new BooleanMatrix(size);

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    inverted[x, y] = !binary[x, y] && mask[x, y];
                }
            }
            return(inverted);
        }
示例#15
0
        static void AddGapRidge(BooleanMatrix shadow, Gap gap, IntPoint[] line)
        {
            var ridge = new SkeletonRidge();

            foreach (var point in line)
            {
                ridge.Points.Add(point);
            }
            ridge.Start = gap.End1;
            ridge.End   = gap.End2;
            foreach (var point in line)
            {
                shadow[point] = true;
            }
        }
示例#16
0
        static BooleanMatrix FilterAbsoluteContrast(DoubleMatrix contrast)
        {
            var result = new BooleanMatrix(contrast.Size);

            foreach (var block in contrast.Size.Iterate())
            {
                if (contrast[block] < Parameters.MinAbsoluteContrast)
                {
                    result[block] = true;
                }
            }
            // https://sourceafis.machinezoo.com/transparency/absolute-contrast-mask
            FingerprintTransparency.Current.Log("absolute-contrast-mask", result);
            return(result);
        }
示例#17
0
        static BooleanMatrix FillBlocks(BooleanMatrix mask, BlockMap blocks)
        {
            var pixelized = new BooleanMatrix(blocks.Pixels);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                if (mask[block])
                {
                    foreach (var pixel in blocks.Primary.Block(block).Iterate())
                    {
                        pixelized[pixel] = true;
                    }
                }
            }
            return(pixelized);
        }
示例#18
0
        public Skeleton(BooleanMatrix binary, SkeletonType type)
        {
            Type = type;
            // https://sourceafis.machinezoo.com/transparency/binarized-skeleton
            FingerprintTransparency.Current.Log(Prefix(Type) + "binarized-skeleton", binary);
            Size = binary.Size;
            var thinned       = Thin(binary);
            var minutiaPoints = FindMinutiae(thinned);
            var linking       = LinkNeighboringMinutiae(minutiaPoints);
            var minutiaMap    = MinutiaCenters(linking);

            TraceRidges(thinned, minutiaMap);
            FixLinkingGaps();
            // https://sourceafis.machinezoo.com/transparency/traced-skeleton
            FingerprintTransparency.Current.LogSkeleton("traced-skeleton", this);
            Filter();
        }
示例#19
0
        BooleanMatrix Shadow()
        {
            var shadow = new BooleanMatrix(Size);

            foreach (var minutia in Minutiae)
            {
                shadow[minutia.Position] = true;
                foreach (var ridge in minutia.Ridges)
                {
                    if (ridge.Start.Position.Y <= ridge.End.Position.Y)
                    {
                        foreach (var point in ridge.Points)
                        {
                            shadow[point] = true;
                        }
                    }
                }
            }
            return(shadow);
        }
示例#20
0
 static bool IsFalseEnding(BooleanMatrix binary, IntPoint ending)
 {
     foreach (var relativeNeighbor in IntPoint.CornerNeighbors)
     {
         var neighbor = ending + relativeNeighbor;
         if (binary[neighbor])
         {
             int count = 0;
             foreach (var relative2 in IntPoint.CornerNeighbors)
             {
                 if (binary.Get(neighbor + relative2, false))
                 {
                     ++count;
                 }
             }
             return(count > 2);
         }
     }
     return(false);
 }
示例#21
0
        static void CleanupBinarized(BooleanMatrix binary, BooleanMatrix mask)
        {
            var size     = binary.Size;
            var inverted = new BooleanMatrix(binary);

            inverted.Invert();
            var islands = Vote(inverted, mask, Parameters.BinarizedVoteRadius, Parameters.BinarizedVoteMajority, Parameters.BinarizedVoteBorderDistance);
            var holes   = Vote(binary, mask, Parameters.BinarizedVoteRadius, Parameters.BinarizedVoteMajority, Parameters.BinarizedVoteBorderDistance);

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    binary[x, y] = binary[x, y] && !islands[x, y] || holes[x, y];
                }
            }
            RemoveCrosses(binary);
            // https://sourceafis.machinezoo.com/transparency/filtered-binary-image
            FingerprintTransparency.Current.Log("filtered-binary-image", binary);
        }
示例#22
0
        static DoublePointMatrix PixelwiseOrientation(DoubleMatrix input, BooleanMatrix mask, BlockMap blocks)
        {
            var neighbors   = PlanOrientations();
            var orientation = new DoublePointMatrix(input.Size);

            for (int blockY = 0; blockY < blocks.Primary.Blocks.Y; ++blockY)
            {
                var maskRange = MaskRange(mask, blockY);
                if (maskRange.Length > 0)
                {
                    var validXRange = new IntRange(
                        blocks.Primary.Block(maskRange.Start, blockY).Left,
                        blocks.Primary.Block(maskRange.End - 1, blockY).Right);
                    for (int y = blocks.Primary.Block(0, blockY).Top; y < blocks.Primary.Block(0, blockY).Bottom; ++y)
                    {
                        foreach (var neighbor in neighbors[y % neighbors.Length])
                        {
                            int radius = Math.Max(Math.Abs(neighbor.Offset.X), Math.Abs(neighbor.Offset.Y));
                            if (y - radius >= 0 && y + radius < input.Height)
                            {
                                var xRange = new IntRange(Math.Max(radius, validXRange.Start), Math.Min(input.Width - radius, validXRange.End));
                                for (int x = xRange.Start; x < xRange.End; ++x)
                                {
                                    double before   = input[x - neighbor.Offset.X, y - neighbor.Offset.Y];
                                    double at       = input[x, y];
                                    double after    = input[x + neighbor.Offset.X, y + neighbor.Offset.Y];
                                    double strength = at - Math.Max(before, after);
                                    if (strength > 0)
                                    {
                                        orientation.Add(x, y, strength * neighbor.Orientation);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/pixelwise-orientation
            FingerprintTransparency.Current.Log("pixelwise-orientation", orientation);
            return(orientation);
        }
示例#23
0
        static void TraceRidges(BooleanMatrix thinned, Dictionary <IntPoint, SkeletonMinutia> minutiaePoints)
        {
            var leads = new Dictionary <IntPoint, SkeletonRidge>();

            foreach (var minutiaPoint in minutiaePoints.Keys)
            {
                foreach (var startRelative in IntPoint.CornerNeighbors)
                {
                    var start = minutiaPoint + startRelative;
                    if (thinned.Get(start, false) && !minutiaePoints.ContainsKey(start) && !leads.ContainsKey(start))
                    {
                        var ridge = new SkeletonRidge();
                        ridge.Points.Add(minutiaPoint);
                        ridge.Points.Add(start);
                        var previous = minutiaPoint;
                        var current  = start;
                        do
                        {
                            var next = IntPoint.Zero;
                            foreach (var nextRelative in IntPoint.CornerNeighbors)
                            {
                                next = current + nextRelative;
                                if (thinned.Get(next, false) && next != previous)
                                {
                                    break;
                                }
                            }
                            previous = current;
                            current  = next;
                            ridge.Points.Add(current);
                        } while (!minutiaePoints.ContainsKey(current));
                        var end = current;
                        ridge.Start                     = minutiaePoints[minutiaPoint];
                        ridge.End                       = minutiaePoints[end];
                        leads[ridge.Points[1]]          = ridge;
                        leads[ridge.Reversed.Points[1]] = ridge;
                    }
                }
            }
        }
示例#24
0
        List <IntPoint> FindMinutiae(BooleanMatrix thinned)
        {
            var result = new List <IntPoint>();

            foreach (var at in Size.Iterate())
            {
                if (thinned[at])
                {
                    int count = 0;
                    foreach (var relative in IntPoint.CornerNeighbors)
                    {
                        if (thinned.Get(at + relative, false))
                        {
                            ++count;
                        }
                    }
                    if (count == 1 || count > 2)
                    {
                        result.Add(at);
                    }
                }
            }
            return(result);
        }
示例#25
0
        static void RemoveCrosses(BooleanMatrix input)
        {
            var  size = input.Size;
            bool any  = true;

            while (any)
            {
                any = false;
                for (int y = 0; y < size.Y - 1; ++y)
                {
                    for (int x = 0; x < size.X - 1; ++x)
                    {
                        if (input[x, y] && input[x + 1, y + 1] && !input[x, y + 1] && !input[x + 1, y] || input[x, y + 1] && input[x + 1, y] && !input[x, y] && !input[x + 1, y + 1])
                        {
                            input[x, y]         = false;
                            input[x, y + 1]     = false;
                            input[x + 1, y]     = false;
                            input[x + 1, y + 1] = false;
                            any = true;
                        }
                    }
                }
            }
        }
示例#26
0
        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);
        }
示例#27
0
 static BooleanMatrix FilterBlockErrors(BooleanMatrix input)
 {
     return(Vote(input, null, Parameters.BlockErrorsVoteRadius, Parameters.BlockErrorsVoteMajority, Parameters.BlockErrorsVoteBorderDistance));
 }
示例#28
0
        static DoubleMatrix Equalize(BlockMap blocks, DoubleMatrix image, HistogramCube histogram, BooleanMatrix blockMask)
        {
            const double rangeMin    = -1;
            const double rangeMax    = 1;
            const double rangeSize   = rangeMax - rangeMin;
            double       widthMax    = rangeSize / histogram.Bins * Parameters.MaxEqualizationScaling;
            double       widthMin    = rangeSize / histogram.Bins * Parameters.MinEqualizationScaling;
            var          limitedMin  = new double[histogram.Bins];
            var          limitedMax  = new double[histogram.Bins];
            var          dequantized = new double[histogram.Bins];

            for (int i = 0; i < histogram.Bins; ++i)
            {
                limitedMin[i]  = Math.Max(i * widthMin + rangeMin, rangeMax - (histogram.Bins - 1 - i) * widthMax);
                limitedMax[i]  = Math.Min(i * widthMax + rangeMin, rangeMax - (histogram.Bins - 1 - i) * widthMin);
                dequantized[i] = i / (double)(histogram.Bins - 1);
            }
            var mappings = new Dictionary <IntPoint, double[]>();

            foreach (var corner in blocks.Secondary.Blocks.Iterate())
            {
                double[] mapping = new double[histogram.Bins];
                mappings[corner] = mapping;
                if (blockMask.Get(corner, false) ||
                    blockMask.Get(corner.X - 1, corner.Y, false) ||
                    blockMask.Get(corner.X, corner.Y - 1, false) ||
                    blockMask.Get(corner.X - 1, corner.Y - 1, false))
                {
                    double step = rangeSize / histogram.Sum(corner);
                    double top  = rangeMin;
                    for (int i = 0; i < histogram.Bins; ++i)
                    {
                        double band      = histogram[corner, i] * step;
                        double equalized = top + dequantized[i] * band;
                        top += band;
                        if (equalized < limitedMin[i])
                        {
                            equalized = limitedMin[i];
                        }
                        if (equalized > limitedMax[i])
                        {
                            equalized = limitedMax[i];
                        }
                        mapping[i] = equalized;
                    }
                }
            }
            var result = new DoubleMatrix(blocks.Pixels);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                var area = blocks.Primary.Block(block);
                if (blockMask[block])
                {
                    var topleft     = mappings[block];
                    var topright    = mappings[new IntPoint(block.X + 1, block.Y)];
                    var bottomleft  = mappings[new IntPoint(block.X, block.Y + 1)];
                    var bottomright = mappings[new IntPoint(block.X + 1, block.Y + 1)];
                    for (int y = area.Top; y < area.Bottom; ++y)
                    {
                        for (int x = area.Left; x < area.Right; ++x)
                        {
                            int    depth = histogram.Constrain((int)(image[x, y] * histogram.Bins));
                            double rx    = (x - area.X + 0.5) / area.Width;
                            double ry    = (y - area.Y + 0.5) / area.Height;
                            result[x, y] = Doubles.Interpolate(bottomleft[depth], bottomright[depth], topleft[depth], topright[depth], rx, ry);
                        }
                    }
                }
                else
                {
                    for (int y = area.Top; y < area.Bottom; ++y)
                    {
                        for (int x = area.Left; x < area.Right; ++x)
                        {
                            result[x, y] = -1;
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/equalized-image
            FingerprintTransparency.Current.Log("equalized-image", result);
            return(result);
        }
示例#29
0
        static DoublePointMatrix BlockOrientations(DoublePointMatrix orientation, BlockMap blocks, BooleanMatrix mask)
        {
            var sums = new DoublePointMatrix(blocks.Primary.Blocks);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                if (mask[block])
                {
                    var area = blocks.Primary.Block(block);
                    for (int y = area.Top; y < area.Bottom; ++y)
                    {
                        for (int x = area.Left; x < area.Right; ++x)
                        {
                            sums.Add(block, orientation[x, y]);
                        }
                    }
                }
            }
            // https://sourceafis.machinezoo.com/transparency/block-orientation
            FingerprintTransparency.Current.Log("block-orientation", sums);
            return(sums);
        }
示例#30
0
        static DoubleMatrix SmoothRidges(DoubleMatrix input, DoubleMatrix orientation, BooleanMatrix mask, BlockMap blocks, double angle, IntPoint[][] lines)
        {
            var output = new DoubleMatrix(input.Size);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                if (mask[block])
                {
                    var line = lines[DoubleAngle.Quantize(DoubleAngle.Add(orientation[block], angle), lines.Length)];
                    foreach (var linePoint in line)
                    {
                        var target = blocks.Primary.Block(block);
                        var source = target.Move(linePoint).Intersect(new IntRect(blocks.Pixels));
                        target = source.Move(-linePoint);
                        for (int y = target.Top; y < target.Bottom; ++y)
                        {
                            for (int x = target.Left; x < target.Right; ++x)
                            {
                                output.Add(x, y, input[x + linePoint.X, y + linePoint.Y]);
                            }
                        }
                    }
                    var blockArea = blocks.Primary.Block(block);
                    for (int y = blockArea.Top; y < blockArea.Bottom; ++y)
                    {
                        for (int x = blockArea.Left; x < blockArea.Right; ++x)
                        {
                            output.Multiply(x, y, 1.0 / line.Length);
                        }
                    }
                }
            }
            return(output);
        }