Example #1
0
        /// <inheritdoc />
        /// <exception cref="ArgumentNullException">
        /// <paramref name="source"/> is <b>null</b>.
        /// </exception>
        public PointsOfInterestFeatures BuildFeatures(ImageSource source, CancellationToken cancellationToken)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            Image image = ImagePreprocessing.Process(source.Image, this.ImagePreprocessingOptions, 8);

            image = image
                    ////.Scale(null, 100.0 / image.HorizontalResolution, 100.0 / image.VerticalResolution, ScalingOptions.None)
                    ////.Binarize()
                    .Convert8To1(null, 128)
                    .CleanOverscan(0.5f, 0.5f)
                    .Deskew(null)
                    .Despeckle(null);

            ISet <ConnectedComponent> components = image.FindConnectedComponents(8);

            image.RemoveConnectedComponents(components.Where(x => x.Power <= 16));

            image = image
                    .CropBlackArea(0, 0)
                    ////.Dilate(null, StructuringElement.Square(3), 1, BorderType.BorderConst, image.WhiteColor)
                    ////.CropBlackArea(0, 0)
                    .Convert1To8(null)
                    .Erode(null, StructuringElement.Square(2), 1, BorderType.BorderRepl, 0)
                    .ScaleByDownsampling2(null)
                    .FilterLowpass(null, 3, BorderType.BorderRepl, 0);

            FeatureDetectors.Features features = this.detector.Detect(image, cancellationToken);

            return(new PointsOfInterestFeatures(source.Id, features));
        }
