public Dictionary<Card, Point> LocateCards(Image<Bgr, Byte> table, Settings settings)
        {
            #region process image
            //Convert the image to grayscale and filter out the noise
            Image<Gray, Byte> gray = table.Convert<Gray, Byte>();

            Gray cannyThreshold = new Gray(180);
            Gray cannyThresholdLinking = new Gray(120);
            Gray circleAccumulatorThreshold = new Gray(120);

            Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);

            StructuringElementEx el = new StructuringElementEx(3, 3, 1, 1, CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
            cannyEdges = cannyEdges.MorphologyEx(el, CV_MORPH_OP.CV_MOP_CLOSE, 1);
            #endregion

            Contour<Point> contours = cannyEdges.FindContours(
                CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, //was CV_CHAIN_APPROX_SIMPLE
                RETR_TYPE.CV_RETR_TREE);

            ContourNode tree = new ContourNode(contours);

            Dictionary<Card, Point> cardlocs = new Dictionary<Card, Point>();
            foreach (KeyValuePair<Card, CardContour> pair in GiveCards(tree))
            {
                ContourNode node = pair.Value.Node;
                Card card = pair.Key;

                PointF fcenter = node.Contour.GetMinAreaRect().center;
                Point center = new Point((int)fcenter.X, (int)fcenter.Y);

                cardlocs.Add(card, center);
            }

            #region draw
            #if DEBUG
            TreeViz.VizualizeTree(tree);
            ContourAnalyzer.DrawContours(tree, table);
            //ImageViewer.Show(table);
            #endif
            #endregion

            return cardlocs;
        }
