Exemple #1
0
 /// <summary>
 /// Initilize a new instance of the CardImage class
 /// </summary>
 /// <param name="image">Card Image</param>
 /// <param name="cardTitleImage">Card Title Image (Sub Image of image)</param>
 public CardImage(Guid cardId, Mat image, CardTitleImage cardTitleImage) : base(image)
 {
     _cardId         = cardId;
     _cardTitleImage = cardTitleImage;
     _angle          = cardTitleImage.Angle;
     _cardFrame      = cardTitleImage.CardFrame;
 }
Exemple #2
0
        /// <summary>
        /// Dipose Of Images
        /// </summary>
        protected override void DisposeImages()
        {
            base.DisposeImages();

            if (_cardTitleImage != null)
            {
                _cardTitleImage.Dispose();
                _cardTitleImage = null;
            }
        }
Exemple #3
0
        /// <summary>
        /// Search the Card Image For The Title And Result It As a Wrapped Class (CardTitleImage)
        /// </summary>
        internal static CardTitleImage FindBestTitleImage(Guid cardId, Image cardImage, float X, float Y, IEnumerable <CannyParam> cannyParameters, IEnumerable <double> angles)
        {
            List <CardTitleImage> potentialCardTitleImages = new List <CardTitleImage>();

            ContourCache contourCache = new ContourCache();

            using (var contours = new VectorOfVectorOfPoint())
            {
                foreach (var angle in angles)
                {
                    foreach (var cannyParameter in cannyParameters)
                    {
                        Debug.WriteLine(string.Format("Find Title Image Canny {0} Angle {1}...", cannyParameter, angle));

                        using (Mat cannyImage = cardImage.GetCannyImage(() => { return(cardImage.GetGreyImage(angle)); }, angle, cannyParameter))
                        {
                            CvInvoke.FindContours(cannyImage, contours, hierarchy: null, mode: RetrType.List, method: ChainApproxMethod.ChainApproxNone);

                            var sortedContours = new List <VectorOfPoint>();
                            for (int idx = 0; idx < contours.Size; idx++)
                            {
                                sortedContours.Add(contours[idx]);
                            }

                            double optimalAspectRatio = ((MaxTitleAspectRatio - MinTitleAspectRatio) / 2.0) + MinTitleAspectRatio;

                            // Sort Each Contour By Delta From the Optiomal Aspect Ratio, Smallest First
                            sortedContours.Sort((c1, c2) =>
                            {
                                RotatedRect rotatedRect1 = CvInvoke.MinAreaRect(c1);
                                double aspectRatio1      = (double)(rotatedRect1.Size.Height / rotatedRect1.Size.Width);

                                RotatedRect rotatedRect2 = CvInvoke.MinAreaRect(c2);
                                double aspectRatio2      = (double)(rotatedRect2.Size.Height / rotatedRect2.Size.Width);

                                double diff1 = Math.Abs(aspectRatio1 - optimalAspectRatio);
                                double diff2 = Math.Abs(aspectRatio2 - optimalAspectRatio);

                                return(diff1.CompareTo(diff2));
                            });

                            using (Mat rotatedImage = cardImage.GetRotatedImage(angle))
                            {
                                cardImage.FireImageEvent(null, cardId, cardId, ImageType.CardContoured, angle: angle, X: X, Y: Y,
                                                         contours: contours, cannyParameter: cannyParameter);

                                // Find The Contour That Matchs What A Title Should Look Like
                                foreach (VectorOfPoint countour in sortedContours)
                                {
                                    // Keep a list of contours that have been tested and don't test those again
                                    // that allows us to go through a bunch of test thresholds to determine
                                    // if they will yield new contours.
                                    if (contourCache.Contains(countour, angle))
                                    {
                                        continue;
                                    }

                                    // Store all the rotated rects that have been examined
                                    contourCache.Add(countour, angle);

                                    Mat          result = null;
                                    MTGCardFrame cardTitleType;

                                    try
                                    {
                                        Guid cardTitleId = Guid.NewGuid();

                                        if (TryFindTitle(cardId, cardTitleId, rotatedImage, angle, cannyParameter, countour, result: out result, cardTitleType: out cardTitleType))
                                        {
                                            // Wrap the Mat Found
                                            Image image = new Image(result);

                                            // Get the MTG card with the minimum Levenshtein distance for the text parsed
                                            // from the image, this will be the closet MTG card to the image
                                            var levenshteinDistanceResults = CardTitleImage.GetLowLevenshteinDistanceCards(cardId, cardTitleId, X, Y, cardTitleType, image);

                                            // Create a class from the card title image, the card title type, and the minimum levenshtien distance cards
                                            CardTitleImage cardTitleImage = new CardTitleImage(cardId, cardTitleId, result, cardTitleType, levenshteinDistanceResults, angle);

                                            // Direct Match Short Circuit
                                            if (levenshteinDistanceResults.Any(ldr => ldr.Distance < LevenshteinDistanceShortCircuit))
                                            {
                                                return(cardTitleImage);
                                            }

                                            // Add it to the potential card titles
                                            potentialCardTitleImages.Add(cardTitleImage);
                                        }
                                    }
                                    finally
                                    {
                                        if (result != null)
                                        {
                                            result.Dispose();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (potentialCardTitleImages.Count == 0)
            {
                return(null);
            }

            // Find The minimum number of character changes (the result of the Levenshtein Distance) alogorithm
            double minLevenshteinResults = potentialCardTitleImages.Min(cti => cti.LevenshteinResults.Min(lr => lr.PercentDistance));

            // Find all unique cards that have this distance
            var potentialCardNames = potentialCardTitleImages.SelectMany(cti => cti.LevenshteinResults)
                                     .Where(lr => lr.PercentDistance == minLevenshteinResults)
                                     .Select(lr => lr.Card.Name)
                                     .Distinct()
                                     .ToArray();

            if (potentialCardNames.Length == 0)
            {
                // There are no cards that match the image
                return(null);
            }
            else if (potentialCardNames.Length > 1)
            {
                // Inconclusive Results
                // There is more than one card with a low Levenshtein score that matches the images presented.
                return(null);
            }
            else
            {
                // Winner Winner Chicken Dinner
                string name = potentialCardNames[0];
                return(potentialCardTitleImages.FirstOrDefault(cti => cti.LevenshteinResults.Any(lr => lr.Card.Name.Equals(name))));
            }
        }
Exemple #4
0
        /// <summary>
        /// The Sureness that the name matches the image.
        /// </summary>
        public double GetNameSurity()
        {
            CardTitleImage cardTitleImage = GetCardTitleImage();

            return(cardTitleImage == null ? 0 : cardTitleImage.Surity);
        }
Exemple #5
0
        /// <summary>
        /// Get the Name Of the Card In This Image
        /// </summary>
        public string GetName()
        {
            CardTitleImage cardTitleImage = GetCardTitleImage();

            return(cardTitleImage == null ? null : cardTitleImage.Name);
        }