Exemple #1
1
        public double[] detectionGlyph(bool CalculTailleTerrain)
        {
            bool Trouve = false;
            double[] ratio = new double[2] { 0, 0 };
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.MinHeight = 23;
            blobCounter.MinWidth = 23;
            blobCounter.FilterBlobs = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            // 4 - find all stand alone blobs
            blobCounter.ProcessImage(imgContour);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            // 5 - check each blob
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List<IntPoint> corners = null;

                // Test de la forme selectionnée
                if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                {
                    // Détection des points de coutour
                    List<IntPoint> leftEdgePoints, rightEdgePoints, topEdgePoints, bottomEdgePoints;

                    Line Horizontale = Line.FromPoints(new IntPoint(0,0),new IntPoint(10,0));
                    blobCounter.GetBlobsLeftAndRightEdges(blobs[i], out leftEdgePoints, out rightEdgePoints);
                    blobCounter.GetBlobsTopAndBottomEdges(blobs[i], out topEdgePoints, out bottomEdgePoints);

                    // calculate average difference between pixel values from outside of the
                    // shape and from inside
                    float diff = CalculateAverageEdgesBrightnessDifference(leftEdgePoints, rightEdgePoints, imgNB);
                    // check average difference, which tells how much outside is lighter than
                    // inside on the average
                    if (diff > 20)
                    {
                        // Transformation de l'image reçu en un carré pour la reconnaissance
                        QuadrilateralTransformation quadrilateralTransformation = new QuadrilateralTransformation(corners, 60, 60);
                        UnmanagedImage glyphImage = quadrilateralTransformation.Apply(imgNB);

                        // Filtre de contraste
                        OtsuThreshold otsuThresholdFilter = new OtsuThreshold();
                        otsuThresholdFilter.ApplyInPlace(glyphImage);
                        imgContour = glyphImage;
                        // Reconnaissance du Glyph
                        Glyph Gl = new Glyph(glyphImage, GlyphSize);

                        Gl.ReconnaissanceGlyph(corners, imgNB);

                        // Si le Glyph est valide
                        if (Gl.getIdentifiant() > 0)
                        {
                            if (AutAffichage[0])
                            {
                                // Coloration des contours des zones détectées
                                UnImgReel.SetPixels(leftEdgePoints, Color.Red);
                                UnImgReel.SetPixels(rightEdgePoints, Color.Red);
                                UnImgReel.SetPixels(topEdgePoints, Color.Red);
                                UnImgReel.SetPixels(bottomEdgePoints, Color.Red);
                            }

                            // Détection du milieu
                            Line line = Line.FromPoints(corners[0], corners[2]);
                            Line line2 = Line.FromPoints(corners[1], corners[3]);
                            IntPoint intersection = (IntPoint)line.GetIntersectionWith(line2);
                            if (AutAffichage[1])
                            {
                                dessinePoint(intersection, UnImgReel, 4, Color.Yellow);
                            }

                            // Calcul de la rotation
                            Line ComparasionAngle = Line.FromPoints(corners[0], corners[1]);
                            Double rotation = (int) ComparasionAngle.GetAngleBetweenLines(Horizontale);
                            rotation += 90 * Gl.getNbRotation();
                            Gl.rotation = 360 - rotation;
                            rotation *= (Math.PI / 180.0);

                            // Calcul d'un point en bout de pince
                            float Taille = corners[0].DistanceTo(corners[1]);

                            float taille = (Taille / BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille) * BibliotequeGlyph.Biblioteque[Gl.getPosition()].DistancePince;
                            int x = -(int)(System.Math.Sin(rotation) * taille);
                            int y = -(int)(System.Math.Cos(rotation) * taille);
                            x += (int)intersection.X;
                            y += (int)intersection.Y;
                            Gl.Position = new int[2]{x,y};
                            if (AutAffichage[2])
                            {
                                dessinePoint(new IntPoint(x, y), UnImgReel, 4, Color.Cyan);
                            }
                            imgContour = Gl.getImage();
                            addGlyph(Gl);

                            if (CalculTailleTerrain == true && Trouve == false)
                            {
                                Trouve = true;
                                int tailleglyph = BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille;

                                // Pythagore pour detection taille
                                Rectangle a = blobs[i].Rectangle;
                                double angle = - Gl.rotation + 180;
                                List<IntPoint> coins = new List<IntPoint>();
                                coins.Add(new IntPoint(100,100));
                                coins.Add(new IntPoint(100, 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph , 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph, 100));
                                IntPoint Centre = new IntPoint((coins[2].X + coins[0].X)/2, (coins[2].Y + coins[0].Y) / 2);
                                int radius = (int)(0.5 * Math.Sqrt(coins[0].DistanceTo(coins[1]) * coins[0].DistanceTo(coins[1]) + coins[1].DistanceTo(coins[2]) * coins[1].DistanceTo(coins[2])));
                                double alpha = Math.Atan2(coins[0].DistanceTo(coins[1]), coins[1].DistanceTo(coins[2])) * (180 / Math.PI);

                                double ang = 0;
                                for(i = 0; i < 4; i++)
                                {
                                    IntPoint tmp = coins[i];
                                    switch (i)
                                    {
                                        case 0:
                                            ang = alpha - 180 + angle;
                                            break;
                                        case 1:
                                            ang = + angle - alpha;
                                            break;
                                        case 2:
                                            ang = + angle + alpha;
                                            break;
                                        case 3:
                                            ang = - alpha + 180 + angle;
                                            break;
                                    }
                                    ang *= (Math.PI / 180);
                                    tmp.X = (int)(Centre.X + radius * Math.Cos(ang));
                                    tmp.Y = (int)(Centre.Y + radius * Math.Sin(ang));

                                    coins[i] = tmp;
                                }

                                Rectangle r = new Rectangle(min(coins[0].X, coins[1].X, coins[2].X, coins[3].X), min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y),
                                                            max(coins[0].X, coins[1].X, coins[2].X, coins[3].X) - min(coins[0].X, coins[1].X, coins[2].X, coins[3].X),
                                                            max(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y) - min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y));
                                ratio[0] = ((double)r.Width / (double)a.Width) * 1.48;
                                ratio[1] = ((double)r.Height / (double)a.Height) * 1.48;

                            }
                        }
                    }
                }
            }
            if (Trouve == false || ratio[0] == 0 || ratio[0] == 1 || ratio[1] == 0 || ratio[1] == 1)
            {
                return null;
            }
            ratio[0] *= 0.7;
            ratio[1] *= 0.7;
            return ratio;
        }
Exemple #2
0
        public MagicCard(Bitmap cameraBitmap, IEnumerable<IntPoint> corners)
        {
            this.CameraBitmap = cameraBitmap;

            QuadrilateralTransformation transformFilter = new QuadrilateralTransformation(corners.ToList(), 211, 298);
            this.CardBitmap = transformFilter.Apply(cameraBitmap);

            QuadrilateralTransformation cardArtFilter = new QuadrilateralTransformation(artCorners.ToList(), 183, 133);
            this.CardArtBitmap = cardArtFilter.Apply(this.CardBitmap);

            this.Corners = corners.ToList();
        }
Exemple #3
0
        /// <summary>
        /// source code : modified and updated from https://www.codeproject.com/Articles/884518/Csharp-Optical-Marks-Recognition-OMR-Engine-a-Mar
        /// </summary>
        public static Bitmap ApplyWrap(List <AForge.IntPoint> quad, Bitmap originalIage, double scale, Pattern pattern)
        {
            //pattern witdh and height
            double ratio = Math.Max((double)originalIage.Width / (double)pattern.Width, (double)originalIage.Height / (double)pattern.Height);

            ratio *= scale;
            AForge.Imaging.Filters.QuadrilateralTransformation wrap = new AForge.Imaging.Filters.QuadrilateralTransformation(quad);
            wrap.UseInterpolation = false;
            Size sr = new Size()
            {
                Width  = pattern.Width,
                Height = pattern.Height
            };

            sr = new Size(
                (int)Math.Round((double)sr.Width * ratio),
                (int)Math.Round((double)sr.Height * ratio)
                );
            wrap.AutomaticSizeCalculaton = false;
            wrap.NewWidth  = sr.Width;
            wrap.NewHeight = sr.Height;
            return(wrap.Apply(originalIage)); // wrap
        }
