Пример #1
0
        static PointF[,] SmoothOutOrientationMap(PointF[,] orientation, bool[,] mask)
        {
            const int radius = 1;
            var       size   = Point.SizeOf(mask);

            PointF[,] smoothed = size.Allocate <PointF>();
            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    if (mask[y, x])
                    {
                        Rectangle neighbors = Rectangle.Between(
                            new Point(Math.Max(0, x - radius), Math.Max(0, y - radius)),
                            new Point(Math.Min(size.X, x + radius + 1), Math.Min(size.Y, y + radius + 1)));
                        PointF sum = new PointF();
                        for (int ny = neighbors.Bottom; ny < neighbors.Top; ++ny)
                        {
                            for (int nx = neighbors.Left; nx < neighbors.Right; ++nx)
                            {
                                if (mask[ny, nx])
                                {
                                    sum += orientation[ny, nx];
                                }
                            }
                        }
                        smoothed[y, x] = sum;
                    }
                }
            }
            return(smoothed);
        }
Пример #2
0
        static bool[,] ComputeInnerMask(bool[,] outer)
        {
            const int minBorderDistance = 14;
            var       size  = Point.SizeOf(outer);
            var       inner = size.Allocate <bool>();

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

            for (int step = 1; total + step <= minBorderDistance; step *= 2)
            {
                inner  = ShrinkMask(inner, step);
                total += step;
            }
            if (total < minBorderDistance)
            {
                inner = ShrinkMask(inner, minBorderDistance - total);
            }
            return(inner);
        }
Пример #3
0
        static bool[,] Binarize(double[,] input, double[,] baseline, bool[,] mask, BlockMap blocks)
        {
            var size      = Point.SizeOf(input);
            var binarized = size.Allocate <bool>();

            for (int blockY = 0; blockY < blocks.AllBlocks.Height; ++blockY)
            {
                for (int blockX = 0; blockX < blocks.AllBlocks.Width; ++blockX)
                {
                    if (mask[blockY, blockX])
                    {
                        Rectangle rect = blocks.BlockAreas[blockY, blockX];
                        for (int y = rect.Bottom; y < rect.Top; ++y)
                        {
                            for (int x = rect.Left; x < rect.Right; ++x)
                            {
                                if (input[y, x] - baseline[y, x] > 0)
                                {
                                    binarized[y, x] = true;
                                }
                            }
                        }
                    }
                }
            }
            return(binarized);
        }
Пример #4
0
        static void MergeMask(bool[,] mask, bool[,] merged)
        {
            var size = Point.SizeOf(mask);

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    mask[y, x] |= merged[y, x];
                }
            }
        }
Пример #5
0
        static bool[,] Invert(bool[,] binary, bool[,] mask)
        {
            var size     = Point.SizeOf(binary);
            var inverted = size.Allocate <bool>();

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    inverted[y, x] = !binary[y, x] && mask[y, x];
                }
            }
            return(inverted);
        }
Пример #6
0
        static bool[,] InvertMask(bool[,] mask)
        {
            var size     = Point.SizeOf(mask);
            var inverted = size.Allocate <bool>();

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    inverted[y, x] = !mask[y, x];
                }
            }
            return(inverted);
        }
Пример #7
0
        static bool[,] ShrinkMask(bool[,] mask, int amount)
        {
            var size   = Point.SizeOf(mask);
            var shrunk = size.Allocate <bool>();

            for (int y = amount; y < size.Y - amount; ++y)
            {
                for (int x = amount; x < size.X - amount; ++x)
                {
                    shrunk[y, x] = mask[y - amount, x] && mask[y + amount, x] && mask[y, x - amount] && mask[y, x + amount];
                }
            }
            return(shrunk);
        }
Пример #8
0
        static void CleanupBinarized(bool[,] binary)
        {
            var size    = Point.SizeOf(binary);
            var islands = FilterBinarized(InvertMask(binary));
            var holes   = FilterBinarized(binary);

            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    binary[y, x] = binary[y, x] && !islands[y, x] || holes[y, x];
                }
            }
            RemoveCrosses(binary);
        }
