Пример #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[,] 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);
        }
Пример #6
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);
        }
Пример #7
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);
        }
Пример #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
        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;
                        }
                    }
                }
            }
        }
Пример #12
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);
        }
Пример #13
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);
        }
Пример #14
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)));
        }