Ejemplo n.º 1
0
        private void Worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            Image image   = (Image)e.Argument;
            var   minSize = new Size(3840, 2160);
            Size  newSize;

            if (image.Width < minSize.Width || image.Height < minSize.Height)
            {
                var ratio = Math.Max((double)minSize.Width / image.Width, (double)minSize.Height / image.Height);
                newSize = new Size((int)(ratio * image.Width), (int)(ratio * image.Height));
            }
            else
            {
                newSize = image.Size;
            }
            var newRect = new Rectangle(Point.Empty, newSize);

            Emgu.CV.Image <Emgu.CV.Structure.Bgr, byte> cvImage;
            using (var bitmap = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format24bppRgb)) {
                using (var graphics = Graphics.FromImage(bitmap)) {
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode      = SmoothingMode.HighQuality;
                    graphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;

                    using (var wrapMode = new ImageAttributes()) {
                        wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                        graphics.DrawImage(image, newRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                    }
                }

                Invoke(new Action(() => {
                    if (screenshotViewer == null)
                    {
                        screenshotViewer = new ScreenshotViewer(this)
                        {
                            Top = Top, Left = Right
                        }
                    }
                    ;
                    screenshotViewer.SetImage(new Bitmap(bitmap));
                    screenshotViewer.Show();
                }));

                var data   = bitmap.LockBits(newRect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                var nBytes = data.Stride * data.Height;
                cvImage = new Emgu.CV.Image <Emgu.CV.Structure.Bgr, byte>(newSize);
                unsafe {
                    Buffer.MemoryCopy(data.Scan0.ToPointer(), cvImage.Mat.DataPointer.ToPointer(), nBytes, nBytes);
                }
                bitmap.UnlockBits(data);
            }

            if (sift == null)
            {
                sift = new Emgu.CV.Features2D.SIFT(edgeThreshold: 25, sigma: 1.2);
            }
            if (matcher == null)
            {
                var use_bf = true;
                if (use_bf)
                {
                    matcher = new Emgu.CV.Features2D.BFMatcher(Emgu.CV.Features2D.DistanceType.L2);
                }
                else
                {
                    matcher = new Emgu.CV.Features2D.FlannBasedMatcher(new Emgu.CV.Flann.KdTreeIndexParams(5), new Emgu.CV.Flann.SearchParams());
                }
            }

            if (heroDescriptors == null)
            {
                Invoke(new Action(() => {
                    screenshotViewer.SetProgress(Stage.LoadingData);
                }));
                heroDescriptors   = loadDescriptors("portraits.zip");
                bgnameDescriptors = loadDescriptors("bgnames.zip");
            }

            int nTotal   = heroDescriptors.Count + bgnameDescriptors.Count;
            int nCurrent = 0;

            using (var kp = new Emgu.CV.Util.VectorOfKeyPoint())
                using (var des = new Emgu.CV.Mat()) {
                    Invoke(new Action(() => {
                        screenshotViewer.SetProgress(Stage.ProcessingImage);
                    }));
                    sift.DetectAndCompute(cvImage, null, kp, des, false);
                    cvImage.Dispose();

                    var searchResults = new List <SearchResult>();
                    Invoke(new Action(() => {
                        screenshotViewer.SetProgress(0.0);
                    }));
                    foreach (var kvp in heroDescriptors)
                    {
                        using (var vMatches = new Emgu.CV.Util.VectorOfVectorOfDMatch()) {
                            matcher.KnnMatch(kvp.Value, des, vMatches, 2);
                            const float maxdist = 0.7f;
                            var         matches = vMatches.ToArrayOfArray().Where(m => m[0].Distance < maxdist * m[1].Distance).ToList();
                            if (matches.Any())
                            {
                                searchResults.Add(new SearchResult(kvp.Key, matches, kp));
                            }
                        }
                        nCurrent++;
                        Invoke(new Action(() => {
                            screenshotViewer.SetProgress((double)nCurrent / nTotal);
                        }));
                    }
                    searchResults.Sort((a, b) => - a.Distance.CompareTo(b.Distance));
                    searchResults.RemoveAll(t => searchResults.Take(searchResults.IndexOf(t)).Select(u => u.Name).Contains(t.Name));
                    var bans_picks = searchResults.Take(16).OrderBy(t => t.Location.Y).ToList();
                    var bans       = bans_picks.Take(6).OrderBy(t => t.Location.X).ToList();
                    var picks      = bans_picks.Skip(6).OrderBy(t => t.Location.X).ToList();
                    var t1picks    = picks.Take(5).OrderBy(t => t.Location.Y).ToList();
                    var t2picks    = picks.Skip(5).OrderBy(t => t.Location.Y).ToList();

                    var bgSearchResults = new List <SearchResult>();
                    foreach (var kvp in bgnameDescriptors)
                    {
                        using (var vMatches = new Emgu.CV.Util.VectorOfVectorOfDMatch()) {
                            matcher.KnnMatch(kvp.Value, des, vMatches, 2);
                            const float maxdist = 0.7f;
                            var         matches = vMatches.ToArrayOfArray().Where(m => m[0].Distance < maxdist * m[1].Distance).ToList();
                            if (matches.Any())
                            {
                                bgSearchResults.Add(new SearchResult(kvp.Key, matches, kp));
                            }
                        }
                        nCurrent++;
                        Invoke(new Action(() => {
                            screenshotViewer.SetProgress((double)nCurrent / nTotal);
                        }));
                    }
                    var bgSearchResult = bgSearchResults.OrderBy(t => - t.Distance).First();
                    Invoke(new Action(() => {
                        screenshotViewer.SetProgress(Stage.Complete);
                        screenshotViewer.SetSearchResults(bans_picks.ToArray(), bgSearchResult);
                        c_bg.Text = bgSearchResult.Name;
                        screenshotViewer.Show();
                        Focus();
                    }));
                }
        }