public static List <Minutia> ExtractMinutiae(double[,] imgBytes)
        {
            var lsEnhanced = SymmetryHelper.EstimateLS(imgBytes, sigma1, sigma2);
            var psEnhanced = SymmetryHelper.EstimatePS(imgBytes, sigma1, sigma2);
            //ImageHelper.SaveComplexArrayAsHSV(lsEnhanced,"C:\\temp\\lsenh.png");

            //ImageHelper.SaveArray(NormalizeArray(psEnhanced.Select2D(x=>x.Magnitude)), "C:\\temp\\psenh.png");

            var psi = KernelHelper.Zip2D(psEnhanced,
                                         lsEnhanced.Select2D(x => x.Magnitude), (x, y) =>
                                         x * (1.0d - y));

            return(SearchMinutiae(psi, lsEnhanced, psEnhanced));
        }
        public static double[,] EnhanceImage(double[,] imgBytes)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();
            var g1 = ImageSizeHelper.Reduce2(imgBytes, 1.7d);
            var g2 = ImageSizeHelper.Reduce2(g1, 1.21d);
            var g3 = ImageSizeHelper.Reduce2(g2, K);
            var g4 = ImageSizeHelper.Reduce2(g3, K);

            var p3 = ImageSizeHelper.Expand2(g4, K, new Size(g3.GetLength(0), g3.GetLength(1)));
            var p2 = ImageSizeHelper.Expand2(g3, K, new Size(g2.GetLength(0), g2.GetLength(1)));
            var p1 = ImageSizeHelper.Expand2(g2, 1.21d, new Size(g1.GetLength(0), g1.GetLength(1)));

            var l3 = ContrastEnhancement(KernelHelper.Subtract(g3, p3));
            var l2 = ContrastEnhancement(KernelHelper.Subtract(g2, p2));
            var l1 = ContrastEnhancement(KernelHelper.Subtract(g1, p1));
            //SaveArray(l3, "C:\\temp\\l3.png");
            //SaveArray(l1, "C:\\temp\\l1.png");
            //SaveArray(l2, "C:\\temp\\l2.png");

            var ls1 = SymmetryHelper.EstimateLS(l1, sigma1, sigma2);
            var ls2 = SymmetryHelper.EstimateLS(l2, sigma1, sigma2);
            var ls3 = SymmetryHelper.EstimateLS(l3, sigma1, sigma2);

            //SaveComplexArrayAsHSV(ls1, "C:\\temp\\ls1.png");
            //SaveComplexArrayAsHSV(ls2, "C:\\temp\\ls2.png");
            //SaveComplexArrayAsHSV(ls3, "C:\\temp\\ls3.png");

            var ls2Scaled =
                KernelHelper.MakeComplexFromDouble(
                    ImageSizeHelper.Expand2(ls2.Select2D(x => x.Real), K, new Size(l1.GetLength(0), l1.GetLength(1))),
                    ImageSizeHelper.Expand2(ls2.Select2D(x => x.Imaginary), K, new Size(l1.GetLength(0), l1.GetLength(1))));
            var multiplier = KernelHelper.Subtract(ls1.Select2D(x => x.Phase), ls2Scaled.Select2D(x => x.Phase));

            for (int x = 0; x < ls1.GetLength(0); x++)
            {
                for (int y = 0; y < ls1.GetLength(1); y++)
                {
                    ls1[x, y] *= Math.Abs(Math.Cos(multiplier[x, y]));
                }
            }

            DirectionFiltering(l1, ls1, tau1, tau2);
            DirectionFiltering(l2, ls2, tau1, tau2);
            DirectionFiltering(l3, ls3, tau1, tau2);

            var ll2 = ImageSizeHelper.Expand2(l3, K, new Size(l2.GetLength(0), l2.GetLength(1)));

            l2 = KernelHelper.Add(ll2, l2);
            var ll1 = ImageSizeHelper.Expand2(l2, 1.21d, new Size(l1.GetLength(0), l1.GetLength(1)));

            l1 = KernelHelper.Add(ll1, l1);
            var ll0 = ImageSizeHelper.Expand2(l1, 1.7d, new Size(imgBytes.GetLength(0), imgBytes.GetLength(1)));

            ll0 = ContrastEnhancement(ll0);
            sw.Stop();
            var enhanced = RearrangeArray(ll0, 0, 255);

            return(enhanced);
        }