Skip to content

Commit 32f7445

Browse files
用CV的相位相关方法代替旧的方法来检测grid界面是否还能滚动,配有单元测试;封装了一个grid界面的操作类,直接对此类对象进行遍历即可获取所有项 (#1724)
1 parent 937c869 commit 32f7445

File tree

4 files changed

+300
-130
lines changed

4 files changed

+300
-130
lines changed

BetterGenshinImpact/GameTask/AutoArtifactSalvage/AutoArtifactSalvageTask.cs

Lines changed: 26 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using BetterGenshinImpact.Core.Recognition.OCR;
2525
using BetterGenshinImpact.GameTask.Common;
2626
using BetterGenshinImpact.GameTask.Common.Job;
27+
using GameTask.Model.GameUI;
2728

2829
namespace BetterGenshinImpact.GameTask.AutoArtifactSalvage;
2930

@@ -210,119 +211,43 @@ public async Task Start(CancellationToken ct)
210211
private async Task Salvage5Star(string regularExpression, int maxNumToCheck)
211212
{
212213
int count = maxNumToCheck;
213-
Queue<string> checkedArtifactAffixesQueue = new Queue<string>();
214-
int duplicateSum = 0;
215-
while (count > 0 && duplicateSum < 3)
216-
{
217-
// VisionContext.Instance().DrawContent.ClearAll();
218-
// await Delay(400, this.ct);
219-
220-
using var ra = CaptureToRectArea();
221-
using ImageRegion grid = ra.DeriveCrop(new Rect((int)(ra.Width * 0.025), (int)(ra.Width * 0.055), (int)(ra.Width * 0.66), (int)(ra.Width * 0.4)));
222-
IEnumerable<Rect> gridItems = GetArtifactGridItems(grid.SrcMat);
223214

224-
//foreach (Rect item in gridItems)
225-
//{
226-
// grid.DrawRect(item, item.GetHashCode().ToString(), new System.Drawing.Pen(System.Drawing.Color.Blue));
227-
//}
228-
229-
bool anyItemChecked = false;
230-
foreach (Rect item in gridItems)
231-
{
232-
using ImageRegion itemRegion = grid.DeriveCrop(item);
233-
if (GetArtifactStatus(itemRegion.SrcMat) == ArtifactStatus.None)
234-
{
235-
anyItemChecked = true;
236-
itemRegion.Click();
237-
await Delay(300, ct);
238-
239-
using var ra1 = CaptureToRectArea();
240-
using ImageRegion grid1 = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.025), (int)(ra1.Width * 0.055), (int)(ra1.Width * 0.66), (int)(ra1.Width * 0.4)));
241-
using ImageRegion itemRegion1 = grid1.DeriveCrop(item);
242-
if (GetArtifactStatus(itemRegion1.SrcMat) == ArtifactStatus.Selected)
243-
{
244-
using ImageRegion card = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.70), (int)(ra1.Width * 0.055), (int)(ra1.Width * 0.24), (int)(ra1.Width * 0.29)));
245-
string affixes = GetArtifactAffixes(card.SrcMat, OcrFactory.Paddle);
246-
247-
if (checkedArtifactAffixesQueue.Any(c => c == affixes))
248-
{
249-
duplicateSum++;
250-
logger.LogInformation($"重复检查了该圣遗物");
251-
}
252-
if (checkedArtifactAffixesQueue.Count >= 36) // 一个grid最多能看到36个完整的圣遗物
253-
{
254-
checkedArtifactAffixesQueue.Dequeue();
255-
}
256-
checkedArtifactAffixesQueue.Enqueue(affixes);
257-
258-
if (IsMatchRegularExpression(affixes, regularExpression, out string msg))
259-
{
260-
logger.LogInformation(message: msg);
261-
}
262-
else
263-
{
264-
itemRegion.Click();
265-
await Delay(100, ct);
266-
}
267-
if (duplicateSum >= 3)
268-
{
269-
break;
270-
}
271-
}
272-
count--;
273-
if (count <= 0)
274-
{
275-
break;
276-
}
277-
}
278-
}
279-
if (count <= 0 || duplicateSum >= 3)
280-
{
281-
break;
282-
}
283-
if (anyItemChecked)
215+
using var ra0 = CaptureToRectArea();
216+
Rect gridRoi = new Rect((int)(ra0.Width * 0.025), (int)(ra0.Width * 0.055), (int)(ra0.Width * 0.66), (int)(ra0.Width * 0.4));
217+
GridScreen gridScreen = new GridScreen(gridRoi, 3, 40, 28, 0.018, this.logger, this.ct); // 圣遗物分解Grid有4行9列
218+
await foreach (ImageRegion itemRegion in gridScreen)
219+
{
220+
Rect gridRect = itemRegion.ToRect();
221+
if (GetArtifactStatus(itemRegion.SrcMat) == ArtifactStatus.None)
284222
{
285-
for (int i = 0; i < 32; i++) // 先滚动大约三行半
286-
{
287-
input.Mouse.VerticalScroll(-2);
288-
await Delay(40, ct);
289-
}
223+
itemRegion.Click();
224+
await Delay(300, ct);
290225

291-
DateTimeOffset rollingEndTime = DateTime.Now.AddSeconds(2);
292-
while (DateTime.Now < rollingEndTime)
226+
using var ra1 = CaptureToRectArea();
227+
using ImageRegion itemRegion1 = ra1.DeriveCrop(gridRect + new Point(gridRoi.X, gridRoi.Y));
228+
if (GetArtifactStatus(itemRegion1.SrcMat) == ArtifactStatus.Selected)
293229
{
294-
await Delay(60, ct);
295-
using var ra2 = CaptureToRectArea();
296-
using ImageRegion grid2 = ra2.DeriveCrop(new Rect((int)(ra2.Width * 0.025), (int)(ra2.Width * 0.055), (int)(ra2.Width * 0.66), (int)(ra2.Width * 0.4)));
297-
IEnumerable<Rect> gridItems2 = GetArtifactGridItems(grid2.SrcMat);
298-
if (gridItems2.Min(i => i.Y) > (ra2.Width * 0.018)) // 精细滚动,保证完整地显示四行
230+
using ImageRegion card = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.70), (int)(ra1.Width * 0.055), (int)(ra1.Width * 0.24), (int)(ra1.Width * 0.29)));
231+
string affixes = GetArtifactAffixes(card.SrcMat, OcrFactory.Paddle);
232+
233+
if (IsMatchRegularExpression(affixes, regularExpression, out string msg))
299234
{
300-
input.Mouse.VerticalScroll(-1);
235+
logger.LogInformation(message: msg);
301236
}
302237
else
303238
{
304-
break;
239+
itemRegion.Click();
240+
await Delay(100, ct);
305241
}
306242
}
307-
308-
grid.MoveTo(grid.Width, grid.Height);
309-
await Delay(500, ct);
310-
}
311-
else
312-
{
313-
await Delay(400, ct);
314-
logger.LogInformation("找不到可检查的圣遗物了");
315-
break;
243+
count--;
244+
if (count <= 0)
245+
{
246+
logger.LogInformation("检查次数已耗尽");
247+
break;
248+
}
316249
}
317250
}
318-
if (count <= 0)
319-
{
320-
logger.LogInformation("检查次数已耗尽");
321-
}
322-
if (duplicateSum >= 3)
323-
{
324-
logger.LogInformation("重复检查次数过多,推断为找不到可检查的了");
325-
}
326251
}
327252