Example #2
0
        public void ErodeTest1()
        {
            const int Width  = 150;
            const int Height = 20;

            for (int ix = 0; ix < Width; ix++)
            {
                for (int iy = 0; iy < Height; iy++)
                {
                    Image image = new Image(Width, Height, 1, 200, 200);
                    image.SetBlack();
                    image.SetPixel(ix, iy, 0);

                    Image dilatedImage = image.Erode(null, StructuringElement.Square(3), 1, BorderType.BorderConst, uint.MaxValue);

                    if ((ix == 0 || ix == Width - 1) && (iy == 0 || iy == Height - 1))
                    {
                        Assert.AreEqual(
                            (ulong)((Width * Height) - 4),
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                    else if ((ix == 0 || ix == Width - 1) || (iy == 0 || iy == Height - 1))
                    {
                        Assert.AreEqual(
                            (ulong)((Width * Height) - 6),
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                    else
                    {
                        Assert.AreEqual(
                            (ulong)((Width * Height) - 9),
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                }
            }
        }
Example #3
0
        public void DilateTest_3x3()
        {
            const int Width  = 150;
            const int Height = 20;

            for (int ix = 0; ix < Width; ix++)
            {
                for (int iy = 0; iy < Height; iy++)
                {
                    Image image = new Image(Width, Height, 1, 200, 200);
                    image.SetPixel(ix, iy, 1);

                    Image dilatedImage = image.Dilate(null, StructuringElement.Square(3), 1, BorderType.BorderConst, image.WhiteColor);

                    if ((ix == 0 || ix == Width - 1) && (iy == 0 || iy == Height - 1))
                    {
                        Assert.AreEqual(
                            4ul,
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                    else if ((ix == 0 || ix == Width - 1) || (iy == 0 || iy == Height - 1))
                    {
                        Assert.AreEqual(
                            6ul,
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                    else
                    {
                        Assert.AreEqual(
                            9ul,
                            dilatedImage.Power(),
                            string.Format(CultureInfo.InvariantCulture, "{0} {1}", ix, iy));
                    }
                }
            }
        }
Example #4
0
        public void DilateTest2()
        {
            StructuringElement[] ses = new[]
            {
                StructuringElement.Brick(3, 1),
                StructuringElement.Brick(1, 3),
                StructuringElement.Brick(1, 4),
                StructuringElement.Brick(1, 4, new Point(0, 1)),
                StructuringElement.Square(7),
                StructuringElement.Brick(8, 6),
                StructuringElement.Brick(8, 6, new Point(6, 5)),
                StructuringElement.Brick(8, 6, new Point(10, 8)),
                StructuringElement.Cross(10, 5),
                StructuringElement.Cross(10, 5, new Point(-3, -2)),
            };

            foreach (int bitsPerPixel in new[] { 1, /*2, 4,*/ 8, 16, 24, 32 })
            {
                foreach (int width in new[] { 64 * 2, 131 })
                {
                    Image src = new Image(width, 50, bitsPerPixel, 200, 200);

                    foreach (StructuringElement se in ses)
                    {
                        // constant border
                        foreach (uint borderValue in new[] { src.BlackColor, src.WhiteColor, (uint)(((ulong)src.BlackColor + (ulong)src.WhiteColor) / 2) })
                        {
                            src.Randomize();
                            Image dst = src.Dilate(null, se, 1, BorderType.BorderConst, borderValue);

                            for (int x = 0; x < src.Width; x++)
                            {
                                for (int y = 0; y < src.Height; y++)
                                {
                                    Assert.AreEqual(ComputePixelBorder(x, y, borderValue), dst.GetPixel(x, y));
                                }
                            }
                        }

                        // replica border
                        {
                            src.Randomize();
                            Image dst = src.Dilate(null, se, 1, BorderType.BorderRepl, 0);

                            for (int x = 0; x < src.Width; x++)
                            {
                                for (int y = 0; y < src.Height; y++)
                                {
                                    Assert.AreEqual(ComputePixel(x, y), dst.GetPixel(x, y));
                                }
                            }
                        }

                        uint ComputePixel(int x, int y)
                        {
                            uint maxcolor = uint.MinValue;

                            foreach (Point point in se.GetElements())
                            {
                                Point pt = new Point(x + point.X, y + point.Y);
                                if (src.Bounds.Contains(pt))
                                {
                                    maxcolor = Color.Max(maxcolor, src.GetPixel(pt), bitsPerPixel);
                                }
                            }

                            return(maxcolor);
                        }

                        uint ComputePixelBorder(int x, int y, uint borderValue)
                        {
                            uint maxcolor = uint.MinValue;

                            foreach (Point point in se.GetElements())
                            {
                                Point pt    = new Point(x + point.X, y + point.Y);
                                uint  color = src.Bounds.Contains(pt) ? src.GetPixel(pt) : borderValue;
                                maxcolor = Color.Max(maxcolor, color, bitsPerPixel);
                            }

                            return(maxcolor);
                        }
                    }
                }
            }
        }
Example #5
0
        public void XXXTest()
        {
#if false
            const int Count     = 10000000;
            Stopwatch stopwatch = new Stopwatch();

            RandomGenerator random = new RandomGenerator();

            int     length = 128;
            float[] dense1 = random.Generate(length);
            float[] dense2 = new float[length];
            for (int i = 0; i < 16; i++)
            {
                dense2[(int)random.Generate(0, length)] = random.Generate();
            }

            SparseVectorF sparse = SparseVectorF.FromDense(length, dense2, 0);

            stopwatch.Restart();

            for (int i = 0; i < Count; i++)
            {
                Math32f.EuclideanDistance(length, dense1, 0, dense2, 0);
            }

            stopwatch.Stop();

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds /* / Count*/);

            stopwatch.Restart();

            for (int i = 0; i < Count; i++)
            {
                sparse.EuclideanDistance(dense1, 0);
            }

            stopwatch.Stop();

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds /* / Count*/);
#else
            const int Count     = 5;
            Stopwatch stopwatch = new Stopwatch();

            ////Image image = new Image(2000, 3000, 8, 200, 200);
            ////image.Randomize();

            ////foreach ((Image image, _, _) in Image.FromFile(@"C:\DNN\dnn\test.jpg"))
            ////foreach ((Image image, _, _) in Image.FromFile(@"C:\DNN\dnn\363978.tif"))
            foreach ((Image image, _, _) in Imaging.Image.FromFile(@"L:\FormXtra\Receipts\Concur\Full\jpg\Work\08240EB488FE324E83C7C54042D9813C.jpg"))
            {
                stopwatch.Restart();

                Image xxx = image.ConvertTo(null, 8);

                for (int i = 0; i < Count; i++)
                {
                    xxx.Erode(xxx, StructuringElement.Square(2), 1, BorderType.BorderRepl, 0);
                    xxx.ScaleByDownsampling2(xxx);
                    ////image.Binarize(null, 0, 0, 0, 0, true, 0, 0);
                    ////IntegralImage.FromImage(image);

                    ////long power = image.Power();
                    ////Histogram hyst = image.GrayHistogram();

                    /*Image workImage = image
                     *  .ConvertTo(null, 8)
                     *  .Scale(null, 100.0 / image.HorizontalResolution, 100.0 / image.VerticalResolution, ScalingOptions.None)
                     *  ////.Binarize(null)
                     *  .Convert8To1(null, 128)
                     *  .CleanOverscan(0.5f, 0.5f)
                     *  .Deskew(null)
                     *  .Despeckle(null);
                     *
                     * ISet<ConnectedComponent> components = workImage.FindConnectedComponents(8);
                     * workImage.RemoveConnectedComponents(components);*/

                    /*workImage = workImage.Scale(100.0 / image.HorizontalResolution, 100.0 / image.VerticalResolution, Imaging.ScalingOptions.None);
                     * workImage = workImage.Binarize();
                     * ////workImage = workImage.Convert8To1(128);
                     * workImage = workImage.Dilate(StructuringElement.Rectangle(5, 1), 1);
                     * workImage = workImage.Dilate(StructuringElement.Rectangle(1, 5), 1);
                     * workImage = workImage.Convert1To8();
                     *
                     * DenseVectorPackF vectors = workImage.HOG(8, 2, 1, 9, 0.2f);
                     *
                     * vectors = DenseVectorPackF.Pack(vectors.Unpack().Where(x => x.Sum() != 0.0f).ToList());*/
                    ////Image temp = image.Binarize();
                }

                stopwatch.Stop();
            }

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds / Count);
#endif
        }
Example #6
0
        /// <summary>
        /// Finds the horizontal and vertical lines on the <see cref="Image"/>.
        /// The type of lines to find is determined by the class parameters.
        /// </summary>
        /// <param name="image">The source <see cref="Image"/>.</param>
        /// <param name="cancellationToken">The cancellationToken token used to notify the <see cref="LineDetector"/> that operation should be canceled.</param>
        /// <returns>
        /// The detected lines.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="image"/> is <b>null</b>.
        /// </exception>
        /// <exception cref="NotImplementedException">
        /// <see cref="Image{T}.BitsPerPixel"/> is not one.
        /// </exception>
        /// <remarks>
        /// <para>This method works with binary (1bpp) images only.</para>
        /// </remarks>
        public ISet <Shape> FindLines(Image image, CancellationToken cancellationToken)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            if (image.BitsPerPixel != 1)
            {
                throw new NotImplementedException(Properties.Resources.E_UnsupportedDepth_1bpp);
            }

            // find check boxes
            ISet <CheckboxShape> checkboxResult            = null;
            BoundedObjectGrid <CheckboxShape> checkboxGrid = null;

            if (this.FindCheckboxes)
            {
                checkboxResult = this.FindBoxes(image, cancellationToken);

                checkboxGrid = new BoundedObjectGrid <CheckboxShape>(image.Bounds, 5, 10);
                checkboxGrid.AddRange(checkboxResult, true, true);
            }

            HashSet <LineShape> hlinesResult = null;
            HashSet <LineShape> vlinesResult = null;

            if (this.LineTypes != LineTypes.None)
            {
                // masks we would like to find
                Image hlines = null;
                Image vlines = null;
                FindLines();

                if (hlines != null || vlines != null)
                {
                    // filter out false positives
                    FilterFalsePositives(out Image nonHLines, out Image nonVLines);

                    if (this.RemoveLines)
                    {
                        if (hlines != null)
                        {
                            RemoveLines(hlines, nonHLines);
                        }

                        if (vlines != null)
                        {
                            RemoveLines(vlines, nonVLines);
                        }

                        if (hlines != null && vlines != null)
                        {
                            RemoveIntersections();
                        }
                    }
                }

                void FindLines()
                {
                    // close up small holes
                    int   maxLineWidth = LineDetector.MaxLineWidth.MulDiv(image.HorizontalResolution, 200);
                    Image closedImage  = image.MorphClose(null, StructuringElement.Brick(maxLineWidth / 3, 2), 1, BorderType.BorderConst, image.WhiteColor);

                    // open up to detect big solid areas
                    Image openedImage = closedImage.MorphOpen(null, StructuringElement.Square(maxLineWidth), 1, BorderType.BorderConst, image.WhiteColor);
                    Image hollowImage = closedImage.Sub(null, openedImage, 0);

                    // open up in both directions to find lines
                    int minHorLineLength = LineDetector.MinHorLineLength.MulDiv(image.HorizontalResolution, 200);

                    hlines = hollowImage.MorphOpen(null, StructuringElement.Brick(minHorLineLength, 1), 1, BorderType.BorderConst, image.WhiteColor);
                    if (hlines.IsAllWhite())
                    {
                        hlines = null;
                    }
                    else
                    {
                        hlinesResult = this.FilterHorizontalLines(hlines, checkboxGrid);
                        if (hlinesResult.Count == 0)
                        {
                            hlines = null;
                        }
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    int minVerLineLength = LineDetector.MinVerLineLength.MulDiv(image.HorizontalResolution, 200);

                    vlines = hollowImage.MorphOpen(null, StructuringElement.Brick(1, minVerLineLength), 1, BorderType.BorderConst, image.WhiteColor);
                    if (vlines.IsAllWhite())
                    {
                        vlines = null;
                    }
                    else
                    {
                        vlinesResult = this.FilterVerticalLines(vlines, hlines, checkboxGrid);
                        if (vlinesResult.Count == 0)
                        {
                            vlines = null;
                        }
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                }

                void FilterFalsePositives(out Image nonHLines, out Image nonVLines)
                {
                    nonHLines = null;
                    nonVLines = null;

                    Image nonLines = null;

                    if (hlines != null)
                    {
                        nonLines = image.Sub(nonLines, hlines, 0);
                    }

                    if (vlines != null)
                    {
                        nonLines = (nonLines ?? image).Sub(nonLines, vlines, 0);
                    }

                    Image intersections = vlines != null && hlines != null ? hlines & vlines : null;

                    int maxLineResidue = 6; //// LineDetector.MaxLineResidue.MulDiv(image.HorizontalResolution, 200);

                    if (hlines != null)
                    {
                        nonHLines = nonLines.Erode(null, StructuringElement.Brick(1, maxLineResidue), 1, BorderType.BorderConst, image.WhiteColor);
                        nonHLines.FloodFill(nonHLines, 8, nonLines);

                        if (vlines != null)
                        {
                            nonHLines += vlines;
                            nonHLines -= intersections;
                        }
                    }

                    ////int maxLineResidue = 6; //// LineDetector.MaxLineResidue.MulDiv(image.HorizontalResolution, 200);
                    if (vlines != null)
                    {
                        nonVLines = nonLines.Erode(null, StructuringElement.Brick(maxLineResidue, 1), 1, BorderType.BorderConst, image.WhiteColor);
                        nonVLines.FloodFill(nonVLines, 8, nonLines);

                        if (hlines != null)
                        {
                            nonVLines += hlines;
                            nonVLines -= intersections;
                        }
                    }

                    int removedCount = 0;

                    do
                    {
                        removedCount = 0;

                        // horizontal lines
                        if (hlines != null)
                        {
                            int count = this.RemoveHorizontalLinesFalsePositives(hlinesResult, hlines, nonHLines, intersections);
                            if (count > 0)
                            {
                                removedCount += count;
                                if (vlines != null)
                                {
                                    // recompute intersections
                                    intersections = hlines.And(intersections, vlines);
                                }

                                if (hlinesResult.Count == 0)
                                {
                                    hlines = null;
                                }
                            }

                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        // vertical lines
                        if (vlines != null)
                        {
                            int count = this.RemoveVerticalLinesFalsePositives(vlinesResult, vlines, nonVLines, intersections);
                            if (count > 0)
                            {
                                removedCount += count;
                                if (hlines != null)
                                {
                                    // recompute intersections
                                    intersections = hlines.And(intersections, vlines);
                                }

                                if (vlinesResult.Count == 0)
                                {
                                    vlines = null;
                                }
                            }

                            cancellationToken.ThrowIfCancellationRequested();
                        }
                    }while (removedCount != 0);
                }

                void RemoveLines(Image lines, Image nonLines)
                {
                    // remove the lines
                    image.Xand(image, lines);

                    // dilate the lines so they touch the residue
                    // then flood fill then to get all the residue (image less non-lines)
                    Image fatLines = lines.Dilate3x3(null, BorderType.BorderConst, image.WhiteColor);

                    fatLines.FloodFill(fatLines, 8, image.Xand(null, nonLines));

                    // remove the residue
                    image.Xand(image, fatLines);

                    cancellationToken.ThrowIfCancellationRequested();
                }

                void RemoveIntersections()
                {
                    // TODO:
                    // get the intersection residue

                    /*Image residue = hlines
                     *  .And(null, vlines)
                     *  .Dilate(null, StructuringElement.Square(5), 1, BorderType.BorderConst, image.WhiteColor);
                     *
                     * residue.FloodFill(residue, 8, image);
                     *
                     * // remove the residue
                     * image.Xand(image, residue);
                     *
                     * cancellationToken.ThrowIfCancellationRequested();*/
                }
            }

            // delete check boxes from the image
            if (this.RemoveCheckboxes && checkboxResult != null)
            {
                foreach (CheckboxShape shape in checkboxResult)
                {
                    image.SetWhite(Rectangle.Inflate(shape.Bounds, 1, 1));
                }
            }

            // create a draft that would show found check boxes
#if DEBUG
            Image draft = image.ConvertTo(null, 32);

            if (checkboxResult != null)
            {
                foreach (CheckboxShape shape in checkboxResult)
                {
                    draft.DrawRectangle(shape.Bounds, Color.Green);
                }
            }

            if (hlinesResult != null)
            {
                foreach (LineShape shape in hlinesResult)
                {
                    draft.DrawRectangle(shape.Bounds, Color.Red);
                }
            }

            if (vlinesResult != null)
            {
                foreach (LineShape shape in vlinesResult)
                {
                    draft.DrawRectangle(shape.Bounds, Color.Red);
                }
            }
#endif

            // create answer
            HashSet <Shape> answer = new HashSet <Shape>();
            if (hlinesResult != null)
            {
                answer.UnionWith(hlinesResult);
            }

            if (vlinesResult != null)
            {
                answer.UnionWith(vlinesResult);
            }

            if (checkboxResult != null)
            {
                answer.UnionWith(checkboxResult);
            }

            return(answer);
        }