Пример #9
0
        static byte[,] ConvertOrientationVectorsToAngles(PointF[,] vectors, bool[,] mask)
        {
            var size = Point.SizeOf(mask);

            byte[,] angles = size.Allocate <byte>();
            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    if (mask[y, x])
                    {
                        angles[y, x] = Angle.ToByte(Angle.Atan(vectors[y, x]));
                    }
                }
            }
            return(angles);
        }
Пример #10
0
        static bool[,] ComputeAbsoluteContrast(byte[,] contrast)
        {
            const int limit = 17;
            var       size  = Point.SizeOf(contrast);

            bool[,] result = size.Allocate <bool>();
            for (int y = 0; y < size.Y; ++y)
            {
                for (int x = 0; x < size.X; ++x)
                {
                    if (contrast[y, x] < limit)
                    {
                        result[y, x] = true;
                    }
                }
            }
            return(result);
        }
Пример #11
0
        void BuildEdgeTable()
        {
            const int maxDistance  = 490;
            const int maxNeighbors = 9;

            EdgeTable = new NeighborEdge[Minutiae.Count][];
            var edges          = new List <NeighborEdge>();
            var allSqDistances = new int[Minutiae.Count];

            for (int reference = 0; reference < EdgeTable.Length; ++reference)
            {
                Point referencePosition = Minutiae[reference].Position;
                int   sqMaxDistance     = MathEx.Sq(maxDistance);
                if (Minutiae.Count - 1 > maxNeighbors)
                {
                    for (int neighbor = 0; neighbor < Minutiae.Count; ++neighbor)
                    {
                        allSqDistances[neighbor] = (referencePosition - Minutiae[neighbor].Position).SqLength;
                    }
                    Array.Sort(allSqDistances);
                    sqMaxDistance = allSqDistances[maxNeighbors];
                }
                for (int neighbor = 0; neighbor < Minutiae.Count; ++neighbor)
                {
                    if (neighbor != reference && (referencePosition - Minutiae[neighbor].Position).SqLength <= sqMaxDistance)
                    {
                        NeighborEdge record = new NeighborEdge();
                        record.Edge     = new EdgeShape(this, reference, neighbor);
                        record.Neighbor = neighbor;
                        edges.Add(record);
                    }
                }

                edges.Sort(NeighborEdgeComparer.Instance);
                if (edges.Count > maxNeighbors)
                {
                    edges.RemoveRange(maxNeighbors, edges.Count - maxNeighbors);
                }
                EdgeTable[reference] = edges.ToArray();
                edges.Clear();
            }
        }
Пример #12
0
        static int[, ,] ComputeSmoothedHistogram(BlockMap blocks, int[, ,] input)
        {
            var blocksAround = new Point[] { new Point(0, 0), new Point(-1, 0), new Point(0, -1), new Point(-1, -1) };
            var output       = new int[blocks.CornerCount.Y, blocks.CornerCount.X, 256];

            foreach (var corner in blocks.AllCorners)
            {
                foreach (Point relative in blocksAround)
                {
                    var block = corner + relative;
                    if (blocks.AllBlocks.Contains(block))
                    {
                        for (int i = 0; i < 256; ++i)
                        {
                            output[corner.Y, corner.X, i] += input[block.Y, block.X, i];
                        }
                    }
                }
            }
            return(output);
        }
Пример #13
0
 Point[][] ConstructOrientedLines(int resolution = 32, int radius = 7, double step = 1.5)
 {
     Point[][] result = new Point[resolution][];
     for (int orientationIndex = 0; orientationIndex < resolution; ++orientationIndex)
     {
         List <Point> line = new List <Point>();
         line.Add(new Point());
         PointF direction = Angle.ToVector(Angle.ByBucketCenter(orientationIndex, 2 * resolution));
         for (double r = radius; r >= 0.5; r /= step)
         {
             Point point = (r * direction).Round();
             if (!line.Contains(point))
             {
                 line.Add(point);
                 line.Add(-point);
             }
         }
         line.Sort(MathEx.CompareYX);
         result[orientationIndex] = line.ToArray();
     }
     return(result);
 }