328253
public static bool IsMatchRegularExpression(string affixes, string regularExpression, out string msg)
@@ -352,33 +277,6 @@ public static string GetArtifactAffixes(Mat src, IOcrService ocrService)
352277
return ocrResult.Text;
353278
}
354279

355-
public static IEnumerable<Rect> GetArtifactGridItems(Mat src)
356-
{
357-
using Mat grey = src.CvtColor(ColorConversionCodes.BGR2GRAY);
358-
359-
using Mat canny = grey.Canny(20, 40);
360-
361-
Cv2.FindContours(canny, out var contours, out _, RetrievalModes.External,
362-
ContourApproximationModes.ApproxSimple, null);
363-
364-
IEnumerable<Rect> boxes = contours.Where(c => Cv2.MinAreaRect(c).Angle % 90 <= 1) // 剔除倾斜
365-
.Select(Cv2.BoundingRect).Where(r =>
366-
{
367-
if (r.Height == 0)
368-
{
369-
return false;
370-
}
371-
return Math.Abs((float)r.Width / r.Height - 0.8) < 0.05; // 按形状筛选
372-
}).ToList();
373-
374-
//src.DrawContours(contours, -1, Scalar.Red);
375-
376-
int biggestRectHeight = boxes.Max(b => b.Height);
377-
boxes = boxes.Where(b => (float)b.Height / biggestRectHeight > 0.88); // 剔除太小的
378-
379-
return boxes.ToArray();
380-
}
381-
382280
public static ArtifactStatus GetArtifactStatus(Mat src)
383281
{
384282
using Mat upperLine = new Mat(src, new Rect(0, 0, src.Width, (int)(src.Height * 0.19)));

0 commit comments

Comments
 (0)