From b5af6485126b784c6a1651bd66d5800c56cf0945 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Mon, 29 Jul 2024 01:35:46 +0900 Subject: [PATCH] Some works for #124 --- WelsonJS.Toolkit/WelsonJS.Service/Program.cs | 11 +- .../WelsonJS.Service/ServiceMain.cs | 40 +++-- .../WelsonJS.Service/TemplateMatching.cs | 141 ++++++++++++++++++ .../WelsonJS.Service/WelsonJS.Service.csproj | 3 + 4 files changed, 175 insertions(+), 20 deletions(-) create mode 100644 WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs diff --git a/WelsonJS.Toolkit/WelsonJS.Service/Program.cs b/WelsonJS.Toolkit/WelsonJS.Service/Program.cs index 129b968..f7106ed 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/Program.cs @@ -1,20 +1,21 @@ using System; -using System.Collections.Generic; using System.ServiceProcess; -using System.Text; namespace WelsonJS.Service { internal static class Program { /// - /// 해당 애플리케이션의 주 진입점입니다. + /// entry point /// static void Main(string[] args) { + ServiceMain svc = new ServiceMain(); + if (Environment.UserInteractive) { - ServiceMain svc = new ServiceMain(); + Console.WriteLine("Welcome to WelsonJS Scripting Service..."); + Console.WriteLine("https://github.com/gnh1201/welsonjs"); svc.TestStartupAndStop(args); } else @@ -22,7 +23,7 @@ namespace WelsonJS.Service ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { - new ServiceMain() + svc }; ServiceBase.Run(ServicesToRun); } diff --git a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs index 90ab6c0..3841d3a 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs +++ b/WelsonJS.Toolkit/WelsonJS.Service/ServiceMain.cs @@ -32,13 +32,13 @@ namespace WelsonJS.Service { public partial class ServiceMain : ServiceBase { - private Timer timer; + private static List timers; private string workingDirectory; + private string scriptName; private string scriptFilePath; private string scriptText; - private string scriptName; private ScriptControl scriptControl; - private string logFilePath; + private readonly string logFilePath = Path.Combine(Path.GetTempPath(), "WelsonJS.Service.Log.txt"); private readonly string appName = "WelsonJS"; public ServiceMain() @@ -46,8 +46,18 @@ namespace WelsonJS.Service InitializeComponent(); // set the log file path - logFilePath = Path.Combine(Path.GetTempPath(), "WelsonJS.Service.Log.txt"); Log(appName + " Service Loaded"); + + // set timers + timers = new List(); + + // set default timer + Timer timer = new Timer + { + Interval = 60000 // 1 minute + }; + timer.Elapsed += OnElapsedTime; + timers.Add(timer); } internal void TestStartupAndStop(string[] args) @@ -128,27 +138,22 @@ namespace WelsonJS.Service { Log($"Script file not found: {scriptFilePath}"); } - - // set interval - timer = new Timer(); - timer.Interval = 60000; // 1 minute - timer.Elapsed += OnElapsedTime; - timer.Start(); + + // Start timers + timers.ForEach(timer => timer.Start()); Log(appName + " Service Started"); } protected override void OnStop() { - timer.Stop(); + // Stop timers + timers.ForEach(timer => timer.Stop()); try { Log(DispatchServiceEvent(scriptName, "stop")); - if (scriptControl != null) - { - scriptControl.Reset(); - } + scriptControl?.Reset(); } catch (Exception ex) { @@ -219,5 +224,10 @@ namespace WelsonJS.Service return arguments; } + + public string GetWorkingDirectory() + { + return workingDirectory; + } } } diff --git a/WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs b/WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs new file mode 100644 index 0000000..c7ff1f9 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Service/TemplateMatching.cs @@ -0,0 +1,141 @@ +// this is prototype code +// https://github.com/gnh1201/welsonjs +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Windows.Forms; +using WelsonJS.Service; + +public class TemplateMatching +{ + public void Test(string workingDirectory) + { + string templateFolderPath = Path.Combine(workingDirectory, "assets/img/templates"); + + // Load all template images + List templateImages = LoadTemplateImages(templateFolderPath); + + // try template matching + List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)> results = + CaptureAndMatchAllScreens(templateImages); + + // print results + foreach (var result in results) + { + Console.WriteLine($"Template: {result.FileName}, Screen: {result.ScreenNumber}, " + + $"Location: (x: {result.Location.X}, y: {result.Location.Y}), " + + $"Max Correlation: {result.MaxCorrelation}"); + } + } + + public static List LoadTemplateImages(string folderPath) + { + var templates = new List(); + var files = Directory.GetFiles(folderPath, "*.png"); + + foreach (var file in files) + { + templates.Add(new Bitmap(file)); + } + + return templates; + } + + public static List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)> + CaptureAndMatchAllScreens(List templateImages) + { + var results = new List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)>(); + + for (int i = 0; i < Screen.AllScreens.Length; i++) + { + Screen screen = Screen.AllScreens[i]; + Bitmap mainImage = CaptureScreen(screen); + + foreach (var templateImage in templateImages) + { + Point matchLocation = FindTemplate(mainImage, templateImage, out double maxCorrelation); + string templateFileName = templateImage.Tag as string; + + results.Add((templateFileName, i, matchLocation, maxCorrelation)); + } + } + + return results; + } + + public static Bitmap CaptureScreen(Screen screen) + { + Rectangle screenSize = screen.Bounds; + Bitmap bitmap = new Bitmap(screenSize.Width, screenSize.Height); + + using (Graphics g = Graphics.FromImage(bitmap)) + { + g.CopyFromScreen(screenSize.Left, screenSize.Top, 0, 0, screenSize.Size); + } + + return bitmap; + } + + public static Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation) + { + int mainWidth = mainImage.Width; + int mainHeight = mainImage.Height; + int templateWidth = templateImage.Width; + int templateHeight = templateImage.Height; + + Point bestMatch = Point.Empty; + maxCorrelation = double.MinValue; + + for (int x = 0; x <= mainWidth - templateWidth; x++) + { + for (int y = 0; y <= mainHeight - templateHeight; y++) + { + double correlation = CalculateCorrelation(mainImage, templateImage, x, y); + if (correlation > maxCorrelation) + { + maxCorrelation = correlation; + bestMatch = new Point(x, y); + } + } + } + + return bestMatch; + } + + private static double CalculateCorrelation(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY) + { + int templateWidth = templateImage.Width; + int templateHeight = templateImage.Height; + + double sumTemplate = 0; + double sumTemplateSquare = 0; + double sumMain = 0; + double sumMainSquare = 0; + double sumProduct = 0; + + for (int x = 0; x < templateWidth; x++) + { + for (int y = 0; y < templateHeight; y++) + { + Color mainPixel = mainImage.GetPixel(x + offsetX, y + offsetY); + Color templatePixel = templateImage.GetPixel(x, y); + + double mainGray = (mainPixel.R + mainPixel.G + mainPixel.B) / 3.0; + double templateGray = (templatePixel.R + templatePixel.G + templatePixel.B) / 3.0; + + sumTemplate += templateGray; + sumTemplateSquare += templateGray * templateGray; + sumMain += mainGray; + sumMainSquare += mainGray * mainGray; + sumProduct += mainGray * templateGray; + } + } + + int numPixels = templateWidth * templateHeight; + double numerator = (numPixels * sumProduct) - (sumMain * sumTemplate); + double denominator = Math.Sqrt(((numPixels * sumMainSquare) - (sumMain * sumMain)) * ((numPixels * sumTemplateSquare) - (sumTemplate * sumTemplate))); + + return denominator == 0 ? 0 : numerator / denominator; + } +} \ No newline at end of file diff --git a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj index 01e647d..4965e9c 100644 --- a/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj +++ b/WelsonJS.Toolkit/WelsonJS.Service/WelsonJS.Service.csproj @@ -83,8 +83,10 @@ + + @@ -102,6 +104,7 @@ ProjectInstaller.cs +