Exemple #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);
        }
Exemple #2
0
        public                          IntPoint[] LineTo(IntPoint to)
        {
            IntPoint[] result;
            var        relative = to - this;

            if (Math.Abs(relative.X) >= Math.Abs(relative.Y))
            {
                result = new IntPoint[Math.Abs(relative.X) + 1];
                if (relative.X > 0)
                {
                    for (int i = 0; i <= relative.X; ++i)
                    {
                        result[i] = new IntPoint(X + i, Y + Doubles.RoundToInt(i * (relative.Y / (double)relative.X)));
                    }
                }
                else if (relative.X < 0)
                {
                    for (int i = 0; i <= -relative.X; ++i)
                    {
                        result[i] = new IntPoint(X - i, Y - Doubles.RoundToInt(i * (relative.Y / (double)relative.X)));
                    }
                }
                else
                {
                    result[0] = this;
                }
            }
            else
            {
                result = new IntPoint[Math.Abs(relative.Y) + 1];
                if (relative.Y > 0)
                {
                    for (int i = 0; i <= relative.Y; ++i)
                    {
                        result[i] = new IntPoint(X + Doubles.RoundToInt(i * (relative.X / (double)relative.Y)), Y + i);
                    }
                }
                else if (relative.Y < 0)
                {
                    for (int i = 0; i <= -relative.Y; ++i)
                    {
                        result[i] = new IntPoint(X - Doubles.RoundToInt(i * (relative.X / (double)relative.Y)), Y - i);
                    }
                }
                else
                {
                    result[0] = this;
                }
            }
            return(result);
        }
Exemple #3
0
 static EdgeShape()
 {
     for (int y = 0; y < PolarCacheRadius; ++y)
     {
         for (int x = 0; x < PolarCacheRadius; ++x)
         {
             PolarDistanceCache[y * PolarCacheRadius + x] = Doubles.RoundToInt(Math.Sqrt(Doubles.Sq(x) + Doubles.Sq(y)));
             if (y > 0 || x > 0)
             {
                 PolarAngleCache[y * PolarCacheRadius + x] = DoubleAngle.Atan(x, y);
             }
             else
             {
                 PolarAngleCache[y * PolarCacheRadius + x] = 0;
             }
         }
     }
 }
Exemple #4
0
        static ConsideredOrientation[][] PlanOrientations()
        {
            var random = new OrientationRandom();
            var splits = new ConsideredOrientation[Parameters.OrientationSplit][];

            for (int i = 0; i < Parameters.OrientationSplit; ++i)
            {
                var orientations = splits[i] = new ConsideredOrientation[Parameters.OrientationsChecked];
                for (int j = 0; j < Parameters.OrientationsChecked; ++j)
                {
                    var sample = orientations[j] = new ConsideredOrientation();
                    while (true)
                    {
                        double angle    = random.Next() * Math.PI;
                        double distance = Doubles.InterpolateExponential(Parameters.MinOrientationRadius, Parameters.MaxOrientationRadius, random.Next());
                        sample.Offset = (distance * DoubleAngle.ToVector(angle)).Round();
                        if (sample.Offset == IntPoint.Zero)
                        {
                            continue;
                        }
                        if (sample.Offset.Y < 0)
                        {
                            continue;
                        }
                        bool duplicate = false;
                        for (int jj = 0; jj < j; ++jj)
                        {
                            if (orientations[jj].Offset == sample.Offset)
                            {
                                duplicate = true;
                            }
                        }
                        if (duplicate)
                        {
                            continue;
                        }
                        break;
                    }
                    sample.Orientation = DoubleAngle.ToVector(DoubleAngle.Add(DoubleAngle.ToOrientation(DoubleAngle.Atan((DoublePoint)sample.Offset)), Math.PI));
                }
            }
            return(splits);
        }
Exemple #5
0
        static DoubleMatrix ClipContrast(BlockMap blocks, HistogramCube histogram)
        {
            var result = new DoubleMatrix(blocks.Primary.Blocks);

            foreach (var block in blocks.Primary.Blocks.Iterate())
            {
                int volume      = histogram.Sum(block);
                int clipLimit   = Doubles.RoundToInt(volume * Parameters.ClippedContrast);
                int accumulator = 0;
                int lowerBound  = histogram.Bins - 1;
                for (int i = 0; i < histogram.Bins; ++i)
                {
                    accumulator += histogram[block, i];
                    if (accumulator > clipLimit)
                    {
                        lowerBound = i;
                        break;
                    }
                }
                accumulator = 0;
                int upperBound = 0;
                for (int i = histogram.Bins - 1; i >= 0; --i)
                {
                    accumulator += histogram[block, i];
                    if (accumulator > clipLimit)
                    {
                        upperBound = i;
                        break;
                    }
                }
                result[block] = (upperBound - lowerBound) * (1.0 / (histogram.Bins - 1));
            }
            // https://sourceafis.machinezoo.com/transparency/contrast
            FingerprintTransparency.Current.Log("contrast", result);
            return(result);
        }
 public IntPoint Round()
 {
     return(new IntPoint(Doubles.RoundToInt(X), Doubles.RoundToInt(Y)));
 }
