Add the Bitmap Comparison with CRC32 hashing
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run

This commit is contained in:
Namhyeon Go 2024-09-19 03:29:43 +09:00
parent 12ce97c385
commit 0742f17f2a
4 changed files with 47 additions and 19 deletions

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Hashing;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
@ -14,6 +15,7 @@ using System.Windows.Forms;
using System.Linq;
using Tesseract;
using WelsonJS.Service;
using System.Security.Cryptography;
public class ScreenMatch
{
@ -114,12 +116,12 @@ public class ScreenMatch
private List<string> _params = new List<string>();
private bool isSearchFromEnd = false;
private bool isSaveToFile = false;
private bool isUseSampleClipboard = false;
private bool isUseSampleOCR = false;
private Size sampleSize;
private int sampleAdjustX = 0;
private int sampleAdjustY = 0;
private int sampleAdjustX;
private int sampleAdjustY;
private List<string> sampleAny;
private List<string> sampleClipboard;
private List<string> sampleOcr;
private List<string> sampleNodup;
private Size sampleNodupSize;
private Queue<Bitmap> sampleOutdated;
@ -133,13 +135,20 @@ public class ScreenMatch
templateDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_templates");
outputDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_captured");
templateImages = new List<Bitmap>();
// Initialize variables for sampling process
sampleSize = new Size
{
Width = 128,
Height = 128
};
sampleAdjustX = 0;
sampleAdjustY = 0;
sampleAny = new List<string>();
sampleClipboard = new List<string>();
sampleOcr = new List<string>();
sampleNodup = new List<string>();
sampleNodupSize = new Size
{
Width = 128,
@ -212,8 +221,7 @@ public class ScreenMatch
case "sample_clipboard":
{
isUseSampleClipboard = true;
this.parent.Log($"Use Clipboard within a {sampleSize.Width}x{sampleSize.Height} pixel range around specific coordinates.");
sampleClipboard = new List<string>(config_value.Split(':'));
break;
}
@ -221,8 +229,7 @@ public class ScreenMatch
{
tesseractDataPath = Path.Combine(workingDirectory, "app/assets/tessdata_best");
tesseractLanguage = "eng";
isUseSampleOCR = true;
this.parent.Log($"Use OCR within a {sampleSize.Width}x{sampleSize.Height} pixel range around specific coordinates.");
sampleOcr = new List<string>(config_value.Split(':'));
break;
}
@ -395,7 +402,7 @@ public class ScreenMatch
}
List<Point> matchPositions = FindTemplate(_mainImage, (Bitmap)image.Clone());
matchPositions.ForEach((matchPosition) =>
foreach (Point matchPosition in matchPositions)
{
try
{
@ -409,12 +416,14 @@ public class ScreenMatch
Position = matchPosition,
Text = text
});
break; // Only one
}
catch (Exception ex)
{
parent.Log($"Ignore the match. {ex.Message}");
}
});
}
}
if (results.Count > 0)
@ -431,7 +440,7 @@ public class ScreenMatch
return results;
}
public Bitmap cropBitmap(Bitmap bitmap, Point matchPosition, Size templateSize, Size sampleSize, int dx = 0, int dy = 0)
public Bitmap CropBitmap(Bitmap bitmap, Point matchPosition, Size templateSize, Size sampleSize, int dx = 0, int dy = 0)
{
// Adjust coordinates to the center
int x = matchPosition.X + (templateSize.Width / 2);
@ -464,14 +473,15 @@ public class ScreenMatch
string text = "";
// Crop image
Bitmap croppedBitmap = cropBitmap(bitmap, matchPosition, templateSize, sampleSize, sampleAdjustX, sampleAdjustY);
Bitmap croppedBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleSize, sampleAdjustX, sampleAdjustY);
// Save to the outdated samples
if (sampleNodup.Contains(templateName))
{
Bitmap croppedNodupBitmap = cropBitmap(bitmap, matchPosition, templateSize, sampleNodupSize);
int bitmapHash = croppedNodupBitmap.GetHashCode();
bool bitmapExists = sampleOutdated.Any(x => x.GetHashCode() == bitmapHash);
Bitmap croppedNodupBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleNodupSize);
uint bitmapCrc32 = ComputeBitmapCrc32(croppedNodupBitmap);
parent.Log($"bitmapCrc32: {bitmapCrc32}");
bool bitmapExists = sampleOutdated.Any(x => ComputeBitmapCrc32(x) == bitmapCrc32);
if (bitmapExists)
{
throw new InvalidOperationException($"This may be a duplicate request. {templateName}");
@ -484,7 +494,7 @@ public class ScreenMatch
}
// if use Clipboard
if (isUseSampleClipboard)
if (sampleClipboard.Contains(templateName))
{
Thread th = new Thread(new ThreadStart(() =>
{
@ -503,7 +513,7 @@ public class ScreenMatch
}
// if use OCR
if (isUseSampleOCR)
if (sampleOcr.Contains(templateName))
{
try
{
@ -755,4 +765,18 @@ public class ScreenMatch
return binaryImage;
}
private uint ComputeBitmapCrc32(Bitmap bitmap)
{
using (MemoryStream ms = new MemoryStream())
{
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] bitmapBytes = ms.ToArray();
Crc32 crc32 = new Crc32();
crc32.Append(bitmapBytes);
return BitConverter.ToUInt32(crc32.GetCurrentHash(), 0);
}
}
}

View File

@ -142,6 +142,9 @@
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.8.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Hashing, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Hashing.8.0.0\lib\net462\System.IO.Hashing.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>

View File

@ -15,6 +15,7 @@
<package id="RestSharp" version="112.0.0" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Diagnostics.DiagnosticSource" version="8.0.1" targetFramework="net48" />
<package id="System.IO.Hashing" version="8.0.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Net.Http.WinHttpHandler" version="8.0.2" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />

View File

@ -13,7 +13,7 @@ DISABLE_SCREEN_TIME=true
DISABLE_FILE_MONITOR=true
; window or screen
SCREEN_TIME_MODE=screen
; backward,save,sample_ocr,sample_clipboard,sample_width=128,sample_height=128,sample_adjust_x=0,sample_adjust_y=0,sample_only=button.png:message.png,sample_nodup=message.png,process_name=notepad.exe
; backward,save,sample_width=128,sample_height=128,sample_adjust_x=0,sample_adjust_y=0,sample_any=button.png:message.png:like.png,sample_ocr=like.png,sample_clipboard=button.png,sample_nodup=message.png,process_name=notepad.exe
SCREEN_TIME_PARAMS=
; default: http://localhost:50051
GRPC_HOST=http://localhost:50051