Пример #14
0
        static void RemoveCrosses(bool[,] input)
        {
            var  size = Point.SizeOf(input);
            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[y, x] && input[y + 1, x + 1] && !input[y + 1, x] && !input[y, x + 1] || input[y + 1, x] && input[y, x + 1] && !input[y, x] && !input[y + 1, x + 1])
                        {
                            input[y, x]         = false;
                            input[y + 1, x]     = false;
                            input[y, x + 1]     = false;
                            input[y + 1, x + 1] = false;
                            any = true;
                        }
                    }
                }
            }
        }
Пример #15
0
        static byte[,] ScaleImage(byte[,] input, int newX, int newY)
        {
            var    oldSize  = Point.SizeOf(input);
            var    output   = new byte[newY, newX];
            double scaleX   = newX / (double)oldSize.X;
            double scaleY   = newY / (double)oldSize.Y;
            double descaleX = 1 / scaleX;
            double descaleY = 1 / scaleY;

            for (int y = 0; y < newY; ++y)
            {
                double y1  = y * descaleY;
                double y2  = y1 + descaleY;
                int    y1i = (int)y1;
                int    y2i = (int)Math.Ceiling(y2);
                for (int x = 0; x < newX; ++x)
                {
                    double x1  = x * descaleX;
                    double x2  = x1 + descaleX;
                    int    x1i = (int)x1;
                    int    x2i = (int)Math.Ceiling(x2);
                    double sum = 0;
                    for (int oy = y1i; oy < y2i; ++oy)
                    {
                        var ry = Math.Min(oy + 1, y2) - Math.Max(oy, y1);
                        for (int ox = x1i; ox < x2i; ++ox)
                        {
                            var rx = Math.Min(ox + 1, x2) - Math.Max(ox, x1);
                            sum += rx * ry * input[oy, ox];
                        }
                    }
                    output[y, x] = Convert.ToByte(sum * (scaleX * scaleY));
                }
            }
            return(output);
        }
Пример #16
0
        static bool[,] ApplyVotingFilter(bool[,] input, int radius = 1, double majority = 0.51, int borderDist = 0)
        {
            var       size = Point.SizeOf(input);
            Rectangle rect = new Rectangle(new Point(borderDist, borderDist),
                                           new Point(size.X - 2 * borderDist, size.Y - 2 * borderDist));
            var output = size.Allocate <bool>();

            for (int y = rect.RangeY.Begin; y < rect.RangeY.End; ++y)
            {
                for (int x = rect.Left; x < rect.Right; ++x)
                {
                    Rectangle neighborhood = Rectangle.Between(
                        new Point(Math.Max(x - radius, 0), Math.Max(y - radius, 0)),
                        new Point(Math.Min(x + radius + 1, size.X), Math.Min(y + radius + 1, size.Y)));

                    int ones = 0;
                    for (int ny = neighborhood.Bottom; ny < neighborhood.Top; ++ny)
                    {
                        for (int nx = neighborhood.Left; nx < neighborhood.Right; ++nx)
                        {
                            if (input[ny, nx])
                            {
                                ++ones;
                            }
                        }
                    }

                    double voteWeight = 1.0 / neighborhood.TotalArea;
                    if (ones * voteWeight >= majority)
                    {
                        output[y, x] = true;
                    }
                }
            }
            return(output);
        }
Пример #17
0
        static byte[,] ScaleImage(byte[,] input, int dpi)
        {
            var size = Point.SizeOf(input);

            return(ScaleImage(input, Convert.ToInt32(500.0 / dpi * size.X), Convert.ToInt32(500.0 / dpi * size.Y)));
        }