/// <summary> /// Event callback for the Clear Screen event generatead by the VideoProcessor /// </summary> private void VideoProcessor_ClearScreen(object sender, VideoProcessor.ClearScreenEventArgs e) { log.Debug("Detected Level Clear"); Image <Gray, byte> grayscaleFrame = e.currentFrame.Mat.ToImage <Gray, byte>().Resize(640, 480, Inter.Cubic); //e.currentFrame.Save("clearmatch_" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".png"); Dictionary <String, bool> events = new Dictionary <String, bool> { { "worldrecord", false }, { "firstclear", false }, }; List <Rectangle> boundaries = new List <Rectangle>(); foreach (EventTemplate tmpl in clearTemplates) { if (events[tmpl.eventType]) { continue; } Point loc = tmpl.getLocation(grayscaleFrame); if (!loc.IsEmpty) { events[tmpl.eventType] = true; boundaries.Add(ImageLibrary.ChangeSize(new Rectangle(loc.X, loc.Y, tmpl.template.Width, tmpl.template.Height), grayscaleFrame.Size, e.currentFrame.Size)); previewer.SetLastMatch(e.currentFrame, boundaries.ToArray()); } } foreach (var evt in events) { if (evt.Value) { log.Info(String.Format("Detected {0}.", evt.Key)); SMMServer.BroadcastEvent(evt.Key); } } if (Properties.Settings.Default.WarpWorldEnabled) { WarpWorld?.win(); } // Read time from screen string clearTime = OCRLibrary.GetClearTimeFromFrame(e.currentFrame, e.commentsEnabled); SMMServer.BroadcastDataEvent("clear", clearTime); }
/// <summary> /// Event Callback for the Black Screen event generated by the VideoProcessor /// </summary> private void VideoProcessor_BlackScreen(object sender, VideoProcessor.VideoEventArgs e) { log.Debug("Detected a black screen"); BeginInvoke((MethodInvoker)(() => processingLabel.Text = "Processing black screen...")); // Is this a new level? Image <Bgr, byte> frame = e.frameBuffer[e.frameBuffer.Length - 5]; double imageMatchPercent = ImageLibrary.CompareImages(frame, levelSelectScreen); if (imageMatchPercent > 0.94) { log.Info("Detected new level."); previewer.SetLastMatch(frame, new Rectangle[] { levelCodeArea, creatorNameArea, levelTitleArea }); BeginInvoke((MethodInvoker)(() => processingLabel.Text = "Processing level screen...")); Level level = getLevelFromCurrentFrame(frame); writeLevelToFile(level); SMMServer.BroadcastLevel(level); BeginInvoke((MethodInvoker)(() => ocrTextBox.Text = level.code + " | " + level.author + " | " + level.name)); BeginInvoke((MethodInvoker)(() => processingLabel.Text = "")); } else { // Not a new level, see if we can detect a template. Dictionary <String, bool> events = new Dictionary <String, bool> { { "death", false }, { "restart", false }, { "exit", false }, }; BeginInvoke((MethodInvoker)(() => processingLabel.Text = "Processing events...")); foreach (Image <Bgr, byte> f in e.frameBuffer) { Image <Gray, byte> grayscaleFrame = f.Mat.ToImage <Gray, byte>().Resize(640, 480, Inter.Cubic); //grayscaleFrame.Save("frame_" + DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".png"); // XXX: Useful for debugging template false-negatives, and for getting templates List <Rectangle> boundaries = new List <Rectangle>(); foreach (EventTemplate tmpl in templates) { if (events[tmpl.eventType]) { continue; } Point loc = tmpl.getLocation(grayscaleFrame); if (!loc.IsEmpty) { events[tmpl.eventType] = true; boundaries.Add(ImageLibrary.ChangeSize(new Rectangle(loc.X, loc.Y, tmpl.template.Width, tmpl.template.Height), grayscaleFrame.Size, f.Size)); previewer.SetLastMatch(f, boundaries.ToArray()); } } } BeginInvoke((MethodInvoker)(() => processingLabel.Text = "")); foreach (var evt in events) { if (evt.Value) { log.Info(String.Format("Detected {0}.", evt.Key)); SMMServer.BroadcastEvent(evt.Key); } } } }
private void previewMatch(object sender, VideoProcessor.TemplateMatchEventArgs e) { var boundary = ImageLibrary.ChangeSize(new Rectangle(e.location, e.template.size), processor.TEMPLATE_FRAME_SIZE, processor.frameSize); previewer.SetLastMatch(e.frame, new Rectangle[] { boundary }); }