Exemple #4
0
        public static Bitmap Clip(Bitmap source,
            List<IntPoint> corners)
        {
#if NO
            // define quadrilateral's corners
            List<IntPoint> corners = new List<IntPoint>();
            corners.Add(new IntPoint(99, 99));
            corners.Add(new IntPoint(156, 79));
            corners.Add(new IntPoint(184, 126));
            corners.Add(new IntPoint(122, 150));
#endif
            int width = 0;
            int height = 0;
            GetWidthHeight(corners, out width, out height);

            // create filter
            QuadrilateralTransformation filter =
                new QuadrilateralTransformation(corners, width, height);
            // apply the filter
            return filter.Apply(source);
        }
Exemple #5
0
        private void detectQuads(Bitmap bitmap)
        {
            // Greyscale
            filteredBitmap = Grayscale.CommonAlgorithms.BT709.Apply(bitmap);

            // edge filter
            SobelEdgeDetector edgeFilter = new SobelEdgeDetector();
            edgeFilter.ApplyInPlace(filteredBitmap);

            // Threshhold filter
            Threshold threshholdFilter = new Threshold(190);
            threshholdFilter.ApplyInPlace(filteredBitmap);

            BitmapData bitmapData = filteredBitmap.LockBits(
                new Rectangle(0, 0, filteredBitmap.Width, filteredBitmap.Height),
                ImageLockMode.ReadWrite, filteredBitmap.PixelFormat);

            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight = 125;
            blobCounter.MinWidth = 125;

            blobCounter.ProcessImage(bitmapData);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            filteredBitmap.UnlockBits(bitmapData);

            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();

            Bitmap bm = new Bitmap(filteredBitmap.Width, filteredBitmap.Height, PixelFormat.Format24bppRgb);

            Graphics g = Graphics.FromImage(bm);
            g.DrawImage(filteredBitmap, 0, 0);

            Pen pen = new Pen(Color.Red, 5);
            List<IntPoint> cardPositions = new List<IntPoint>();

            // Loop through detected shapes
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List<IntPoint> corners;
                bool sameCard = false;

                // is triangle or quadrilateral
                if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
                {
                    // get sub-type
                    PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);

                    // Only return 4 corner rectanges
                    if ((subType == PolygonSubType.Parallelogram || subType == PolygonSubType.Rectangle) &&  corners.Count == 4)
                    {
                        // Check if its sideways, if so rearrange the corners so it's veritcal
                        rearrangeCorners(corners);

                        // Prevent it from detecting the same card twice
                        foreach (IntPoint point in cardPositions)
                        {
                            if (corners[0].DistanceTo(point) < 40)
                                sameCard = true;
                        }

                        if (sameCard)
                            continue;

                        // Hack to prevent it from detecting smaller sections of the card instead of the whole card
                        if (GetArea(corners) < 20000)
                            continue;

                        cardPositions.Add(corners[0]);

                        g.DrawPolygon(pen, ToPointsArray(corners));

                        // Extract the card bitmap
                        QuadrilateralTransformation transformFilter = new QuadrilateralTransformation(corners, 211, 298);
                        cardBitmap = transformFilter.Apply(cameraBitmap);

                        List<IntPoint> artCorners = new List<IntPoint>();
                        artCorners.Add(new IntPoint(14, 35));
                        artCorners.Add(new IntPoint(193, 35));
                        artCorners.Add(new IntPoint(193, 168));
                        artCorners.Add(new IntPoint(14, 168));

                        // Extract the art bitmap
                        QuadrilateralTransformation cartArtFilter = new QuadrilateralTransformation(artCorners, 183, 133);
                        cardArtBitmap = cartArtFilter.Apply(cardBitmap);

                        MagicCard card = new MagicCard();
                        card.corners = corners;
                        card.cardBitmap = cardBitmap;
                        card.cardArtBitmap = cardArtBitmap;

                        magicCards.Add(card);
                    }
                }
            }

            pen.Dispose();
            g.Dispose();

            filteredBitmap = bm;
        }
        public List<Object> findObjects(VideoReader videoReader, IDepthReader depthReader, Action<ushort[], CameraSpacePoint[]> mappingFunction, IProgress<int> progress)
        {
            var shapeOptimizer = new FlatAnglesOptimizer(160);
            Console.WriteLine("Find glyph box");
            List<Object> objects = new List<Object>();

            if (videoReader == null)
                return objects;

            /// For each frame (int frameNo)
            /// For each recognized glyph in frame (int faceIndex)
            /// Store A tuple of 
            ///              -    A list of bounding points for recognized glyph
            ///              -    A glyphface instance
            var recognizedGlyphs = new Dictionary<int, Dictionary<int, Dictionary<int, Tuple<List<System.Drawing.PointF>, GlyphFace, List<Point3>>>>>();

            Bitmap image = null;
            Mat m = null;
            Bitmap grayImage = null;
            Bitmap edges = null;
            UnmanagedImage grayUI = null;
            Bitmap transformed = null;
            Bitmap transformedOtsu = null;


            //A control flag, true if at the previous frame loop, there is detection of some glyph
            // When this is true, only searching for glyph box in some neighborhood of the previous glyphs
            // if the frame is not an anchor frame
            bool previousFrameDetection = false;

            for (int frameNo = 0; frameNo < videoReader.frameCount; frameNo++)
            //for (int frameNo = 80; frameNo < 81; frameNo++)
            {
                if (progress != null)
                    progress.Report(frameNo);

                Console.WriteLine("=============================================");
                Console.WriteLine("Frame no " + frameNo);
                m = videoReader.getFrame(frameNo);
                if (m == null)
                {
                    break;
                }

                var startPos = new System.Drawing.Point();

                getImageForProcessing(recognizedGlyphs, m, previousFrameDetection, frameNo, ref image, ref startPos);

                // Reset right after using
                previousFrameDetection = false;


                Stopwatch stopwatch = Stopwatch.StartNew();

                /// Adapt from Glyph Recognition Prototyping
                /// Copyright © Andrew Kirillov, 2009-2010
                /// 
                // 1 - Grayscale
                grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image);

                stopwatch.Stop();
                Console.WriteLine("Gray scale time = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();

                // 2 - Edge detection
                DifferenceEdgeDetector edgeDetector = new DifferenceEdgeDetector();
                edges = edgeDetector.Apply(grayImage);

                stopwatch.Stop();
                Console.WriteLine("Edge detection time = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();

                // 3 - Threshold edges
                // Was set to 20 and the number of detected glyphs are too low
                // Should be set higher
                Threshold thresholdFilter = new Threshold(60);
                thresholdFilter.ApplyInPlace(edges);

                stopwatch.Stop();
                Console.WriteLine("Threshold time = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();

                // 4 - Blob Counter
                BlobCounter blobCounter = new BlobCounter();
                blobCounter.MinHeight = 32;
                blobCounter.MinWidth = 32;
                blobCounter.FilterBlobs = true;
                blobCounter.ObjectsOrder = ObjectsOrder.Size;

                blobCounter.ProcessImage(edges);
                Blob[] blobs = blobCounter.GetObjectsInformation();

                stopwatch.Stop();
                Console.WriteLine("Blob finding time = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();

                //// create unmanaged copy of source image, so we could draw on it
                //UnmanagedImage imageData = UnmanagedImage.FromManagedImage(image);

                // Get unmanaged copy of grayscale image, so we could access it's pixel values
                grayUI = UnmanagedImage.FromManagedImage(grayImage);

                // list of found dark/black quadrilaterals surrounded by white area
                List<List<IntPoint>> foundObjects = new List<List<IntPoint>>();
                // shape checker for checking quadrilaterals
                SimpleShapeChecker shapeChecker = new SimpleShapeChecker();

                Console.WriteLine("edgePoints");

                // 5 - check each blob
                for (int i = 0, n = blobs.Length; i < n; i++)
                {
                    List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);

                    List<IntPoint> corners = null;

                    // does it look like a quadrilateral ?
                    if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                    {
                        // do some more checks to filter so unacceptable shapes
                        // if ( CheckIfShapeIsAcceptable( corners ) )
                        {

                            // get edge points on the left and on the right side
                            List<IntPoint> leftEdgePoints, rightEdgePoints;
                            blobCounter.GetBlobsLeftAndRightEdges(blobs[i], out leftEdgePoints, out rightEdgePoints);

                            // calculate average difference between pixel values from outside of the shape and from inside
                            float diff = this.CalculateAverageEdgesBrightnessDifference(
                                leftEdgePoints, rightEdgePoints, grayUI);

                            // check average difference, which tells how much outside is lighter than inside on the average
                            if (diff > 20)
                            {
                                //Drawing.Polygon(imageData, corners, Color.FromArgb(255, 255, 0, 0));
                                // add the object to the list of interesting objects for further processing
                                foundObjects.Add(corners);
                            }
                        }
                    }
                }

                stopwatch.Stop();
                Console.WriteLine("Finding black quadiralateral surrounded by white area = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();


                int recordedTimeForRgbFrame = (int)(videoReader.totalMiliTime * frameNo / (videoReader.frameCount - 1));

                CameraSpacePoint[] csps = new CameraSpacePoint[videoReader.frameWidth * videoReader.frameHeight];
                if (depthReader != null)
                {
                    ushort[] depthValues = depthReader.readFrameAtTime(recordedTimeForRgbFrame);
                    mappingFunction(depthValues, csps);
                }

                stopwatch.Stop();
                Console.WriteLine("Mapping into 3 dimensional = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();


                // further processing of each potential glyph
                foreach (List<IntPoint> corners in foundObjects)
                {
                    Console.WriteLine("found some corner");
                    // 6 - do quadrilateral transformation
                    QuadrilateralTransformation quadrilateralTransformation =
                        new QuadrilateralTransformation(corners, 20 * (glyphSize + 2), 20 * (glyphSize + 2));

                    transformed = quadrilateralTransformation.Apply(grayImage);

                    // 7 - otsu thresholding
                    OtsuThreshold otsuThresholdFilter = new OtsuThreshold();
                    transformedOtsu = otsuThresholdFilter.Apply(transformed);

                    // +2 for offset
                    int glyphSizeWithBoundary = glyphSize + 2;
                    SquareBinaryGlyphRecognizer gr = new SquareBinaryGlyphRecognizer(glyphSizeWithBoundary);

                    bool[,] glyphValues = gr.Recognize(ref transformedOtsu,
                        new Rectangle(0, 0, 20 * (glyphSize + 2), 20 * (glyphSize + 2)));

                    bool[,] resizedGlyphValues = new bool[glyphSize, glyphSize];

                    for (int i = 0; i < glyphSize; i++)
                        for (int j = 0; j < glyphSize; j++)
                        {
                            resizedGlyphValues[i, j] = glyphValues[i + 1, j + 1];
                        }


                    GlyphFace face = new GlyphFace(resizedGlyphValues, glyphSize);

                    Console.WriteLine("Find glyph face " + face.ToString());

                    // Transfer back to original coordinates
                    List<IntPoint> originalCorners = new List<IntPoint>();
                    foreach (var corner in corners)
                    {
                        IntPoint p = new IntPoint(corner.X + startPos.X, corner.Y + startPos.Y);
                        originalCorners.Add(p);
                    }

                    Console.WriteLine("Corner points");
                    foreach (var corner in originalCorners)
                    {
                        Console.WriteLine(corner);
                    }

                    for (int boxPrototypeIndex = 0; boxPrototypeIndex < boxPrototypes.Count; boxPrototypeIndex++)
                    {
                        var boxPrototype = boxPrototypes[boxPrototypeIndex];
                        foreach (int faceIndex in boxPrototype.indexToGlyphFaces.Keys)
                        {
                            if (face.Equals(boxPrototype.indexToGlyphFaces[faceIndex]))
                            {
                                if (!recognizedGlyphs.ContainsKey(boxPrototypeIndex))
                                {
                                    Console.WriteLine("Detect new type of prototype " + boxPrototypeIndex);
                                    recognizedGlyphs[boxPrototypeIndex] = new Dictionary<int, Dictionary<int, Tuple<List<System.Drawing.PointF>, GlyphFace, List<Point3>>>>();
                                }

                                if (!recognizedGlyphs[boxPrototypeIndex].ContainsKey(frameNo))
                                {
                                    Console.WriteLine("Detect glyph at frame " + frameNo + " for prototype " + boxPrototypeIndex);
                                    if (!previousFrameDetection)
                                    {
                                        previousFrameDetection = true;
                                    }

                                    recognizedGlyphs[boxPrototypeIndex][frameNo] = new Dictionary<int, Tuple<List<System.Drawing.PointF>, GlyphFace, List<Point3>>>();
                                }

                                recognizedGlyphs[boxPrototypeIndex][frameNo][faceIndex] = new Tuple<List<System.Drawing.PointF>, GlyphFace, List<Point3>>(
                                    originalCorners.Select(p => new System.Drawing.PointF(p.X, p.Y)).ToList(),
                                    face,
                                    depthReader != null ?
                                    originalCorners.Select(p => p.X + p.Y * videoReader.frameWidth >= 0 && p.X + p.Y * videoReader.frameWidth < videoReader.frameWidth * videoReader.frameHeight ?
                                                                   new Point3(csps[p.X + p.Y * videoReader.frameWidth].X,
                                                                   csps[p.X + p.Y * videoReader.frameWidth].Y,
                                                                   csps[p.X + p.Y * videoReader.frameWidth].Z) : new Point3()).ToList() :
                                                                   new List<Point3>()
                                    );

                                break;
                            }
                        }
                    }
                }

                foreach (IDisposable o in new IDisposable[] { image, m, grayImage, edges, grayUI, transformed, transformedOtsu })
                {
                    if (o != null)
                    {
                        o.Dispose();
                    }
                }

                stopwatch.Stop();
                Console.WriteLine("Transforming and detect glyph = " + stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();

            }

            if (progress != null)
                progress.Report(videoReader.frameCount);

            if (recognizedGlyphs.Keys.Count != 0)
            {
                foreach (int boxPrototypeIndex in recognizedGlyphs.Keys)
                {
                    Console.WriteLine("For boxPrototypeIndex = " + boxPrototypeIndex + " Found glyph box at " + recognizedGlyphs[boxPrototypeIndex].Keys.Count + " frames");
                    GlyphBoxObject oneBox = null;
                    var boxPrototype = boxPrototypes[boxPrototypeIndex];
                    oneBox = new GlyphBoxObject(currentSession, "", Color.Black, 1, videoReader.fileName);
                    oneBox.boxPrototype = boxPrototype;
                    foreach (int frameNo in recognizedGlyphs[boxPrototypeIndex].Keys)
                    {
                        var glyphs = recognizedGlyphs[boxPrototypeIndex][frameNo];

                        var glyphBounds = new List<List<System.Drawing.PointF>>();
                        var glyph3DBounds = new List<List<Point3>>();
                        var faces = new List<GlyphFace>();

                        foreach (var glyph in glyphs)
                        {
                            glyphBounds.Add(glyph.Value.Item1);
                            faces.Add(glyph.Value.Item2);
                            glyph3DBounds.Add(glyph.Value.Item3);
                        }

                        oneBox.setBounding(frameNo, glyphSize, glyphBounds, faces);
                        oneBox.set3DBounding(frameNo, glyphSize, glyph3DBounds, faces);

                        //Point3 center = new Point3();
                        //Quaternions quaternions = new Quaternions();

                        //oneBox.set3DBounding(frameNo, new CubeLocationMark(frameNo, center, quaternions));
                    }

                    objects.Add(oneBox);
                }
            }

            return objects;
        }
        /// <summary>
        /// Detects and recognizes cards from source image
        /// </summary>
        /// <param name="source">Source image to be scanned</param>
        /// <returns>Recognized Cards</returns>
        public CardCollection Recognize(Bitmap source)
        {
            CardCollection collection = new CardCollection();  //Collection that will hold cards
            Bitmap temp = source.Clone() as Bitmap; //Clone image to keep original image

            FiltersSequence seq = new FiltersSequence();
            seq.Add(Grayscale.CommonAlgorithms.BT709);  //First add  grayScaling filter
            seq.Add(new OtsuThreshold()); //Then add binarization(thresholding) filter
            temp = seq.Apply(source); // Apply filters on source image

            //Extract blobs from image whose size width and height larger than 150
            BlobCounter extractor = new BlobCounter();
            extractor.FilterBlobs = true;
            extractor.MinWidth = extractor.MinHeight = 150;
            extractor.MaxWidth = extractor.MaxHeight = 350;
            extractor.ProcessImage(temp);

            //Will be used transform(extract) cards on source image
            QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation();

            //Will be used resize(scaling) cards
            ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight);

            foreach (Blob blob in extractor.GetObjectsInformation())
            {
                //Get Edge points of card
                List<IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob);
                //Calculate/Find corners of card on source image from edge points
                List<IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints);

                quadTransformer.SourceQuadrilateral = corners; //Set corners for transforming card
                quadTransformer.AutomaticSizeCalculaton = true;

                Bitmap cardImg = quadTransformer.Apply(source); //Extract(transform) card image

                if (cardImg.Width > cardImg.Height) //If card is positioned horizontally
                    cardImg.RotateFlip(RotateFlipType.Rotate90FlipNone); //Rotate
                cardImg = resizer.Apply(cardImg); //Normalize card size

                Card card = new Card(cardImg, corners.ToArray()); //Create Card Object
                bool faceCard = IsFaceCard(cardImg); //Determine type of card(face or not)

                ResizeBicubic res;

                seq.Clear();
                seq.Add(Grayscale.CommonAlgorithms.BT709);
                seq.Add(new OtsuThreshold());

                Bitmap topLeftSuit = card.GetTopLeftSuitPart();
                Bitmap bmp = seq.Apply(topLeftSuit);

                bmp = CutWhiteSpaces(bmp);
                res = new ResizeBicubic(32, 40);
                bmp = res.Apply(bmp);

                Bitmap topLeftRank = card.GetTopLeftRankPart();
                Bitmap bmp2 = seq.Apply(topLeftRank);

                bmp2 = CutWhiteSpaces(bmp2);

                seq.Clear();
                seq.Add(new OtsuThreshold());
                bmp = seq.Apply(bmp);
                card.Suit = ScanSuit(bmp);

                if (!faceCard)
                {
                    res = new ResizeBicubic(26, 40);
                    bmp2 = res.Apply(bmp2);
                    seq.Clear();
                    seq.Add(new OtsuThreshold());
                    bmp2 = seq.Apply(bmp2);
                    card.Rank = ScanRank(bmp2);
                }
                else
                {
                    res = new ResizeBicubic(32, 40);
                    bmp2 = res.Apply(bmp2);
                    seq.Clear();
                    seq.Add(new OtsuThreshold());
                    bmp2 = seq.Apply(bmp2);
                    card.Rank = ScanFaceRank(bmp2);
                }
                collection.Add(card); //Add card to collection
            }
            return collection;
        }
        /// <summary>
        /// Detects and recognizes cards from source image
        /// </summary>
        /// <param name="source">Source image to be scanned</param>
        /// <returns>Recognized Cards</returns>
        public List<Card> Recognize(Bitmap source)
        {
            List<Card> collection = new List<Card>();
            
            Bitmap temp = source.Clone(source.PixelFormat) as Bitmap; //Clone image to keep original image

            FiltersSequence seq = new FiltersSequence();
            seq.Add(Grayscale.CommonAlgorithms.BT709);  //First add  grayScaling filter
            seq.Add(new OtsuThreshold()); //Then add binarization(thresholding) filter
            temp = seq.Apply(source); // Apply filters on source image

            //Extract blobs from image whose size width and height larger than 150
            BlobCounter extractor = new BlobCounter();
            extractor.FilterBlobs = true;
            extractor.MinWidth = extractor.MinHeight = 150;
            extractor.MaxWidth = extractor.MaxHeight = 350;
            extractor.ProcessImage(temp);

            //Will be used transform(extract) cards on source image 
            QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation();

            //Will be used resize(scaling) cards 
            ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight);

            foreach (Blob blob in extractor.GetObjectsInformation())
            {
                //Get Edge points of card
                List<IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob);
                //Calculate/Find corners of card on source image from edge points
                List<IntPoint> corners = PointsCloud.FindQuadrilateralCorners(edgePoints);

                quadTransformer.SourceQuadrilateral = corners; //Set corners for transforming card 
                quadTransformer.AutomaticSizeCalculaton = true;

                Bitmap cardImg = quadTransformer.Apply(source); //Extract(transform) card image

                if (cardImg.Width > cardImg.Height) //If card is positioned horizontally
                {
                    WriteableBitmap wbmp=(WriteableBitmap)cardImg;
                    wbmp = wbmp.Rotate(90);
                    cardImg = (Bitmap)wbmp; //Rotate
                }
                cardImg = resizer.Apply(cardImg); //Normalize card size

                Card card = new Card(cardImg, corners.ToArray()); //Create Card Object
                char color = ScanColor(card.GetTopLeftPart()); //Scan color
                bool faceCard = IsFaceCard(cardImg); //Determine type of card(face or not)

                if (!faceCard)
                {
                    card.Suit = ScanSuit(cardImg, color); //Scan Suit of non-face card
                    card.Rank = ScanRank(cardImg); //Scan Rank of non-face card
                }
                else
                {
                    Bitmap topLeft = card.GetTopLeftPart();

                    seq = null;
                    seq = new FiltersSequence();

                    seq.Add(Grayscale.CommonAlgorithms.BT709);
                    seq.Add(new BradleyLocalThresholding());
                    topLeft = seq.Apply(topLeft);
                    BlobsFiltering bFilter = new BlobsFiltering(5, 5, 150, 150);
                    bFilter.ApplyInPlace(topLeft); //Filter blobs that can not be a suit

                    //topLeft.Save("topleft.bmp", ImageFormat.Bmp);

                    card.Suit = ScanFaceSuit(topLeft, color); //Scan suit of face card
                    card.Rank = ScanFaceRank(topLeft); //Scan rank of face card
                }
                collection.Add(card); //Add card to collection
            }
            return collection;
        }
        public void PerspectiveTransform(string path)
        {
            List<Rectangle> minX = outerMarker.OrderBy(r => r.X).Take(2).ToList();
            List<Rectangle> maxX = outerMarker.OrderBy(r => r.X).Reverse().Take(2).ToList();

            Rectangle topLeft = minX.OrderBy(r => r.Y).First();
            Rectangle bottomLeft = minX.OrderBy(r => r.Y).Reverse().First();

            Rectangle topRight = maxX.OrderBy(r => r.Y).First();
            Rectangle bottomRight = maxX.OrderBy(r => r.Y).Reverse().First();

            List<AForge.IntPoint> corners = new List<AForge.IntPoint>();
            corners.Add(new AForge.IntPoint( topLeft.X, topLeft.Y));
            corners.Add(new AForge.IntPoint(topRight.X + topRight.Width , topRight.Y ));
            corners.Add(new AForge.IntPoint(bottomRight.X + bottomRight.Width , bottomRight.Y + bottomRight.Height));
            corners.Add(new AForge.IntPoint(bottomLeft.X, bottomLeft.Y + bottomRight.Height ));

            QuadrilateralTransformation filter = new QuadrilateralTransformation(corners, 1000, 1375);
            Bitmap newImage = filter.Apply(originalImage.ToBitmap());

            newImage.Save(path);
        }
