diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index a0a01c15..172c3c01 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -56,16 +56,16 @@
-
-
-
+
+
+
-
-
+
+
diff --git a/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs b/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
index 8736c805..4f25458c 100644
--- a/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
+++ b/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
@@ -61,14 +61,14 @@ public static class CommonExtension
public static Point GetCenterPoint(this Rect rectangle)
{
- if (rectangle == Rect.Empty) throw new ArgumentException("rectangle is empty");
+ if (rectangle == default) throw new ArgumentException("rectangle is empty");
return new Point(rectangle.X + rectangle.Width / 2, rectangle.Y + rectangle.Height / 2);
}
public static Rect Multiply(this Rect rect, double assetScale)
{
- if (rect == Rect.Empty) throw new ArgumentException("rect is empty");
+ if (rect == default) throw new ArgumentException("rect is empty");
return new Rect((int)(rect.X * assetScale), (int)(rect.Y * assetScale), (int)(rect.Width * assetScale), (int)(rect.Height * assetScale));
}
diff --git a/BetterGenshinImpact/Core/Recognition/OpenCv/FeatureMatch/FeatureMatcher.cs b/BetterGenshinImpact/Core/Recognition/OpenCv/FeatureMatch/FeatureMatcher.cs
index 446ad10f..28d57ad0 100644
--- a/BetterGenshinImpact/Core/Recognition/OpenCv/FeatureMatch/FeatureMatcher.cs
+++ b/BetterGenshinImpact/Core/Recognition/OpenCv/FeatureMatch/FeatureMatcher.cs
@@ -334,7 +334,7 @@ public class FeatureMatcher
var corners = MatchCorners(_trainKeyPoints, _trainDescriptors, queryMat, queryMatMask);
if (corners.Length == 0)
{
- return Rect.Empty;
+ return default;
}
return Cv2.BoundingRect(corners);
}
@@ -483,7 +483,7 @@ public class FeatureMatcher
var corners = KnnMatchCorners(_trainKeyPoints, _trainDescriptors, queryMat, queryMatMask);
if (corners.Length == 0)
{
- return Rect.Empty;
+ return default;
}
return Cv2.BoundingRect(corners);
}
diff --git a/BetterGenshinImpact/Core/Recognition/OpenCv/OpenCvCommonHelper.cs b/BetterGenshinImpact/Core/Recognition/OpenCv/OpenCvCommonHelper.cs
index b5d8557e..2ce6cb77 100644
--- a/BetterGenshinImpact/Core/Recognition/OpenCv/OpenCvCommonHelper.cs
+++ b/BetterGenshinImpact/Core/Recognition/OpenCv/OpenCvCommonHelper.cs
@@ -1,5 +1,8 @@
-using OpenCvSharp;
+using System;
+using System.Collections.Generic;
+using OpenCvSharp;
using System.Diagnostics;
+using System.Linq;
namespace BetterGenshinImpact.Core.Recognition.OpenCv;
@@ -7,7 +10,6 @@ public class OpenCvCommonHelper
{
///
/// 计算灰度图中某个颜色的像素个数
- /// 快速遍历方法来自于: https://blog.csdn.net/TyroneKing/article/details/129108838
///
///
///
@@ -15,57 +17,65 @@ public class OpenCvCommonHelper
public static int CountGrayMatColor(Mat mat, byte color)
{
Debug.Assert(mat.Depth() == MatType.CV_8U);
- var channels = mat.Channels();
- var nRows = mat.Rows;
- var nCols = mat.Cols * channels;
- if (mat.IsContinuous())
+ return SplitChannal(mat, m => CountGrayMatColorC1(m, color)).Sum();
+ }
+
+ private static IEnumerable SplitChannal(Mat mat, Func func)
+ {
+ if (mat.Empty()) return [];
+ if (mat.Channels() == 1)
{
- nCols *= nRows;
- nRows = 1;
+ return [func.Invoke(mat)];
}
- var sum = 0;
- unsafe
+ Mat[]? channels = null;
+ try
{
- for (var i = 0; i < nRows; i++)
- {
- var p = mat.Ptr(i);
- var b = (byte*)p.ToPointer();
- for (var j = 0; j < nCols; j++)
- if (b[j] == color)
- sum++;
- }
+ channels = mat.Split();
+ return channels.AsParallel().Select(func);
}
+ finally
+ {
+ // 释放所有分离出的通道内存
+ if (channels is not null)
+ foreach (var ch in channels)
+ ch.Dispose();
+ }
+ }
- return sum;
+ ///
+ /// 仅限单通道,统计等于color的颜色
+ ///
+ /// 矩阵
+ /// 值
+ ///
+ public static int CountGrayMatColorC1(Mat mat, byte color)
+ {
+ Debug.Assert(mat.Depth() == MatType.CV_8U);
+ Debug.Assert(mat.Channels() == 1);
+ using var dst = new Mat();
+ Cv2.Compare(mat, color, dst, CmpType.EQ);
+ return Cv2.CountNonZero(dst);
+ }
+
+ ///
+ /// 仅限单通道,统计颜色在lowColor和highColor中范围
+ ///
+ /// 矩阵
+ /// 低
+ /// 高
+ ///
+ public static int CountGrayMatColorC1(Mat mat, byte lowColor, byte highColor)
+ {
+ using var mask = new Mat();
+ // 使用InRange直接生成二值掩膜
+ Cv2.InRange(mat, new Scalar(lowColor), new Scalar(highColor), mask);
+ return Cv2.CountNonZero(mask);
}
public static int CountGrayMatColor(Mat mat, byte lowColor, byte highColor)
{
- Debug.Assert(mat.Depth() == MatType.CV_8U);
- var channels = mat.Channels();
- var nRows = mat.Rows;
- var nCols = mat.Cols * channels;
- if (mat.IsContinuous())
- {
- nCols *= nRows;
- nRows = 1;
- }
-
- var sum = 0;
- unsafe
- {
- for (var i = 0; i < nRows; i++)
- {
- var p = mat.Ptr(i);
- var b = (byte*)p.ToPointer();
- for (var j = 0; j < nCols; j++)
- if (b[j] >= lowColor && b[j] <= highColor)
- sum++;
- }
- }
-
- return sum;
+ return SplitChannal(mat, m => CountGrayMatColorC1(m, lowColor, highColor)).Sum();
}
public static Mat Threshold(Mat src, Scalar low, Scalar high)
@@ -75,7 +85,7 @@ public class OpenCvCommonHelper
Cv2.CvtColor(src, rgbMat, ColorConversionCodes.BGR2RGB);
Cv2.InRange(rgbMat, low, high, mask);
- Cv2.Threshold(mask, mask, 0, 255, ThresholdTypes.Binary); //二值化
+ // Cv2.Threshold(mask, mask, 0, 255, ThresholdTypes.Binary); //二值化 //不需要
return mask.Clone();
}
@@ -104,6 +114,6 @@ public class OpenCvCommonHelper
{
var mask = new Mat();
Cv2.InRange(src, s, s, mask);
- return 255 - mask;
+ return ~ mask;
}
}
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
index dc743a38..68bd5bb5 100644
--- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
@@ -662,7 +662,7 @@ public class AutoDomainTask : ISoloTask
while (!_ct.IsCancellationRequested)
{
var treeRect = DetectTree(CaptureToRectArea());
- if (treeRect != Rect.Empty)
+ if (treeRect != default)
{
var treeMiddleX = treeRect.X + treeRect.Width / 2;
if (treeRect.X + treeRect.Width < middleX && !_config.ShortMovement)
@@ -828,7 +828,7 @@ public class AutoDomainTask : ISoloTask
return new Rect(box.Bounds.X, box.Bounds.Y, box.Bounds.Width, box.Bounds.Height);
}
- return Rect.Empty;
+ return default;
}
private Task LockCameraToEastTask(CancellationTokenSource cts, Task moveAvatarTask)
diff --git a/BetterGenshinImpact/GameTask/AutoFight/Model/Avatar.cs b/BetterGenshinImpact/GameTask/AutoFight/Model/Avatar.cs
index 622f76b2..5fe275f9 100644
--- a/BetterGenshinImpact/GameTask/AutoFight/Model/Avatar.cs
+++ b/BetterGenshinImpact/GameTask/AutoFight/Model/Avatar.cs
@@ -299,7 +299,7 @@ public class Avatar
///
public bool IsActive(ImageRegion region)
{
- if (IndexRect == Rect.Empty)
+ if (IndexRect == default)
{
throw new Exception("IndexRect为空");
}
@@ -328,7 +328,7 @@ public class Avatar
public bool IsActiveNoIndexRect(ImageRegion region)
{
// 通过寻找右侧人物编号来判断是否出战
- if (IndexRect == Rect.Empty)
+ if (IndexRect == default)
{
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
// 剪裁出队伍区域
diff --git a/BetterGenshinImpact/GameTask/AutoFight/Model/CombatScenes.cs b/BetterGenshinImpact/GameTask/AutoFight/Model/CombatScenes.cs
index dc7d8fbf..f8bd7121 100644
--- a/BetterGenshinImpact/GameTask/AutoFight/Model/CombatScenes.cs
+++ b/BetterGenshinImpact/GameTask/AutoFight/Model/CombatScenes.cs
@@ -230,7 +230,7 @@ public class CombatScenes : IDisposable
var avatars = new Avatar[AvatarCount];
for (var i = 0; i < AvatarCount; i++)
{
- var nameRect = nameRects?[i] ?? Rect.Empty;
+ var nameRect = nameRects?[i] ?? default;
avatars[i] = new Avatar(this, names[i], i + 1, nameRect)
{
IndexRect = avatarIndexRectList[i]
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.cs
index 64f2f17c..b9612104 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.cs
@@ -99,7 +99,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
Debug.WriteLine(e);
}
- return Rect.Empty;
+ return default;
}
}
}
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
index 42f703b2..d578e128 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
@@ -63,7 +63,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
var result = blackboard.Predictor.Detect(memoryStream);
Debug.WriteLine($"YOLOv8识别: {result.Speed}");
var fishpond = new Fishpond(result, ignoreObtained: true);
- if (fishpond.FishpondRect == Rect.Empty)
+ if (fishpond.FishpondRect == default)
{
return BehaviourStatus.Running;
}
@@ -313,7 +313,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
var fishpond = new Fishpond(result, includeTarget: timeProvider.GetLocalNow() <= ignoreObtainedEndTime);
blackboard.fishpond = fishpond;
Random _rd = new();
- if (fishpond.TargetRect == null || fishpond.TargetRect == Rect.Empty)
+ if (fishpond.TargetRect == null || fishpond.TargetRect == default)
{
if (!foundTarget)
{
@@ -713,7 +713,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
//VisionContext.Instance().DrawContent.PutRect("liftingWordsAreaRect", liftingWordsAreaRect.ToRectDrawable(new Pen(Color.Cyan, 2)));
using var wordCaptureMat = new Mat(imageRegion.SrcMat, liftingWordsAreaRect);
var currentBiteWordsTips = AutoFishingImageRecognition.MatchFishBiteWords(wordCaptureMat, liftingWordsAreaRect);
- if (currentBiteWordsTips != Rect.Empty)
+ if (currentBiteWordsTips != default)
{
// VisionContext.Instance().DrawContent.PutRect("FishBiteTips",
// currentBiteWordsTips
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Blackboard.cs b/BetterGenshinImpact/GameTask/AutoFishing/Blackboard.cs
index b93c9d32..40ae7960 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Blackboard.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Blackboard.cs
@@ -52,7 +52,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
///
/// 拉条位置的识别框
///
- internal Rect fishBoxRect = Rect.Empty;
+ internal Rect fishBoxRect;
///
/// 是否正在选鱼饵界面
@@ -106,7 +106,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
abort = false;
throwRodNoTargetTimes = 0;
throwRodNoBaitFishFailures = new List();
- fishBoxRect = Rect.Empty;
+ fishBoxRect = default;
chooseBaitUIOpening = false;
chooseBaitFailures = new List();
pitchReset = true;
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Model/Fishpond.cs b/BetterGenshinImpact/GameTask/AutoFishing/Model/Fishpond.cs
index d1fcee28..ec5e7bdd 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Model/Fishpond.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Model/Fishpond.cs
@@ -115,7 +115,7 @@ public class Fishpond
{
if (Fishes.Count == 0)
{
- return Rect.Empty;
+ return default;
}
var left = int.MaxValue;
diff --git a/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs b/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs
index 3d1cc4f1..eb4533ab 100644
--- a/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoSkip/AutoTrackTask.cs
@@ -36,7 +36,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
///
/// 任务距离
///
- private Rect _missionDistanceRect = Rect.Empty;
+ private Rect _missionDistanceRect = default;
private CancellationToken _ct;
@@ -131,7 +131,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
var centerX = ra.Width / 2;
var centerY = ra.Height / 2;
var minDistance = double.MaxValue;
- var nearestRect = Rect.Empty;
+ Rect nearestRect = default;
foreach (var tpPoint in tpPointList)
{
var distanceTp = Math.Sqrt(Math.Pow(Math.Abs(tpPoint.X - centerX), 2) + Math.Pow(Math.Abs(tpPoint.Y - centerY), 2));
diff --git a/BetterGenshinImpact/GameTask/AutoSkip/ExpeditionTask.cs b/BetterGenshinImpact/GameTask/AutoSkip/ExpeditionTask.cs
index 4a4751ce..f279e64b 100644
--- a/BetterGenshinImpact/GameTask/AutoSkip/ExpeditionTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoSkip/ExpeditionTask.cs
@@ -75,7 +75,7 @@ public class ExpeditionTask
var result = CaptureAndOcr(content, new Rect(0, 0, captureRect.Width - (int)(480 * assetScale), captureRect.Height));
var rect = result.FindRectByText("探险完成");
// TODO i>1 的时候,可以通过关键词“探索派遣限制 4 / 5 ”判断是否已经派遣完成?
- if (rect != Rect.Empty)
+ if (rect != default)
{
// 点击探险完成下方的人物头像
content.CaptureRectArea.Derive(new Rect(rect.X, rect.Y + (int)(50 * assetScale), rect.Width, (int)(80 * assetScale))).Click();
@@ -83,7 +83,7 @@ public class ExpeditionTask
// 重新截图 找领取
result = CaptureAndOcr(content);
rect = result.FindRectByText("领取");
- if (rect != Rect.Empty)
+ if (rect != default)
{
using var ra = content.CaptureRectArea.Derive(rect);
ra.Click();
@@ -96,7 +96,7 @@ public class ExpeditionTask
// 选择角色
result = CaptureAndOcr(content);
rect = result.FindRectByText("选择角色");
- if (rect != Rect.Empty)
+ if (rect != default)
{
content.CaptureRectArea.Derive(rect).Click();
TaskControl.Sleep(400); // 等待动画
diff --git a/BetterGenshinImpact/GameTask/AutoSkip/Model/HangoutOption.cs b/BetterGenshinImpact/GameTask/AutoSkip/Model/HangoutOption.cs
index 8cfb1a3b..b79c8acc 100644
--- a/BetterGenshinImpact/GameTask/AutoSkip/Model/HangoutOption.cs
+++ b/BetterGenshinImpact/GameTask/AutoSkip/Model/HangoutOption.cs
@@ -23,7 +23,7 @@ public class HangoutOption : IDisposable
// 选项文字所在区域初始化
// 选项图标往上下区域扩展 2/3
- var r = Rect.Empty;
+ Rect r = default;
var captureArea = TaskContext.Instance().SystemInfo.ScaleMax1080PCaptureRect;
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
if (IconRect.Left > captureArea.Width / 2)
@@ -44,10 +44,10 @@ public class HangoutOption : IDisposable
if (r.Width < captureArea.Width / 8)
{
TaskControl.Logger.LogError("自动邀约:选项文字区域过小 {Rect}", TextRect);
- r = Rect.Empty;
+ r = default;
}
- if (r != Rect.Empty)
+ if (r != default)
{
if (iconRect.Prev is ImageRegion prev)
{
diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
index 44572a35..3f44de8a 100644
--- a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
@@ -660,7 +660,7 @@ public class TpTask(CancellationToken ct)
if (mapScaleButtonRa.IsExist())
{
rect = BigMap.Instance.GetBigMapRectByFeatureMatch(ra.SrcGreyMat);
- if (rect == Rect.Empty)
+ if (rect == default)
{
// 滚轮调整后再次识别
Simulation.SendInput.Mouse.VerticalScroll(2);
@@ -674,7 +674,7 @@ public class TpTask(CancellationToken ct)
}
}, TimeSpan.FromMilliseconds(500), 5);
- if (rect == Rect.Empty)
+ if (rect == default)
{
throw new InvalidOperationException("多次重试后,识别大地图位置失败");
}
diff --git a/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs b/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs
index 28c18e0e..5b0b2d1c 100644
--- a/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs
+++ b/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs
@@ -53,7 +53,7 @@ public class BigMap : Singleton
catch
{
Debug.WriteLine("Feature Match Failed");
- return Rect.Empty;
+ return default;
}
}
}
diff --git a/BetterGenshinImpact/GameTask/Common/Map/Camera/CameraOrientationFromLimint.cs b/BetterGenshinImpact/GameTask/Common/Map/Camera/CameraOrientationFromLimint.cs
index 19521e71..e1b03e6c 100644
--- a/BetterGenshinImpact/GameTask/Common/Map/Camera/CameraOrientationFromLimint.cs
+++ b/BetterGenshinImpact/GameTask/Common/Map/Camera/CameraOrientationFromLimint.cs
@@ -103,8 +103,8 @@ public class CameraOrientationFromLimint
private void GeneratePoints()
{
- Mat r = new Mat(1, rLength, MatType.CV_32F, LinearSpaced(tplInnRad, tplOutRad, rLength));
- Mat theta = new Mat(thetaLength, 1, MatType.CV_32F, LinearSpaced(0, 360, thetaLength, false));
+ Mat r = Mat.FromPixelData(1, rLength, MatType.CV_32F, LinearSpaced(tplInnRad, tplOutRad, rLength));
+ Mat theta =Mat.FromPixelData(thetaLength, 1, MatType.CV_32F, LinearSpaced(0, 360, thetaLength, false));
Mat rMat = r.Repeat(thetaLength, 1);
Mat thetaMat = theta.Repeat(1, rLength);
rotationRemapDataX = new Mat();
@@ -117,13 +117,13 @@ public class CameraOrientationFromLimint
private void CreateAlphaMask()
{
var values = LinearSpaced(tplInnRad, tplOutRad, rLength);
- var alphaMask1Row = new Mat(1, rLength, MatType.CV_32F, values.Select(v =>
+ var alphaMask1Row = Mat.FromPixelData(1, rLength, MatType.CV_32F, values.Select(v =>
{
var index = Array.BinarySearch(alphaParams1, v);
return (float)(229 + (index < 0 ? ~index : index));
}).ToArray());
alphaMask1 = alphaMask1Row.Repeat(thetaLength, 1);
- var alphaMask2Row = new Mat(1, rLength, MatType.CV_32F, values.Select(v => (float)(111.7 + 1.836 * v)).ToArray());
+ var alphaMask2Row = Mat.FromPixelData(1, rLength, MatType.CV_32F, values.Select(v => (float)(111.7 + 1.836 * v)).ToArray());
alphaMask2 = alphaMask2Row.Repeat(thetaLength, 1);
}
diff --git a/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs b/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs
index 8128e760..11732b4e 100644
--- a/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs
+++ b/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs
@@ -29,7 +29,7 @@ public class CharacterOrientation
if (contours.Length > 0)
{
- var maxRect = Rect.Empty;
+ Rect maxRect = default;
var maxIndex = 0;
for (int i = 0; i < contours.Length; i++)
{
diff --git a/BetterGenshinImpact/GameTask/Model/Area/ImageRegion.cs b/BetterGenshinImpact/GameTask/Model/Area/ImageRegion.cs
index f32816b6..44184919 100644
--- a/BetterGenshinImpact/GameTask/Model/Area/ImageRegion.cs
+++ b/BetterGenshinImpact/GameTask/Model/Area/ImageRegion.cs
@@ -71,7 +71,8 @@ public class ImageRegion : Region
}
}
- public ImageRegion(Mat mat, int x, int y, Region? owner = null, INodeConverter? converter = null, DrawContent? drawContent = null) : base(x, y, mat.Width, mat.Height, owner, converter, drawContent)
+ public ImageRegion(Mat mat, int x, int y, Region? owner = null, INodeConverter? converter = null,
+ DrawContent? drawContent = null) : base(x, y, mat.Width, mat.Height, owner, converter, drawContent)
{
_srcMat = mat;
}
@@ -160,21 +161,27 @@ public class ImageRegion : Region
throw new Exception($"[TemplateMatch]识别对象{ro.Name}的模板图片不能为null");
}
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
// TODO roi 是可以加缓存的
- if (!(0 <= ro.RegionOfInterest.X && 0 <= ro.RegionOfInterest.Width && ro.RegionOfInterest.X + ro.RegionOfInterest.Width <= roi.Cols
- && 0 <= ro.RegionOfInterest.Y && 0 <= ro.RegionOfInterest.Height && ro.RegionOfInterest.Y + ro.RegionOfInterest.Height <= roi.Rows))
+ if (!(0 <= ro.RegionOfInterest.X && 0 <= ro.RegionOfInterest.Width &&
+ ro.RegionOfInterest.X + ro.RegionOfInterest.Width <= roi.Cols
+ && 0 <= ro.RegionOfInterest.Y && 0 <= ro.RegionOfInterest.Height &&
+ ro.RegionOfInterest.Y + ro.RegionOfInterest.Height <= roi.Rows))
{
- TaskControl.Logger.LogError("在图像{W1}x{H1}中查找模板,名称:{Name},ROI位置{X2}x{Y2},区域{H2}x{W2},边界溢出!", roi.Width, roi.Height, ro.Name, ro.RegionOfInterest.X, ro.RegionOfInterest.Y, ro.RegionOfInterest.Width, ro.RegionOfInterest.Height);
+ TaskControl.Logger.LogError("在图像{W1}x{H1}中查找模板,名称:{Name},ROI位置{X2}x{Y2},区域{H2}x{W2},边界溢出!",
+ roi.Width, roi.Height, ro.Name, ro.RegionOfInterest.X, ro.RegionOfInterest.Y,
+ ro.RegionOfInterest.Width, ro.RegionOfInterest.Height);
}
+
roi = new Mat(roi, ro.RegionOfInterest);
}
var p = MatchTemplateHelper.MatchTemplate(roi, template, ro.TemplateMatchMode, ro.MaskMat, ro.Threshold);
if (p != new Point())
{
- var newRa = Derive(p.X + ro.RegionOfInterest.X, p.Y + ro.RegionOfInterest.Y, template.Width, template.Height);
+ var newRa = Derive(p.X + ro.RegionOfInterest.X, p.Y + ro.RegionOfInterest.Y, template.Width,
+ template.Height);
if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name))
{
newRa.DrawSelf(ro.Name, ro.DrawOnWindowPen);
@@ -202,7 +209,7 @@ public class ImageRegion : Region
}
var roi = SrcGreyMat;
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
roi = new Mat(SrcGreyMat, ro.RegionOfInterest);
}
@@ -256,7 +263,9 @@ public class ImageRegion : Region
if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name))
{
// 画出OCR识别到的区域
- var drawList = result.Regions.Select(item => this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name, ro.DrawOnWindowPen)).ToList();
+ var drawList = result.Regions.Select(item =>
+ this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name,
+ ro.DrawOnWindowPen)).ToList();
drawContent.PutOrRemoveRectList(ro.Name, drawList);
}
@@ -274,27 +283,30 @@ public class ImageRegion : Region
return new Region();
}
}
- else if (RecognitionTypes.Ocr.Equals(ro.RecognitionType) || RecognitionTypes.ColorRangeAndOcr.Equals(ro.RecognitionType))
+ else if (RecognitionTypes.Ocr.Equals(ro.RecognitionType) ||
+ RecognitionTypes.ColorRangeAndOcr.Equals(ro.RecognitionType))
{
Mat roi;
if (RecognitionTypes.ColorRangeAndOcr.Equals(ro.RecognitionType))
{
roi = SrcMat;
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
roi = new Mat(SrcMat, ro.RegionOfInterest);
}
+
roi = roi.Clone();
if (ro.ColorConversionCode != ColorConversionCodes.BGRA2BGR)
{
Cv2.CvtColor(roi, roi, ro.ColorConversionCode);
}
+
Cv2.InRange(roi, ro.LowerColor, ro.UpperColor, roi);
}
else
{
roi = SrcGreyMat;
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
roi = new Mat(SrcGreyMat, ro.RegionOfInterest);
}
@@ -308,10 +320,13 @@ public class ImageRegion : Region
if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name))
{
// 画出OCR识别到的区域
- var drawList = result.Regions.Select(item => this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name, ro.DrawOnWindowPen)).ToList();
+ var drawList = result.Regions.Select(item =>
+ this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name,
+ ro.DrawOnWindowPen)).ToList();
drawContent.PutOrRemoveRectList(ro.Name, drawList);
}
- if (ro.RegionOfInterest != Rect.Empty)
+
+ if (ro.RegionOfInterest != default)
{
var newRa = Derive(ro.RegionOfInterest);
newRa.Text = text;
@@ -354,7 +369,8 @@ public class ImageRegion : Region
/// 失败后做什么
/// 无内嵌图片的 RectArea List
///
- public List FindMulti(RecognitionObject ro, Action>? successAction = null, Action? failAction = null)
+ public List FindMulti(RecognitionObject ro, Action>? successAction = null,
+ Action? failAction = null)
{
if (!HasImage())
{
@@ -387,19 +403,21 @@ public class ImageRegion : Region
throw new Exception($"[TemplateMatch]识别对象{ro.Name}的模板图片不能为null");
}
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
roi = new Mat(roi, ro.RegionOfInterest);
}
- var rectList = MatchTemplateHelper.MatchOnePicForOnePic(roi, template, ro.TemplateMatchMode, ro.MaskMat, ro.Threshold);
+ var rectList =
+ MatchTemplateHelper.MatchOnePicForOnePic(roi, template, ro.TemplateMatchMode, ro.MaskMat, ro.Threshold);
if (rectList.Count > 0)
{
var resRaList = rectList.Select(r => this.Derive(r + ro.RegionOfInterest.Location)).ToList();
if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name))
{
- VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, resRaList.Select(ra => ra.SelfToRectDrawable(ro.Name)).ToList());
+ VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name,
+ resRaList.Select(ra => ra.SelfToRectDrawable(ro.Name)).ToList());
}
successAction?.Invoke(resRaList);
@@ -419,7 +437,7 @@ public class ImageRegion : Region
else if (RecognitionTypes.Ocr.Equals(ro.RecognitionType))
{
var roi = SrcGreyMat;
- if (ro.RegionOfInterest != Rect.Empty)
+ if (ro.RegionOfInterest != default)
{
roi = new Mat(SrcGreyMat, ro.RegionOfInterest);
}
@@ -437,7 +455,9 @@ public class ImageRegion : Region
if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name))
{
// 画出OCR识别到的区域
- var drawList = result.Regions.Select(item => this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name, ro.DrawOnWindowPen)).ToList();
+ var drawList = result.Regions.Select(item =>
+ this.ToRectDrawable(item.Rect.BoundingRect() + ro.RegionOfInterest.Location, ro.Name,
+ ro.DrawOnWindowPen)).ToList();
VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, drawList);
}
@@ -467,4 +487,4 @@ public class ImageRegion : Region
_srcMat?.Dispose();
_srcBitmap?.Dispose();
}
-}
+}
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs b/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs
index 1d105ed0..ae4a5281 100644
--- a/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs
+++ b/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs
@@ -157,7 +157,7 @@ public class TestTrigger : ITaskTrigger
if (contours.Length > 0)
{
- var maxRect = Rect.Empty;
+ Rect maxRect = default;
var maxIndex = 0;
for (int i = 0; i < contours.Length; i++)
{
diff --git a/Fischless.GameCapture/BitBlt/BitBltCapture.cs b/Fischless.GameCapture/BitBlt/BitBltCapture.cs
index b06bfb50..99384c8b 100644
--- a/Fischless.GameCapture/BitBlt/BitBltCapture.cs
+++ b/Fischless.GameCapture/BitBlt/BitBltCapture.cs
@@ -46,13 +46,28 @@ public class BitBltCapture : IGameCapture
Gdi32.SafeHBITMAP hBitmap = Gdi32.SafeHBITMAP.Null;
try
{
- User32.GetClientRect(_hWnd, out var windowRect);
- int x = 0, y = 0;
+ if (!User32.GetClientRect(_hWnd, out var windowRect))
+ {
+ Debug.Fail("Failed to get client rectangle");
+ return null;
+ }
+
var width = windowRect.right - windowRect.left;
var height = windowRect.bottom - windowRect.top;
hdcSrc = User32.GetDC(_hWnd == IntPtr.Zero ? User32.GetDesktopWindow() : _hWnd);
+ if (hdcSrc.IsInvalid)
+ {
+ Debug.WriteLine($"Failed to get DC for {_hWnd}");
+ return null;
+ }
+
hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
+ if (hdcSrc.IsInvalid)
+ {
+ Debug.Fail("Failed to create CompatibleDC");
+ return null;
+ }
var bmi = new Gdi32.BITMAPINFO
{
@@ -68,18 +83,32 @@ public class BitBltCapture : IGameCapture
}
};
- nint bits = 0;
- hBitmap = Gdi32.CreateDIBSection(hdcDest, bmi, Gdi32.DIBColorMode.DIB_RGB_COLORS, out bits, IntPtr.Zero, 0);
+ hBitmap = Gdi32.CreateDIBSection(hdcDest, bmi, Gdi32.DIBColorMode.DIB_RGB_COLORS, out var bits,
+ IntPtr.Zero,
+ 0);
+ if (hBitmap.IsInvalid || bits == 0)
+ {
+ Debug.WriteLine($"Failed to create dIB section for {_hWnd}");
+ return null;
+ }
+
var oldBitmap = Gdi32.SelectObject(hdcDest, hBitmap);
+ if (oldBitmap.IsNull)
+ {
+ return null;
+ }
- Gdi32.StretchBlt(hdcDest, 0, 0, width, height, hdcSrc, x, y, width, height, Gdi32.RasterOperationMode.SRCCOPY);
+ if (!Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.RasterOperationMode.SRCCOPY))
+ {
+ Debug.WriteLine($"BitBlt failed for {_hWnd}");
+ return null;
+ }
- var mat = new Mat(height, width, MatType.CV_8UC4, bits);
+ using var mat = Mat.FromPixelData(height, width, MatType.CV_8UC4, bits);
Gdi32.SelectObject(hdcDest, oldBitmap);
-
if (!mat.Empty())
{
- Mat bgrMat = new Mat();
+ var bgrMat = new Mat();
Cv2.CvtColor(mat, bgrMat, ColorConversionCodes.BGRA2BGR);
return bgrMat;
}
@@ -95,12 +124,12 @@ public class BitBltCapture : IGameCapture
}
finally
{
- if (hBitmap != Gdi32.SafeHBITMAP.Null)
+ if (!hBitmap.IsNull)
{
Gdi32.DeleteObject(hBitmap);
}
- if (hdcDest != Gdi32.SafeHDC.Null)
+ if (!hdcDest.IsNull)
{
Gdi32.DeleteDC(hdcDest);
}
diff --git a/Fischless.GameCapture/Fischless.GameCapture.csproj b/Fischless.GameCapture/Fischless.GameCapture.csproj
index 1e832bb0..9af61e65 100644
--- a/Fischless.GameCapture/Fischless.GameCapture.csproj
+++ b/Fischless.GameCapture/Fischless.GameCapture.csproj
@@ -19,8 +19,8 @@
-
-
+
+
\ No newline at end of file
diff --git a/Fischless.GameCapture/Graphics/GraphicsCapture.cs b/Fischless.GameCapture/Graphics/GraphicsCapture.cs
index b9f13bda..f0e88ddb 100644
--- a/Fischless.GameCapture/Graphics/GraphicsCapture.cs
+++ b/Fischless.GameCapture/Graphics/GraphicsCapture.cs
@@ -40,7 +40,7 @@ public class GraphicsCapture : IGameCapture
// 用于获取帧数据的临时纹理和暂存资源
private Texture2D? _stagingTexture;
-
+
private long _lastFrameTime = 0;
@@ -81,12 +81,14 @@ public class GraphicsCapture : IGameCapture
_captureFramePool.FrameArrived += OnFrameArrived;
_captureSession = _captureFramePool.CreateCaptureSession(_captureItem);
- if (ApiInformation.IsPropertyPresent("Windows.Graphics.Capture.GraphicsCaptureSession", "IsCursorCaptureEnabled"))
+ if (ApiInformation.IsPropertyPresent("Windows.Graphics.Capture.GraphicsCaptureSession",
+ "IsCursorCaptureEnabled"))
{
_captureSession.IsCursorCaptureEnabled = false;
}
- if (ApiInformation.IsWriteablePropertyPresent("Windows.Graphics.Capture.GraphicsCaptureSession", "IsBorderRequired"))
+ if (ApiInformation.IsWriteablePropertyPresent("Windows.Graphics.Capture.GraphicsCaptureSession",
+ "IsBorderRequired"))
{
_captureSession.IsBorderRequired = false;
}
@@ -110,7 +112,8 @@ public class GraphicsCapture : IGameCapture
ResourceRegion region = new();
- DwmApi.DwmGetWindowAttribute(hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out var windowRect);
+ DwmApi.DwmGetWindowAttribute(hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS,
+ out var windowRect);
User32.GetClientRect(_hWnd, out var clientRect);
//POINT point = default; // 这个点和 DwmGetWindowAttribute 结果差1
//User32.ClientToScreen(hWnd, ref point);
@@ -174,13 +177,14 @@ public class GraphicsCapture : IGameCapture
{
return;
}
-
+
// 限制最高处理帧率为66fps
var now = Kernel32.GetTickCount();
if (now - _lastFrameTime < 15)
{
return;
}
+
_lastFrameTime = now;
var frameSize = _captureItem.Size;
@@ -227,7 +231,7 @@ public class GraphicsCapture : IGameCapture
try
{
// 创建一个新的Mat
- var newFrame = new Mat(stagingTexture.Description.Height, stagingTexture.Description.Width,
+ var newFrame = Mat.FromPixelData(stagingTexture.Description.Height, stagingTexture.Description.Width,
_isHdrEnabled ? MatType.MakeType(7, 4) : MatType.CV_8UC4, dataBox.DataPointer);
// 如果是HDR,进行HDR到SDR的转换
diff --git a/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
index f3f94a4e..2957a74b 100644
--- a/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
+++ b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
@@ -90,7 +90,7 @@ public static class Texture2DExtensions
MapMode.Read,
SharpDX.Direct3D11.MapFlags.None);
- var mat = new Mat(staging.Description.Height, staging.Description.Width, MatType.CV_8UC4, dataBox.DataPointer);
+ var mat = Mat.FromPixelData(staging.Description.Height, staging.Description.Width, MatType.CV_8UC4, dataBox.DataPointer);
return mat;
}
catch (Exception e)
diff --git a/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyGen.cs b/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyGen.cs
index 31079d01..66fc31a6 100644
--- a/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyGen.cs
+++ b/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyGen.cs
@@ -19,12 +19,16 @@ public class AvatarClassifyGen
// 读取基础图像
// List sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "*.png", SearchOption.TopDirectoryOnly).ToList();
// 只用一个图像
- List sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Varesa.png", SearchOption.TopDirectoryOnly).ToList();
- List sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Iansan.png", SearchOption.TopDirectoryOnly).ToList();
+ List sideImageFiles = Directory.GetFiles(Path.Combine(BaseDir, "side_src"),
+ "UI_AvatarIcon_Side_Varesa.png", SearchOption.TopDirectoryOnly).ToList();
+ List sideImageFiles2 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"),
+ "UI_AvatarIcon_Side_Iansan.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles2);
- List sideImageFiles3 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_AmborCostumeWic.png", SearchOption.TopDirectoryOnly).ToList();
+ List sideImageFiles3 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"),
+ "UI_AvatarIcon_Side_AmborCostumeWic.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles3);
- List sideImageFiles4 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_Ambor.png", SearchOption.TopDirectoryOnly).ToList();
+ List sideImageFiles4 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"),
+ "UI_AvatarIcon_Side_Ambor.png", SearchOption.TopDirectoryOnly).ToList();
sideImageFiles.AddRange(sideImageFiles4);
// List sideImageFiles5 = Directory.GetFiles(Path.Combine(BaseDir, "side_src"), "UI_AvatarIcon_Side_XianglingCostumeWinter.png", SearchOption.TopDirectoryOnly).ToList();
// sideImageFiles.AddRange(sideImageFiles5);
@@ -72,11 +76,14 @@ public class AvatarClassifyGen
for (int i = 0; i < count; i++)
{
// 随机挑选一张背景图像
- string backgroundImageFile = Path.Combine(BackgroundDir, Directory.GetFiles(BackgroundDir, "*.png")[Rd.Next(Directory.GetFiles(BackgroundDir, "*.png").Length)]);
+ string backgroundImageFile = Path.Combine(BackgroundDir,
+ Directory.GetFiles(BackgroundDir, "*.png")[
+ Rd.Next(Directory.GetFiles(BackgroundDir, "*.png").Length)]);
// 从背景图像中随机取一块 128x128 的区域
Mat backgroundImage = Cv2.ImRead(backgroundImageFile, ImreadModes.Color);
- Rect backgroundRect = new Rect(Rd.Next(backgroundImage.Width - 128), new Random().Next(backgroundImage.Height - 128), 128, 128);
+ Rect backgroundRect = new Rect(Rd.Next(backgroundImage.Width - 128),
+ new Random().Next(backgroundImage.Height - 128), 128, 128);
Mat backgroundImageRegion = backgroundImage[backgroundRect];
// 随机平移、缩放保留区域
@@ -93,9 +100,11 @@ public class AvatarClassifyGen
// Cv2.ImShow("resizedSideImage", resizedSideImage);
var resizedMaskImage = new Mat();
// Cv2.Threshold(alphaChannel, alphaChannel, 200, 255, ThresholdTypes.Otsu);
- Cv2.Resize(255 - alphaChannel, resizedMaskImage, new Size(128 * scale, 128 * scale), 0, 0, InterpolationFlags.Cubic);
+ Cv2.Resize(~alphaChannel, resizedMaskImage, new Size(128 * scale, 128 * scale), 0, 0,
+ InterpolationFlags.Cubic);
var resizedAlphaChannel = new Mat();
- Cv2.Resize(alphaChannel, resizedAlphaChannel, new Size(128 * scale, 128 * scale), 0, 0, InterpolationFlags.Cubic);
+ Cv2.Resize(alphaChannel, resizedAlphaChannel, new Size(128 * scale, 128 * scale), 0, 0,
+ InterpolationFlags.Cubic);
// Cv2.ImShow("resizedMaskImage", resizedMaskImage);
// generatedImage[transformedRect] = resizedSideImage;
@@ -112,7 +121,8 @@ public class AvatarClassifyGen
int offsetY = Rd.Next(-ySpace, 0);
Debug.WriteLine($"{sideImageFileName} 缩放{scale}大于1 偏移 ({offsetX},{offsetY})");
- var roi = new Rect((resizedSideImage.Width - 128) / 2 + offsetX, (resizedSideImage.Height - 128) + offsetY, 128, 128);
+ var roi = new Rect((resizedSideImage.Width - 128) / 2 + offsetX,
+ (resizedSideImage.Height - 128) + offsetY, 128, 128);
// result = new Mat();
// Cv2.BitwiseAnd(backgroundImageRegionClone, backgroundImageRegionClone, result, resizedMaskImage[roi]);
result = Mul(backgroundImageRegionClone, resizedAlphaChannel[roi]);
@@ -126,7 +136,8 @@ public class AvatarClassifyGen
int offsetY = Rd.Next(-ySpace, 0);
Debug.WriteLine($"{sideImageFileName} 缩放{scale}小于等于1 偏移 ({offsetX},{offsetY})");
- var roi = new Rect((128 - resizedSideImage.Width) / 2 + offsetX, (128 - resizedSideImage.Height) + offsetY, resizedSideImage.Width, resizedSideImage.Height);
+ var roi = new Rect((128 - resizedSideImage.Width) / 2 + offsetX,
+ (128 - resizedSideImage.Height) + offsetY, resizedSideImage.Width, resizedSideImage.Height);
var res = new Mat();
// Cv2.BitwiseAnd(backgroundImageRegionClone[roi], backgroundImageRegionClone[roi], res, resizedMaskImage);
res = Mul(backgroundImageRegionClone[roi], resizedAlphaChannel);
@@ -146,11 +157,12 @@ public class AvatarClassifyGen
var channels = background.Split();
for (int i = 0; i < 3; i++)
{
- Cv2.Multiply(channels[i], 255 - alphaChannel, channels[i], 1 / 255.0);
+ Cv2.Multiply(channels[i], ~ alphaChannel, channels[i], 1 / 255.0);
}
+
Mat result = new Mat();
Cv2.Merge(channels[..3], result);
return result;
}
}
-}
+}
\ No newline at end of file
diff --git a/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyTransparentGen.cs b/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyTransparentGen.cs
index 9ce939f6..cc6acffb 100644
--- a/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyTransparentGen.cs
+++ b/Test/BetterGenshinImpact.Test/Dataset/AvatarClassifyTransparentGen.cs
@@ -100,7 +100,7 @@ public class AvatarClassifyTransparentGen
// Cv2.ImShow("resizedSideImage", resizedSideImage);
var resizedMaskImage = new Mat();
// Cv2.Threshold(alphaChannel, alphaChannel, 200, 255, ThresholdTypes.Otsu);
- Cv2.Resize(255 - alphaChannel, resizedMaskImage, new Size(128 * scale, 128 * scale), 0, 0, InterpolationFlags.Cubic);
+ Cv2.Resize(~ alphaChannel, resizedMaskImage, new Size(128 * scale, 128 * scale), 0, 0, InterpolationFlags.Cubic);
var resizedAlphaChannel = new Mat();
Cv2.Resize(alphaChannel, resizedAlphaChannel, new Size(128 * scale, 128 * scale), 0, 0, InterpolationFlags.Cubic);
@@ -153,7 +153,7 @@ public class AvatarClassifyTransparentGen
var channels = background.Split();
for (int i = 0; i < 3; i++)
{
- Cv2.Multiply(channels[i], 255 - alphaChannel, channels[i], 1 / 255.0);
+ Cv2.Multiply(channels[i], ~ alphaChannel, channels[i], 1 / 255.0);
}
Mat result = new Mat();
Cv2.Merge(channels[..3], result);
diff --git a/Test/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs b/Test/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
index 0e298f12..b5d4bbc1 100644
--- a/Test/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
+++ b/Test/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
@@ -281,10 +281,10 @@ public class KeyPointMatchTest
writer.Write(image.Rows);
writer.Write(image.Cols);
int depth = image.Depth();
- int type = image.Type();
+ MatType type = image.Type();
int channels = image.Channels();
writer.Write(depth);
- writer.Write(type);
+ writer.Write(type.Value);
writer.Write(channels);
int sizeInBytes = (int)image.Step() * image.Rows;
writer.Write(sizeInBytes);
diff --git a/Test/BetterGenshinImpact.Test/Simple/MiniMap/CharacterOrientationTest.cs b/Test/BetterGenshinImpact.Test/Simple/MiniMap/CharacterOrientationTest.cs
index 4e1f73a5..6e6a9abd 100644
--- a/Test/BetterGenshinImpact.Test/Simple/MiniMap/CharacterOrientationTest.cs
+++ b/Test/BetterGenshinImpact.Test/Simple/MiniMap/CharacterOrientationTest.cs
@@ -282,7 +282,7 @@ public class CharacterOrientationTest
if (contours.Length > 0)
{
- var maxRect = Rect.Empty;
+ Rect maxRect = default;
var maxIndex = 0;
for (int i = 0; i < contours.Length; i++)
{
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
index be0becbe..cf70aaa8 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
@@ -31,7 +31,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1);
var blackboard = new Blackboard(sleep: i => { })
{
- fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList())
+ fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList())
};
//
@@ -62,7 +62,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1);
var blackboard = new Blackboard(sleep: i => { })
{
- fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList())
+ fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList())
};
DateTimeOffset dateTime = new DateTimeOffset(2025, 2, 26, 16, 13, 54, 285, TimeSpan.FromHours(8));
@@ -116,7 +116,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1);
var blackboard = new Blackboard(sleep: i => { })
{
- fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList())
+ fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList())
};
DateTimeOffset dateTime = new DateTimeOffset(2025, 2, 26, 16, 13, 54, 285, TimeSpan.FromHours(8));
@@ -155,7 +155,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region medaka受到遮挡,第3次失败
//
fishNames = new string[] { "koi", "koi head", "sunfish" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(20));
@@ -173,7 +173,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region sunfish受到遮挡,medaka再次出现,第4次成功,并钓起medaka
//
fishNames = new string[] { "koi", "koi head", "medaka" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(30));
@@ -191,7 +191,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region sunfish再次出现,第5次失败
//
fishNames = new string[] { "koi", "koi head", "sunfish" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(40));
@@ -222,7 +222,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
IEnumerable fishNames = new string[] { "koi", "koi head", "sunfish" };
var blackboard = new Blackboard(sleep: i => { })
{
- fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList())
+ fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList())
};
DateTimeOffset dateTime = new DateTimeOffset(2025, 2, 26, 16, 13, 54, 285, TimeSpan.FromHours(8));
@@ -244,7 +244,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region koi受到遮挡,第2次失败
//
fishNames = new string[] { "sunfish" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(10));
@@ -263,7 +263,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region koi再次出现,第3次失败
//
fishNames = new string[] { "koi", "koi head", "sunfish" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(20));
@@ -281,7 +281,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
#region 第4次失败
//
fishNames = new string[] { "koi", "koi head", "sunfish" };
- blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, OpenCvSharp.Rect.Empty, 0)).ToList());
+ blackboard.fishpond = new Fishpond(fishNames.Select(n => new OneFish(n, default, 0)).ToList());
sut.Reset();
fakeTimeProvider.SetUtcNow(dateTime.AddSeconds(40));
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
index b1105b81..8fc18c07 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
@@ -135,7 +135,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
var actual = sut.currentFish;
//
- Assert.True(blackboard.fishpond.TargetRect != null && blackboard.fishpond.TargetRect.Value != OpenCvSharp.Rect.Empty);
+ Assert.True(blackboard.fishpond.TargetRect != null && blackboard.fishpond.TargetRect.Value != default);
Assert.Equal(3, blackboard.fishpond.Fishes.Count(f => f.FishType.Name == "pufferfish"));
Assert.Equal(blackboard.fishpond.Fishes.OrderBy(f => f.Rect.X).First(), actual);