Esempio n. 1
0
        /// <summary>
        /// Use Vscan to verify the current visuals (e.g. screenshot) against the given model.
        /// </summary>
        /// <param name="elementToCapture">UIElement to take a screen shot of.</param>
        /// <param name="modelFilename">Full path to model file to compare current visuals against.</param>
        /// <exception cref="ArgumentException">If modelFilename is not a valid path.</exception>
        public void CompareVisualsToModel(UIElement elementToCapture, object modelFilename)
        {
            string modelName = modelFilename as string;

            Console.WriteLine("[VisualScan]: Master is '" + modelFilename + "'.");

            EnsureRenderComplete();

            // Create vscan object.
            VScan scan = new VScan(CreateBitmap(elementToCapture));

            // Analyze Data.
            Console.WriteLine("[VisualScan]: analyzing screen capture.");
            scan.OriginalData.Analyze();
            // Compare model with image.
            Console.WriteLine("[VisualScan]: comparing against master.");
            bool result = scan.OriginalData.CompareModels(modelName);

            Console.WriteLine("[VisualScan]: " + ((result) ? "SUCCEEDED" : "FAILED"));
            if (!result)
            {
                // Dump a report of the differences.
                //
                XmlNode     xmlDiff = scan.OriginalData.ModelDifferences;
                XmlDocument xmlDoc  = new XmlDocument();
                xmlDoc.LoadXml(xmlDiff.OuterXml);
                string errorFilename = "vscan_error_" + DateTime.Now.Ticks + ".xml";
                xmlDoc.Save(errorFilename);
                throw new Exception("Visuals differ from expected, error log generated '" + errorFilename + "'.");
            }
        }