Exemple #10
0
        // Process specified image trying to recognize counter's image
        public void Process( Bitmap image, IImageProcessingLog log )
        {
            log.AddMessage( "Image size: " + image.Width + " x " + image.Height );

            // 1 - Grayscale
            Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image );
            log.AddImage( "Grayscale", grayImage );

            // 2 - Edge detection
            DifferenceEdgeDetector edgeDetector = new DifferenceEdgeDetector( ); 
            Bitmap edges = edgeDetector.Apply( grayImage );
            log.AddImage( "Edges", edges );

            // 3 - Threshold edges
            Threshold thresholdFilter = new Threshold( 40 ); 
            thresholdFilter.ApplyInPlace( edges );
            log.AddImage( "Thresholded Edges", edges );

            // 4 - Blob Counter
            BlobCounter blobCounter = new BlobCounter( );
            blobCounter.MinHeight = 32;
            blobCounter.MinWidth  = 32;
            blobCounter.FilterBlobs  = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            blobCounter.ProcessImage( edges );
            Blob[] blobs = blobCounter.GetObjectsInformation( );

            // create copy of source image, so we could draw on it
            Bitmap imageCopy = AForge.Imaging.Image.Clone( image );

            BitmapData imageData = imageCopy.LockBits( new Rectangle( 0, 0, image.Width, image.Height ),
                ImageLockMode.ReadWrite, imageCopy.PixelFormat );

            // lock grayscale image, so we could access it's pixel values
            BitmapData grayData = grayImage.LockBits( new Rectangle( 0, 0, image.Width, image.Height ),
                ImageLockMode.ReadOnly, grayImage.PixelFormat );
            UnmanagedImage grayUI = new UnmanagedImage( grayData );

            // list of found dark/black quadrilaterals surrounded by white area
            List<List<IntPoint>> foundObjects = new List<List<IntPoint>>( );
            // shape checker for checking quadrilaterals
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker( );

            // 5 - check each blob
            for ( int i = 0, n = blobs.Length; i < n; i++ )
            {
                List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints( blobs[i] );
                List<IntPoint> corners = null;

                // does it look like a quadrilateral ?
                if ( shapeChecker.IsQuadrilateral( edgePoints, out corners ) )
                {
                    // do some more checks to filter so unacceptable shapes
                    // if ( CheckIfShapeIsAcceptable( corners ) )
                    {
                        log.AddMessage( "Blob size: " + blobs[i].Rectangle.Width + " x " + blobs[i].Rectangle.Height );

                        // get edge points on the left and on the right side
                        List<IntPoint> leftEdgePoints, rightEdgePoints;
                        blobCounter.GetBlobsLeftAndRightEdges( blobs[i], out leftEdgePoints, out rightEdgePoints );

                        // calculate average difference between pixel values from outside of the shape and from inside
                        float diff = CalculateAverageEdgesBrightnessDifference(
                            leftEdgePoints, rightEdgePoints, grayUI );

                        log.AddMessage( "Avg Diff: " + diff );

                        // check average difference, which tells how much outside is lighter than inside on the average
                        if ( diff > 20 )
                        {
                            Drawing.Polygon( imageData, corners, Color.Red );
                            // add the object to the list of interesting objects for further processing
                            foundObjects.Add( corners );
                        }
                    }
                }
            }

            imageCopy.UnlockBits( imageData );
            grayImage.UnlockBits( grayData );

            log.AddImage( "Potential glyps", imageCopy );

            int counter = 1;

            // further processing of each potential glyph
            foreach ( List<IntPoint> corners in foundObjects )
            {
                log.AddMessage( "Glyph #" + counter );
                
                log.AddMessage( string.Format( "Corners: ({0}), ({1}), ({2}), ({3})",
                    corners[0], corners[1], corners[2], corners[3] ) );

                // 6 - do quadrilateral transformation
                QuadrilateralTransformation quadrilateralTransformation =
                    new QuadrilateralTransformation( corners, 250, 250 );

                Bitmap transformed = quadrilateralTransformation.Apply( grayImage );

                log.AddImage( "Transformed #" + counter, transformed );

                // 7 - otsu thresholding
                OtsuThreshold otsuThresholdFilter = new OtsuThreshold( ); 
                Bitmap transformedOtsu = otsuThresholdFilter.Apply( transformed );
                log.AddImage( "Transformed Otsu #" + counter, transformedOtsu );

                int glyphSize = 5;
                SquareBinaryGlyphRecognizer gr = new SquareBinaryGlyphRecognizer( glyphSize );

                bool[,] glyphValues = gr.Recognize( transformedOtsu,
                    new Rectangle( 0, 0, 250, 250 ) );

                log.AddImage( "Glyph lines #" + counter, transformedOtsu );

                // output recognize glyph to log
                log.AddMessage( string.Format( "glyph: {0:F2}%", gr.confidence * 100 ) );
                for ( int i = 0; i < glyphSize; i++ )
                {
                    StringBuilder sb = new StringBuilder( "   " );

                    for ( int j = 0; j < glyphSize; j++ )
                    {
                        sb.Append( ( glyphValues[i, j] ) ? "1 " : "0 " );
                    }

                    log.AddMessage( sb.ToString( ) );
                }

                counter++;
            }
        }