Exemple #7
0
        public void Compute(MatcherThread thread)
        {
            MinutiaCount               = thread.Count;
            MinutiaScore               = Parameters.MinutiaScore * MinutiaCount;
            MinutiaFractionInProbe     = thread.Count / (double)thread.Probe.Minutiae.Length;
            MinutiaFractionInCandidate = thread.Count / (double)thread.Candidate.Minutiae.Length;
            MinutiaFraction            = 0.5 * (MinutiaFractionInProbe + MinutiaFractionInCandidate);
            MinutiaFractionScore       = Parameters.MinutiaFractionScore * MinutiaFraction;
            SupportingEdgeSum          = 0;
            SupportedMinutiaCount      = 0;
            MinutiaTypeHits            = 0;
            for (int i = 0; i < thread.Count; ++i)
            {
                var pair = thread.Tree[i];
                SupportingEdgeSum += pair.SupportingEdges;
                if (pair.SupportingEdges >= Parameters.MinSupportingEdges)
                {
                    ++SupportedMinutiaCount;
                }
                if (thread.Probe.Minutiae[pair.Probe].Type == thread.Candidate.Minutiae[pair.Candidate].Type)
                {
                    ++MinutiaTypeHits;
                }
            }
            EdgeCount             = thread.Count + SupportingEdgeSum;
            EdgeScore             = Parameters.EdgeScore * EdgeCount;
            SupportedMinutiaScore = Parameters.SupportedMinutiaScore * SupportedMinutiaCount;
            MinutiaTypeScore      = Parameters.MinutiaTypeScore * MinutiaTypeHits;
            int    innerDistanceRadius = Doubles.RoundToInt(Parameters.DistanceErrorFlatness * Parameters.MaxDistanceError);
            double innerAngleRadius    = Parameters.AngleErrorFlatness * Parameters.MaxAngleError;

            DistanceErrorSum = 0;
            AngleErrorSum    = 0;
            for (int i = 1; i < thread.Count; ++i)
            {
                var pair          = thread.Tree[i];
                var probeEdge     = new EdgeShape(thread.Probe.Minutiae[pair.ProbeRef], thread.Probe.Minutiae[pair.Probe]);
                var candidateEdge = new EdgeShape(thread.Candidate.Minutiae[pair.CandidateRef], thread.Candidate.Minutiae[pair.Candidate]);
                DistanceErrorSum += Math.Max(innerDistanceRadius, Math.Abs(probeEdge.Length - candidateEdge.Length));
                AngleErrorSum    += Math.Max(innerAngleRadius, DoubleAngle.Distance(probeEdge.ReferenceAngle, candidateEdge.ReferenceAngle));
                AngleErrorSum    += Math.Max(innerAngleRadius, DoubleAngle.Distance(probeEdge.NeighborAngle, candidateEdge.NeighborAngle));
            }
            DistanceAccuracyScore = 0;
            AngleAccuracyScore    = 0;
            int distanceErrorPotential = Parameters.MaxDistanceError * Math.Max(0, thread.Count - 1);

            DistanceAccuracySum   = distanceErrorPotential - DistanceErrorSum;
            DistanceAccuracyScore = Parameters.DistanceAccuracyScore * (distanceErrorPotential > 0 ? DistanceAccuracySum / (double)distanceErrorPotential : 0);
            double angleErrorPotential = Parameters.MaxAngleError * Math.Max(0, thread.Count - 1) * 2;

            AngleAccuracySum   = angleErrorPotential - AngleErrorSum;
            AngleAccuracyScore = Parameters.AngleAccuracyScore * (angleErrorPotential > 0 ? AngleAccuracySum / angleErrorPotential : 0);
            TotalScore         = MinutiaScore
                                 + MinutiaFractionScore
                                 + SupportedMinutiaScore
                                 + EdgeScore
                                 + MinutiaTypeScore
                                 + DistanceAccuracyScore
                                 + AngleAccuracyScore;
            ShapedScore = Shape(TotalScore);
        }
Exemple #8
0
 static DoubleMatrix ScaleImage(DoubleMatrix input, double dpi)
 {
     return(ScaleImage(input, Doubles.RoundToInt(500.0 / dpi * input.Width), Doubles.RoundToInt(500.0 / dpi * input.Height)));
 }
Exemple #9
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);
        }