Esempio n. 2
0
        /// <summary>
        /// The scanner attemps to locate content assuming that:
        ///   contentOff is the imagaeadapter of the scene before content is shown
        ///   contentOn  is the imagaeadapter of the scene with the content shown
        /// Note: content may have a variable alpha map
        /// </summary>
        public Result Process(IImageAdapter content, IImageAdapter contentOff, IImageAdapter contentOn, double[] transformMatrix)
        {
            string paramEx = string.Empty;

            if (content == null)
            {
                paramEx = "<IImageAdapter content> ";
            }
            if (contentOff == null)
            {
                paramEx += "<IImageAdapter contentOff>";
            }
            if (contentOn == null)
            {
                paramEx += "<IImageAdapter contentOn>";
            }
            if (content == null)
            {
                paramEx += "<IImageAdapter content>";
            }
            if (transformMatrix == null)
            {
                paramEx += "<double []transformMatrix>";
            }

/*
 *                  if (transformMatrix.Length != Interpolator.TransformLength)
 *                  {
 *                      throw new Exception("Transform array length != " + Interpolator.TransformLength);
 *                  }
 */
            //sentinel
            bool         validResult = true;
            string       log         = string.Empty;
            ImageAdapter res         = GetTransformedContent(content, transformMatrix, contentOff.Width, contentOff.Height);

            // locate rec
            //  1) compute the diff image
            //  2) synthetise the transformed content
            //  3) compare with the sourceOn
            ImageComparator imageComparator = new ImageComparator();

            imageComparator.Compare(contentOn, contentOff);
            IImageAdapter imdiff = imageComparator.GetErrorDifference(ErrorDifferenceType.FilterEdge);

            // make sure there is only one descriptor and the background.
            //convert the diff image to a binary image (black-bg and white-fg)
            ImageAdapter imbinmap = new ImageAdapter(imdiff.Width, imdiff.Height);
            IColor       black    = new ColorByte(Color.Black);
            IColor       white    = new ColorByte(Color.White);

            for (int j = 0; j < imbinmap.Width; j++)
            {
                for (int i = 0; i < imbinmap.Height; i++)
                {
                    if (imdiff[j, i].Red + imdiff[j, i].Green + imdiff[j, i].Blue > 1e-6)
                    {
                        imdiff[j, i] = white;
                    }
                    else
                    {
                        imdiff[j, i] = black;
                    }
                }
            }
#if DEBUG
            ImageUtility.ToImageFile(imdiff, "bwmap.png", ImageFormat.Png);
#endif
            //Analyze the bin-diff-image
            VScan lvsc = new VScan(imdiff);
            lvsc.OriginalData.Analyze();

            //topological check
            //root nodes: either a pair of white and black descriptor
            //or a tree.
            // all further descendant must be children of the white cell

/*
 *                  int[] descriptorCounter = new int[2];
 *
 *                  //loop on the descriptors
 *                  foreach (IDescriptor desc in lvsc.OriginalData.Descriptors.ActiveDescriptors)
 *                  {
 *                      if (desc.Depth <= 1)
 *                      {
 *                          descriptorCounter[desc.Depth]++;
 *                      }
 *
 *                      Console.WriteLine("Descr " + desc.BoundingBox + "   " + desc.Depth);
 *                  }
 *
 *                  //check
 *                  int summ = descriptorCounter[0] + descriptorCounter[1];
 *                  if (summ != 2)
 *                  {
 *                      validResult = false;
 *                      if (summ == 0)
 *                      {
 *                          log = "<Fail> No top level descriptors found";
 *                      }
 *                      else
 *                      {
 *                          log = "<Fail> Too many top level descriptors found (should be two) :" + summ;
 *                      }
 *                  }
 */
            // topology is good to go, time to find the bounding box of the dynamic content
            int minx = int.MaxValue;
            int miny = int.MaxValue;
            int maxx = int.MinValue;
            int maxy = int.MinValue;
            if (validResult == true)
            {
                for (int j = 0; j < imdiff.Width; j++)
                {
                    for (int i = 0; i < imdiff.Height; i++)
                    {
                        double sum = imdiff[j, i].Blue + imdiff[j, i].Red + imdiff[j, i].Green;
                        if (sum > 1e-6)
                        {
                            if (j < minx)
                            {
                                minx = j;
                            }
                            if (i < miny)
                            {
                                miny = i;
                            }
                            if (j > maxx)
                            {
                                maxx = j;
                            }
                            if (i > maxy)
                            {
                                maxy = i;
                            }
                        }
                    }
                }

                // bounding box
                maxx -= minx;
                maxy -= miny;
                Console.WriteLine("<Target> found at " + minx + " " + miny + "  " + maxx + " " + maxy);
                ImageUtility.ToImageFile(imdiff, "Recpos.png");

                // synthetize content into contentOff
                IImageAdapter iafcomp = new ImageAdapter(contentOff.Width, contentOff.Height);
                double        dx      = minx - _imageAdapterXmin;
                double        dy      = miny - _imageAdapterYmin;

                // translate results
                for (int j = 0; j < 4; j++)
                {
                    _contentLocation[j, 0] += dx;
                    _contentLocation[j, 1] += dy;
                }

                // copy the background
                iafcomp = (IImageAdapter)contentOff.Clone();

                // add the transformed content
                for (int j = 0; j < res.Width; j++)
                {
                    for (int i = 0; i < res.Height; i++)
                    {
                        if (j + minx < iafcomp.Width && i + miny < iafcomp.Height)
                        {
                            if (res[j, i].Alpha > 0)
                            {
                                double lalp = res[j, i].Alpha;
                                int    jid  = j + minx;
                                int    iid  = i + miny;
                                IColor lvc  = iafcomp[jid, iid];
                                lvc.Red           = lalp * res[j, i].Red + (1 - lalp) * iafcomp[jid, iid].Red;
                                lvc.Green         = lalp * res[j, i].Green + (1 - lalp) * iafcomp[jid, iid].Green;
                                lvc.Blue          = lalp * res[j, i].Blue + (1 - lalp) * iafcomp[jid, iid].Blue;
                                iafcomp[jid, iid] = lvc;
                            }
                        }
                    }
                }
#if DEBUG
                ImageUtility.ToImageFile(iafcomp, "SynthGlyph.png", ImageFormat.Png);
#endif

/*
 *                      if (Tolerance != null)
 *                      {
 *                          imageComparator.Tolerance.Clear();
 *                          double x = double.NaN;
 *                          double y = double.NaN;
 *                          for(int t=0;t<Tolerance.Count;t++)
 *                          {
 *                              x = (double)Tolerance.GetKey(t);
 *                              y = (double)Tolerance[x];
 *                              imageComparator.Tolerance.Add(x,y);
 *                          }
 *                      }
 */
                validResult = imageComparator.Compare(iafcomp, contentOn);
                string toluse = "No Tolerance used - strict comparison";
                if (_tolerance != null)
                {
                    toluse = "with the given Tolerance";
                }
                if (validResult == false)
                {
                    log = "<Fail> Computed Content does not match actual content -- " + toluse;
                }
                else
                {
                    log = "<Pass>";
                }

                Console.WriteLine("Final comp pass " + validResult);
                ImageUtility.ToImageFile(imageComparator.GetErrorDifference(ErrorDifferenceType.FilterEdge), "SynthError.png");
#if DEBUG
                using (Bitmap fbmp = ImageUtility.ToBitmap(contentOn))
                {
                    using (Graphics graphics = Graphics.FromImage(fbmp))
                    {
                        using (Brush brush = new SolidBrush(Color.FromArgb(40, 255, 0, 0)))
                        {
                            graphics.FillRectangle(brush, minx, miny, maxx, maxy);
                        }
                        using (Pen pen = new Pen(Color.Red, 2))
                        {
                            graphics.DrawRectangle(pen, minx, miny, maxx, maxy);
                        }
                        using (Font fnt = new Font("Arial", 10))
                        {
                            SizeF sz = graphics.MeasureString("TL", fnt);
                            graphics.FillRectangle(Brushes.Yellow, (float)_contentLocation[0, 0], (float)_contentLocation[0, 1], sz.Width, sz.Height);
                            graphics.FillRectangle(Brushes.Yellow, (float)_contentLocation[1, 0], (float)_contentLocation[1, 1], sz.Width, sz.Height);
                            graphics.FillRectangle(Brushes.Yellow, (float)_contentLocation[2, 0], (float)_contentLocation[2, 1], sz.Width, sz.Height);
                            graphics.FillRectangle(Brushes.Yellow, (float)_contentLocation[3, 0], (float)_contentLocation[3, 1], sz.Width, sz.Height);
                            graphics.DrawString("TL", fnt, Brushes.Red, (float)_contentLocation[0, 0], (float)_contentLocation[0, 1]);
                            graphics.DrawString("TR", fnt, Brushes.Red, (float)_contentLocation[1, 0], (float)_contentLocation[1, 1]);
                            graphics.DrawString("BL", fnt, Brushes.Red, (float)_contentLocation[2, 0], (float)_contentLocation[2, 1]);
                            graphics.DrawString("BR", fnt, Brushes.Red, (float)_contentLocation[3, 0], (float)_contentLocation[3, 1]);
                        }
                        fbmp.Save("TrackMatch.png");
                    }
                }
#endif
            }
            Result dcres = new Result(validResult, log, _contentLocation);

            return(dcres);
        }