private void CollectMinutiae(FingerprintSkeleton skeleton, FingerprintMinutiaType type)
 {
     foreach (var skeletonMinutia in skeleton.Minutiae)
     {
         if (skeletonMinutia.IsConsidered && skeletonMinutia.Ridges.Count == 1)
         {
             var templateMinutia = new FingerprintMinutia
             {
                 Type      = type,
                 Position  = skeletonMinutia.Position,
                 Direction = skeletonMinutia.Ridges[0].ComputeDirection()
             };
             Minutiae.Add(templateMinutia);
         }
     }
 }
        public FingerprintTemplate(byte[,] image, int dpi = 500)
        {
            const int blockSize = 15;

            if (dpi != 500)
            {
                image = ScaleImage(image, dpi);
            }
            image = InvertInput(image);
            var blocks = new BlockMap(new Point(image.GetLength(1), image.GetLength(0)), blockSize);

            var histogram       = ComputeHistogram(blocks, image);
            var smoothHistogram = ComputeSmoothedHistogram(blocks, histogram);
            var mask            = ComputeMask(blocks, histogram);
            var equalized       = Equalize(blocks, image, smoothHistogram, mask);

            var orientation = ComputeOrientationMap(equalized, mask, blocks);
            var smoothed    = SmoothByOrientation(equalized, orientation, mask, blocks, 0,
                                                  ConstructOrientedLines(step: 1.59));
            var orthogonal = SmoothByOrientation(smoothed, orientation, mask, blocks, Angle.PIB,
                                                 ConstructOrientedLines(11, 4, 1.11));

            var binary = Binarize(smoothed, orthogonal, mask, blocks);

            CleanupBinarized(binary);

            var pixelMask = FillBlocks(mask, blocks);
            var innerMask = ComputeInnerMask(pixelMask);

            var inverted = Invert(binary, pixelMask);

            var ridges  = new FingerprintSkeleton(binary);
            var valleys = new FingerprintSkeleton(inverted);

            CollectMinutiae(ridges, FingerprintMinutiaType.Ending);
            CollectMinutiae(valleys, FingerprintMinutiaType.Bifurcation);
            ApplyMask(innerMask);
            RemoveMinutiaClouds();
            LimitTemplateSize();
            ShuffleMinutiae();

            BuildEdgeTable();
        }