Exemple #11
0
        private Bitmap ExtractImage(Bitmap bitmap, Bitmap originalImg, int fillint, int contint)
        {
            int bmpWidth = bitmap.Width;
            int bmpHeight = bitmap.Height;

            // lock image, Bitmap itself takes much time to be processed
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bmpWidth, bmpHeight),
                ImageLockMode.ReadWrite,
                bitmap.PixelFormat);

            // Store sheet corner locations (if anyone is detected)
            List<IntPoint> quad = new List<IntPoint>();
            try
            {
                // step 2 - locating objects
                BlobCounter blobCounter = new BlobCounter();
                blobCounter.FilterBlobs = true;
                blobCounter.MinHeight = 25;  // both these variables have to be given when calling the
                blobCounter.MinWidth = 25;   // method, the can also be queried from the XML reader using OMREnums

                UnmanagedImage unmanagedImage = new UnmanagedImage(bitmapData);

                blobCounter.ProcessImage(unmanagedImage);
                AForge.Imaging.Blob[] blobs = blobCounter.GetObjects(unmanagedImage, false);

                // this helps filtering out much smaller and much larger blobs depending upon the size of image.
                double minbr = 0.0001;
                double maxbr = 0.005;

                // Detect left edge.
                foreach (AForge.Imaging.Blob blob in blobs)
                {
                    // filters out very small or very larg blobs
                    if (((double)blob.Area) / ((double)bmpWidth * bmpHeight) > minbr &&
                        ((double)blob.Area) / ((double)bmpWidth * bmpHeight) < maxbr &&
                            blob.Rectangle.X < (bmpWidth) / 4)
                    {
                        // filters out blobs having insanely wrong aspect ratio
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > 0.6)
                        {
                            using (Bitmap leftBoundingResized = ResizeImage(this.leftBoundingImg, blob.Rectangle.Width, blob.Rectangle.Height))
                            {
                                if (isSame(blob.Image, leftBoundingResized))
                                {
                                    quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                                }
                            }
                        }
                    }
                }

                // Sort out the list in right sequence, UpperLeft, LowerLeft, LowerRight, UpperRight
                if (quad.Count >= 2)
                {
                    if (quad[0].Y > quad[1].Y)
                    {
                        IntPoint tp = quad[0];
                        quad[0] = quad[1];
                        quad[1] = tp;
                    }
                }

                // Detect right edge.
                foreach (AForge.Imaging.Blob blob in blobs)
                {
                    if (
                        ((double)blob.Area) / ((double)bmpWidth * bmpHeight) > minbr &&
                        ((double)blob.Area) / ((double)bmpWidth * bmpHeight) < maxbr &&
                        blob.Rectangle.X > (bmpWidth * 3) / 4)
                    {
                        if ((double)blob.Rectangle.Width / blob.Rectangle.Height < 1.4 &&
                            (double)blob.Rectangle.Width / blob.Rectangle.Height > 0.6)
                        {
                            using (Bitmap rightBoundingResized = ResizeImage(this.rightBoundingImg, blob.Rectangle.Width, blob.Rectangle.Height))
                            {
                                if (isSame(blob.Image, rightBoundingResized))
                                {
                                    quad.Add(new IntPoint((int)blob.CenterOfGravity.X, (int)blob.CenterOfGravity.Y));
                                }
                            }
                        }
                    }
                }

                if (quad.Count >= 4)
                {
                    if (quad[2].Y < quad[3].Y)
                    {
                        IntPoint tp = quad[2];
                        quad[2] = quad[3];
                        quad[3] = tp;
                    }
                }
            }
            finally
            {
                bitmap.UnlockBits(bitmapData);
            }

            //Again, filter out if wrong blobs pretended to our blobs.
            if (quad.Count == 4)
            {
                // clear if, both edges have insanely wrong lengths
                if (((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) < 0.75 ||
                    ((double)quad[1].Y - (double)quad[0].Y) / ((double)quad[2].Y - (double)quad[3].Y) > 1.25)
                {
                    quad.Clear();
                }
                // clear if, sides appear to be "wrong sided"
                else if (quad[0].X > bmpWidth / 2 || quad[1].X > bmpWidth / 2 || quad[2].X < bmpWidth / 2 || quad[3].X < bmpWidth / 2)
                {
                    quad.Clear();
                }
            }

            // sheet found
            if (quad.Count == 4)
            {
                IntPoint tp2 = quad[3];
                quad[3] = quad[1];
                quad[1] = tp2;
                //sort the edges for wrap operation
                QuadrilateralTransformation wrap = new QuadrilateralTransformation(quad);
                wrap.UseInterpolation = false; //perspective wrap only, no binary.
                wrap.AutomaticSizeCalculaton = false;
                wrap.NewWidth = this.ОMRConfig.ImageWidth;
                wrap.NewHeight = this.ОMRConfig.ImageHeight;
                return wrap.Apply(originalImg);
            }
            else
            {
                return null;
            }
        }
        private void drawRowsAndColsOnCurrentWordsearch()
        {
            //If there is a currently loaded bitmap to draw on
            if(bitmapToShow != null)
            {
                //Get Rows & Cols
                uint rows, cols;
                uint.TryParse(txtNumRows.Text, out rows);
                uint.TryParse(txtNumCols.Text, out cols);

                //Check we have all four coordinates of the wordsearch image
                if (txtTopLeftX.Text != "" && txtTopLeftY.Text != "" &&
                    txtTopRightX.Text != "" && txtTopRightY.Text != "" &&
                    txtBottomRightX.Text != "" && txtBottomRightY.Text != "" &&
                    txtBottomLeftX.Text != "" && txtBottomLeftY.Text != "")
                {
                    List<IntPoint> corners = new List<IntPoint>(4);
                    try
                    {
                        corners.Add(getTopLeftCoordinate());
                        corners.Add(getTopRightCoordinate());
                        corners.Add(getBottomRightCoordinate());
                        corners.Add(getBottomLeftCoordinate());
                    }
                    catch (FormatException) 
                    {
                        //There was an error parsing one of the coordinates
                        MessageBox.Show("Unable to parse coordinates as integers, please check they are valid");
                        return;
                    }
                    
                    //Draw the bounding box onto the main image
                    Bitmap drawnOn = bitmapToShow.DeepCopy();
                    DrawShapes.PolygonInPlace(drawnOn, corners, Color.Red);

                    //If there is a Bitmap which will become unused in memory, dispose of it
                    if(picBoxImage.Image != bitmapToShow)
                    {
                        picBoxImage.Image.Dispose();
                    }
                    picBoxImage.Image = drawnOn;

                    //Extract the wordsearch image & draw the grid on it
                    QuadrilateralTransformation quadTransform = new QuadrilateralTransformation(corners, 
                        picBoxWordsearchImage.Width, picBoxWordsearchImage.Height);

                    Bitmap transformed = quadTransform.Apply(currentBitmap.Key);
                    DrawGrid.GridInPlace(transformed, (int)rows, (int)cols);

                    //If there is a Bitmap which will become unused in memory, dispose if it
                    if(picBoxWordsearchImage.Image != null)
                    {
                        picBoxWordsearchImage.Image.Dispose();
                    }

                    picBoxWordsearchImage.Image = transformed;

                    //If we're currently showing the picture box image in the larger display, show it there too
                    if(picBoxWordsearchImageLarge.Visible)
                    {
                        picBoxWordsearchImageLarge.Image = transformed;
                    }
                }
            }
        }
        //Method to extract a Bitmap of the best match for a wordsearch in an image using a specified Wordsearch Segmentation Algorithm
        //returns null if no Wordsearch candidate could be found in the image
        public static Tuple<List<IntPoint>, Bitmap> ExtractBestWordsearch(Bitmap image, SegmentationAlgorithm segAlg, bool removeSmallRowsAndCols)
        {
            double blobMinDimensionDbl = BLOB_MIN_DIMENSION_PERCENTAGE / 100;
            int minWidth = (int)Math.Ceiling(image.Width * blobMinDimensionDbl); //Round up, so that the integer comaprison minimum will always be correct
            int minHeight = (int)Math.Ceiling(image.Height * blobMinDimensionDbl);

            List<List<IntPoint>> quads = ShapeFinder.Quadrilaterals(image, minWidth, minHeight);

            //Check that there are some quads found to search through for the best wordsearch candidate
            if(quads.Count != 0)
            {
                double bestScore = double.NegativeInfinity;
                List<IntPoint> bestCoords = null;
                Bitmap bestBitmap = null;

                //Search for the Bitmap that yields the best score
                foreach (List<IntPoint> quad in quads)
                {
                    //Extract the Bitmap of this quad
                    QuadrilateralTransformation quadTransform = new QuadrilateralTransformation(quad);
                    Bitmap quadBitmap = quadTransform.Apply(image);

                    //Score this wordsearch candidate
                    double score;
                    //If an InvalidRowsAndCols Exception gets throw by the segmentation 
                    //  (due to there being 0 rows/cols in the returned segmentation)
                    //  this is obviously not a good wordsearch candidate
                    try
                    {
                        Segmentation segmentation = segAlg.Segment(quadBitmap);
                        
                        //If removing erroneously small rows and cols before scoring the segmentation, do so now
                        if(removeSmallRowsAndCols)
                        {
                            segmentation = segmentation.RemoveSmallRowsAndCols();
                        }

                        CandidateScorer scorer = new CandidateScorer(segmentation);
                        score = scorer.WordsearchRecognitionScore;
                    }
                    catch(InvalidRowsAndColsException)
                    {
                        //This is slightly better than the default score of Negative Infinity as any candidate
                        //  (even one with no rows or cols found in it) is better than no candidate whatsoever
                        score = double.MinValue;
                    }

                    //If this score is better than the previous best (don't 
                    //  override equal scores as the list is size ordered and 
                    //  we'll default to the biggest wordsearch as being better)
                    if(score > bestScore)
                    {
                        bestScore = score;
                        bestCoords = quad;

                        //Dispose of the previously best Bitmap resource
                        if(bestBitmap != null)
                        {
                            bestBitmap.Dispose();
                        }
                        //Update the ptr to the new one
                        bestBitmap = quadBitmap;
                    }
                    else
                    {
                        //Clean up
                        quadBitmap.Dispose();
                    }
                }

                return Tuple.Create(bestCoords, bestBitmap);
            }
            else //Otherwise there are no quads to search through
            {
                return null;
            }
        }
        public void QuadrilateralSlotsTransformation(Point[] curvePoints, Bitmap[] bmParkingSlots, Bitmap bmBackgound, int i)
        {
            List<AForge.IntPoint> corners = new List<AForge.IntPoint>();

            corners.Add(new AForge.IntPoint(curvePoints[3 + (4 * i)].X, curvePoints[3 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(curvePoints[0 + (4 * i)].X, curvePoints[0 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(curvePoints[1 + (4 * i)].X, curvePoints[1 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(curvePoints[2 + (4 * i)].X, curvePoints[2 + (4 * i)].Y));

            QuadrilateralTransformation filter = new QuadrilateralTransformation(corners, 200, 200);
            bmParkingSlots[i] = filter.Apply(bmBackgound);
        }
        private Bitmap Transform(List<IntPoint> corners, Bitmap image)
        {
            // otestovat zamenu za SimpleQuadrilateralTransformation - mela by byt rychlejsi
            QuadrilateralTransformation filter = new QuadrilateralTransformation(corners);

            Bitmap newImage = filter.Apply(image);

            // zpetna rotace kvuli transformaci do puvodniho tvaru
            if (newImage.Height > newImage.Width)
            {
                newImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
            }

            newImage = this.Resize(newImage);

            return this.Threshold(newImage, _thresholdLevel);
        }
Exemple #16
0
        // Transform quadrilateral
        private void quadrilateralTransformationMenuItem_Click( object sender, EventArgs e )
        {
            // get corners of the quadrilateral
            QuadrilateralFinder qf = new QuadrilateralFinder( );
            List<IntPoint> corners = qf.ProcessImage( image );
            // create filter
            QuadrilateralTransformation filter =
                new QuadrilateralTransformation( corners );

            ApplyFilter( filter );
        }
        /// <summary>
        /// Scans dominant color on image and returns it.
        /// Crops rank part on image and analyzes suit part on image
        /// </summary>
        /// <param name="bmp">Bitmap to be scanned</param>
        /// <returns>Returns 'B' for black , 'R' for red</returns>
        private char ScanColor(Bitmap bmp)
        {
            //System.Diagnostics.Debug.Flush();
            //System.Diagnostics.Debug.Print("I'm here");
            char color = 'B';
            //Crop rank part


            Crop crop = new Crop(new Rectangle(0, bmp.Height / 2, bmp.Width, bmp.Height / 2));
            bmp = crop.Apply(bmp);
            Bitmap temp = commonSeq.Apply(bmp); //Apply filters

            //Find suit blob on image
            BlobCounter counter = new BlobCounter();
            counter.ProcessImage(temp);
            Blob[] blobs = counter.GetObjectsInformation();

            if (blobs.Length > 0) //If blobs found
            {
                Blob max = blobs[0];
                //Find blob whose size is biggest 
                foreach (Blob blob in blobs)
                {
                    if (blob.Rectangle.Height > max.Rectangle.Height)
                        max = blob;
                    else if (blob.Rectangle.Height == max.Rectangle.Height)
                        max = blob.Rectangle.Width > max.Rectangle.Width ? blob : max;
                }
                QuadrilateralTransformation trans = new QuadrilateralTransformation();
                trans.SourceQuadrilateral = PointsCloud.FindQuadrilateralCorners(counter.GetBlobsEdgePoints(max));
                bmp = trans.Apply(bmp); //Extract suit
            }
            //Lock Bits for processing

            //int bitsPerPixel = ((int)bmp.PixelFormat & 0xff00) >> 8;
            //int bytesPerPixel = (bitsPerPixel + 7) / 8;
            //int stride = 4 * ((bmp.Width * bytesPerPixel + 3) / 4);


           // BitmapData imageData=new BitmapData(bmp.Width, bmp.Height, bmp. )
          // BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly, bmp.PixelFormat);
            int totalRed = 0;
            int totalBlack = 0;

            WriteableBitmap wbmp = (WriteableBitmap)bmp;

            wbmp.ForEach((x, y, pcolor) =>
            {
                int r=Convert.ToInt32(pcolor.R);
                int g=Convert.ToInt32(pcolor.G);
                int b=Convert.ToInt32(pcolor.B);

                if (r > g + b)
                    totalRed++;
                else if (r <= g + b && (r < 50 && g < 50))
                    totalBlack++;

                return pcolor;

            });

            

            if (totalRed > totalBlack) //If red is dominant
                color = 'R'; //Set color as Red

            return color;
        }
        public void DetectQuads()
        {
            // Greyscale
            FilteredBitmap = Grayscale.CommonAlgorithms.BT709.Apply(CameraBitmap);

            // edge filter
            var edgeFilter = new SobelEdgeDetector();
            edgeFilter.ApplyInPlace(FilteredBitmap);

            // Threshhold filter
            var threshholdFilter = new Threshold(190);
            threshholdFilter.ApplyInPlace(FilteredBitmap);

            var bitmapData = FilteredBitmap.LockBits(
                new Rectangle(0, 0, FilteredBitmap.Width, FilteredBitmap.Height),
                ImageLockMode.ReadWrite, FilteredBitmap.PixelFormat);

            var blobCounter = new BlobCounter
            {
                FilterBlobs = true,
                MinHeight = 125,
                MinWidth = 125
            };

            blobCounter.ProcessImage(bitmapData);
            var blobs = blobCounter.GetObjectsInformation();
            FilteredBitmap.UnlockBits(bitmapData);

            var shapeChecker = new SimpleShapeChecker();

            var bm = new Bitmap(FilteredBitmap.Width, FilteredBitmap.Height, PixelFormat.Format24bppRgb);

            var g = Graphics.FromImage(bm);
            g.DrawImage(FilteredBitmap, 0, 0);

            var pen = new Pen((Color)new ColorConverter().ConvertFromString(Application.Current.Resources["AccentColor"].ToString()), 5);
            var cardPositions = new List<IntPoint>();

            // Loop through detected shapes
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                var edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List<IntPoint> corners;
                var sameCard = false;

                // is triangle or quadrilateral
                if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                {
                    if (!corners.Any())
                        return;
                    // get sub-type
                    var subType = shapeChecker.CheckPolygonSubType(corners);

                    // Only return 4 corner rectanges
                    if ((subType != PolygonSubType.Parallelogram && subType != PolygonSubType.Rectangle) || corners.Count != 4)
                        continue;

                    // Check if its sideways, if so rearrange the corners so it's veritcal
                    RearrangeCorners(corners);

                    // Prevent it from detecting the same card twice
                    foreach (var point in cardPositions)
                    {
                        var distance = corners[0].DistanceTo(point);
                        if (corners[0].DistanceTo(point) < 40)
                            sameCard = true;
                    }

                    if (sameCard)
                        continue;

                    // Hack to prevent it from detecting smaller sections of the card instead of the whole card
                    var area = GetArea(corners);

                    if (area < 20000)// || area > 35000)
                        continue;

                    cardPositions.Add(corners[0]);

                    g.DrawPolygon(pen, ToPointsArray(corners));

                    // Extract the card bitmap
                    var transformFilter = new QuadrilateralTransformation(corners, 225, 325);
                    CardBitmap = transformFilter.Apply(CameraBitmap);
                    TmpCard = new MagicCard
                    {
                        Corners = corners,
                        CardBitmap = CardBitmap
                    };
                }
            }

            pen.Dispose();
            g.Dispose();

            FilteredBitmap = bm;
        }
        /// <summary>
        /// Scans dominant color on image and returns it.
        /// Crops rank part on image and analyzes suit part on image
        /// </summary>
        /// <param name="bmp">Bitmap to be scanned</param>
        /// <returns>Returns 'B' for black , 'R' for red</returns>
        private char ScanColor(Bitmap bmp)
        {
            char color = 'B';
            //Crop rank part
            Crop crop = new Crop(new Rectangle(0, bmp.Height / 2, bmp.Width, bmp.Height / 2));
            bmp = crop.Apply(bmp);
            Bitmap temp = commonSeq.Apply(bmp); //Apply filters

            //Find suit blob on image
            BlobCounter counter = new BlobCounter();
            counter.ProcessImage(temp);
            Blob[] blobs = counter.GetObjectsInformation();

            if (blobs.Length > 0) //If blobs found
            {
                Blob max = blobs[0]; 
                //Find blob whose size is biggest 
                foreach (Blob blob in blobs)
                {
                    if (blob.Rectangle.Height > max.Rectangle.Height)
                        max = blob;
                    else if (blob.Rectangle.Height == max.Rectangle.Height)
                        max = blob.Rectangle.Width > max.Rectangle.Width ? blob : max;
                }
                QuadrilateralTransformation trans = new QuadrilateralTransformation();
                trans.SourceQuadrilateral = PointsCloud.FindQuadrilateralCorners(counter.GetBlobsEdgePoints(max));
                bmp = trans.Apply(bmp); //Extract suit
            }
            //Lock Bits for processing
            BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
               ImageLockMode.ReadOnly, bmp.PixelFormat);
            int totalRed = 0;
            int totalBlack = 0;

            unsafe
            {
                //Count red and black pixels
                try
                {
                    UnmanagedImage img = new UnmanagedImage(imageData);
     
                    int height = img.Height;
                    int width = img.Width;
                    int pixelSize = (img.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                    byte* p = (byte*)img.ImageData.ToPointer();

                    // for each line
                    for (int y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (int x = 0; x < width; x++, p += pixelSize)
                        {
                            int r = (int)p[RGB.R]; //Red pixel value
                            int g = (int)p[RGB.G]; //Green pixel value
                            int b = (int)p[RGB.B]; //Blue pixel value

                            if (r > g + b) //If red component is bigger then total of green and blue component
                                totalRed++;  //then its red

                            if (r <= g + b && r < 50 && g < 50 && b < 50) //If all components less 50
                                totalBlack++; //then its black
                        }
                    }

                }
                finally
                {
                    bmp.UnlockBits(imageData); //Unlock
                }
            }
            if (totalRed > totalBlack) //If red is dominant
                color = 'R'; //Set color as Red

            return color;
        }
        // New frame received by the player
        private void videoSourcePlayer_NewFrame( object sender, ref Bitmap image )
        {
            BitmapData imageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);

            try
            {
                UnmanagedImage unmanagedImg = new UnmanagedImage( imageData );

                int x = (int)(unmanagedImg.Width / 3.19); // 443
                int y = (int)(unmanagedImg.Height / 2.2); // 490
                int w = (int)(unmanagedImg.Width / 2.7); // 553
                int h = (int)(unmanagedImg.Height / 4); // 270
                int s = (int)(unmanagedImg.Width / 10.2); // 141

                // Crop the player scroll window.  Speeds up the next couple operations
                Crop onePlayer = new Crop(new Rectangle(x, y, w, h));
                UnmanagedImage img = onePlayer.Apply(unmanagedImg);

                // Use a quadrilateral transformation to make the scroller a big square.
                List<IntPoint> corners = new List<IntPoint>();
                corners.Add(new IntPoint(s, 0));
                corners.Add(new IntPoint(img.Width - s, 0)); ;
                corners.Add(new IntPoint(img.Width, img.Height));
                corners.Add(new IntPoint(0, img.Height));

                QuadrilateralTransformation filter =
                    new QuadrilateralTransformation(corners, img.Width, img.Height);
                img = filter.Apply(img);

                // Crop the bottom half since it appears to have the best imagery
                Crop bottom = new Crop(new Rectangle(0, img.Height / 2, img.Width, img.Height / 2));
                img = bottom.Apply(img);

                UnmanagedImage grayImg = UnmanagedImage.Create(img.Width, img.Height, PixelFormat.Format8bppIndexed);
                Grayscale.CommonAlgorithms.BT709.Apply(img, grayImg);

                OtsuThreshold threshold = new OtsuThreshold();
                threshold.ApplyInPlace(grayImg);

                // Divide the square into 5 peices.  One for each color.
                UnmanagedImage[] colorImg = new UnmanagedImage[5];
                for(int i=0; i < 5; i++) {
                    int colorWidth = grayImg.Width / 5;
                    int colorHeight = grayImg.Height;
                    Crop colorCrop = new Crop(new Rectangle(colorWidth * i, 0, colorWidth, colorHeight));
                    colorImg[i] = colorCrop.Apply(grayImg);
                }

                greenCol.Image = colorImg[GREEN].ToManagedImage();
                redCol.Image = colorImg[RED].ToManagedImage();
                yellowCol.Image = colorImg[YELLOW].ToManagedImage();
                blueCol.Image = colorImg[BLUE].ToManagedImage();
                orangeCol.Image = colorImg[ORANGE].ToManagedImage();

                VerticalIntensityStatistics[] hist = new VerticalIntensityStatistics[5];

                for (int i = 0; i < 5; i++)
                {
                    hist[i] = new VerticalIntensityStatistics(colorImg[i]);
                }

                findPucks(hist);

                greenHist.Values = hist[GREEN].Gray.Values;
                redHist.Values = hist[RED].Gray.Values;
                yellowHist.Values = hist[YELLOW].Gray.Values;
                blueHist.Values = hist[BLUE].Gray.Values;
                orangeHist.Values = hist[ORANGE].Gray.Values;

                pictureBox1.Image = img.ToManagedImage();
            }
            finally
            {
                image.UnlockBits( imageData );
            }
        }
        private Bitmap cutLot(Bitmap blackCanvas, System.Drawing.Point[] ParkingPoint, int i)
        {
            Bitmap compoundImage = null;
            System.Drawing.Point[] parkingLot = { ParkingPoint[0 + (4 * i)], ParkingPoint[1 + (4 * i)],
                                         ParkingPoint[2 + (4 * i)], ParkingPoint[3 + (4 * i)] };

            List<AForge.IntPoint> corners = new List<AForge.IntPoint>();

            corners.Add(new AForge.IntPoint(ParkingPoint[3 + (4 * i)].X, ParkingPoint[3 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(ParkingPoint[0 + (4 * i)].X, ParkingPoint[0 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(ParkingPoint[1 + (4 * i)].X, ParkingPoint[1 + (4 * i)].Y));
            corners.Add(new AForge.IntPoint(ParkingPoint[2 + (4 * i)].X, ParkingPoint[2 + (4 * i)].Y));

            QuadrilateralTransformation Qfilter = new QuadrilateralTransformation(corners, 200, 200);

            //Bitmap frame = new Bitmap(@"currImage.jpg");
            Bitmap frame = (Bitmap)currentFrame.Clone();

            Bitmap nframe = Qfilter.Apply(frame);
            nframe.RotateFlip(RotateFlipType.Rotate180FlipY);

            BackwardQuadrilateralTransformation BQfilter = new BackwardQuadrilateralTransformation(nframe, corners);

            compoundImage = BQfilter.Apply(blackCanvas);
            return nframe;
        }
        public Bitmap GetBitmapCustomResolution(int width, int height)
        {
            //Fetch the bitmap of the main image this wordsearch image is in
            Image fromImage = FromImage;
            fromImage.RegisterInterestInBitmap();

            //Transform the region containing this wordsearch into a new image
            QuadrilateralTransformation quadTransform = new QuadrilateralTransformation(
                new List<IntPoint>(Coordinates), width, height);

            Bitmap customResBitmap = quadTransform.Apply(fromImage.Bitmap);

            //Deregister interest in the main Image's Bitmap to allow for it to dispose of it appropriately
            fromImage.DeregisterInterestInBitmap();

            return customResBitmap;
        }