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(); })); } }