Beispiel #2
0
        private Image<Bgr, Byte> Run(string filename)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();

            ContourAnalyzer ca = new ContourAnalyzer();
            Image<Bgr, Byte> table = new Image<Bgr, byte>(filename);
            table = table.PyrDown().PyrDown();

            int debuglevel = cmbDebuglevel.SelectedIndex;

            Settings settings = new Settings(debuglevel);
            Dictionary<Card, System.Drawing.Point> cards = ca.LocateCards(table, settings);

            Logic logic = new Logic();
            HashSet<List<Card>> sets = logic.FindSets(new List<Card>(cards.Keys));

            Random rnd = new Random();
            foreach (List<Card> set in sets)
            {
                DrawSet(table, cards, rnd, set);
            }

            watch.Stop();
            this.Title = String.Format("Done. Elapsed time: {0}", watch.Elapsed.ToString());

            ImageSource bitmap = TreeViz.ToBitmapSource(table);
            Shower.Source = bitmap;

            return table;
        }
 public Dictionary<SetVision.Gamelogic.Card, Point> LocateCards(Image<Bgr, byte> table, Settings settings)
 {
     throw new NotImplementedException();
 }
        private static CardColor RecognizeColor(ContourNode node, Settings settings)
        {
            Image<Bgr, Byte> image = node.Image;
            image.ROI = node.Contour.BoundingRectangle;

            Image<Bgr, Byte> debugBest = null;
            Point bestpos = FindBestColoredPixel(image, out debugBest);
            Bgr bgr = image[bestpos];

            #region classification
            CardColor classification = classifier.Classify(bgr);
            CardColor verdict = classification;
            if (verdict == CardColor.Other)
            {
                if (!isGray(bgr, 10))
                {
                    verdict = ClassifyBgr2(bgr);
                }
                else
                {
                    verdict = CardColor.White;
                }
            }
            #endregion
            #if DEBUG
            //save for training:
            writer.Write((int)bgr.Blue, (int)bgr.Green, (int)bgr.Red);
            #endif

            #region debug
            if (settings.debuglevel >= 4)
            {
                ImageViewer.Show(debugBest, verdict.ToString());
            }
            else if (settings.debuglevel >= 2 && verdict == CardColor.Other)
            {
                ImageViewer.Show(debugBest, verdict.ToString());
            }
            #endregion
            return verdict;
        }
 private static void AssignColors(ContourNode tree, Image<Bgr, Byte> image, Settings settings)
 {
     AssignColor(tree, image, settings);
     foreach (ContourNode child in tree.Children)
     {
         //AssignColor(child, image, settings);
         AssignColors(child, image, settings);
     }
 }
        private static void AssignColor(ContourNode node, Image<Bgr, Byte> image, Settings settings)
        {
            if (node.Contour.Area > 100
                && ((node.Shape == Shape.Squiggle)
                    || (node.Shape == Shape.Diamond)
                    || (node.Shape == Shape.Oval)))
            {
                //CardColor color = RecognizeColor(image, node);
                //CardColor color = RecognizeColor(node);
                CardColor color = RecognizeColor(node, settings);
                node.Color = color;

                AssignAverageColors(node, settings);
            }
            else if (node.Shape == Shape.Card)
            {
                AssignAverageColors(node, settings);
            }
        }
        private static void AssignAverageColors(ContourNode node, Settings settings)
        {
            //Then get the average color of the card (should be white or gray)
            Bgr avgBgr = new Bgr();
            MCvScalar scr1 = new MCvScalar();
            node.Image.AvgSdv(out avgBgr, out scr1, node.AttentionMask);

            node.averageBgr = avgBgr;

            Hsv avgHsv = new Hsv();
            MCvScalar scr2 = new MCvScalar();
            node.Image.Convert<Hsv, Byte>().AvgSdv(out avgHsv, out scr2, node.AttentionMask);

            node.averageBgr = avgBgr;
            node.averageHsv = avgHsv;
        }
        /// <summary>
        /// LocateCards works by analyzing the contours in the image. 
        /// For instance, the Diamond in Set is a polygon with exactly 4 vertices. 
        /// The Oval has no such features yet. 
        /// The Squiggle is not convex, but concave and has edges in a 'right bend', instead of only 'left bends'
        /// 
        /// All these shapes are inside the contour of a (white) card, which is a rounded square. 
        /// Cards may also be the (only) exterior boundaries
        /// </summary>
        /// <param name="table">An image displaying the table with the Set cards</param>
        /// <returns>A dict locating which cards are present where in the image</returns>
        public Dictionary<Card, Point> LocateCards(Image<Bgr, Byte> table, Settings settings)
        {
            classifier = new BgrHsvClassifier();
            classifier.Train();

            #region process image
            //Convert the image to grayscale and filter out the noise
            Image<Gray, Byte> gray = table.Convert<Gray, Byte>();

            Gray cannyThreshold = new Gray(50); //180
            Gray cannyThresholdLinking = new Gray(30); //120
            Gray circleAccumulatorThreshold = new Gray(100); //120
            #region old
                    Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);
            if (settings.debuglevel >= 3)
            {
                ImageViewer.Show(cannyEdges, "cannyEdges before Closing");
            }
            #endregion
            //#region new
            //Image<Gray, Byte> thresholded = new Image<Gray, byte>(gray.Size);
            //CvInvoke.cvAdaptiveThreshold(gray.Ptr, thresholded.Ptr,
            //    255,
            //    ADAPTIVE_THRESHOLD_TYPE.CV_ADAPTIVE_THRESH_GAUSSIAN_C,
            //    THRESH.CV_THRESH_BINARY_INV, 9, 5);
            //StructuringElementEx el1 = new StructuringElementEx(3, 3, 1, 1, CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
            //thresholded = thresholded.Erode(1);//thresholded.MorphologyEx(el1, CV_MORPH_OP.CV_MOP_CLOSE, 1);//
            //Image<Gray, Byte> cannyEdges = thresholded;//.Canny(new Gray(1), new Gray(10));
            //#endregion

            //StructuringElementEx el = new StructuringElementEx(5, 5, 2, 2, CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
            StructuringElementEx el = new StructuringElementEx(3, 3, 1, 1, CV_ELEMENT_SHAPE.CV_SHAPE_RECT);
            cannyEdges = cannyEdges.MorphologyEx(el, CV_MORPH_OP.CV_MOP_CLOSE, 1);
            if (settings.debuglevel >= 3)
            {
                ImageViewer.Show(cannyEdges, "cannyEdges after Closing");
            }
            #endregion

            Contour<Point> contours = cannyEdges.FindContours(
                CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, //was CV_CHAIN_APPROX_SIMPLE
                RETR_TYPE.CV_RETR_TREE);

            ContourNode tree = new ContourNode(contours);

            FilterTree(tree);
            #region debug
            if (settings.debuglevel >= 3)
            {
                var debug = table.Clone();
                DrawContours(tree, debug);
                ImageViewer.Show(debug, "Contours after filtering");
            }
            #endregion

            AssignShapes(tree);
            AssignImages(tree, table, true);
            #region debug
            if (settings.debuglevel >= 3)
            {
                var debug1 = table.Clone();
                DrawContours(tree, debug1);
                ImageViewer.Show(debug1);
            }
            #endregion

            FilterTree(tree);

            #region debug
            if (settings.debuglevel >= 3)
            {
                var debug2 = table.Clone();
                DrawContours(tree, debug2);
                ImageViewer.Show(debug2);
            }
            #endregion

            AssignColors(tree, table, settings);

            #region debug
            if (settings.debuglevel >= 3)
            {
                TreeViz.VizualizeTree(tree);
            }
            #endregion

            AssignFills(tree);

            Dictionary<Card, Point> cardlocs = new Dictionary<Card, Point>();
            foreach (KeyValuePair<Card, ContourNode> pair in GiveCards(tree))
            {
                ContourNode node = pair.Value;
                Card card = pair.Key;

                PointF fcenter = node.Contour.GetMinAreaRect().center;
                Point center = new Point((int)fcenter.X, (int)fcenter.Y);

                cardlocs.Add(card, center);
            }

            #region debug
            if (settings.debuglevel >= 1)
            {
                TreeViz.VizualizeTree(tree);
            }
            if (settings.debuglevel >= 2)
            {
                DrawContours(tree, table);
                ImageViewer.Show(table);
            }
            #endregion
            return cardlocs;
        }