mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
151 lines
4.7 KiB
C#
151 lines
4.7 KiB
C#
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||
using Compunet.YoloV8.Data;
|
||
using OpenCvSharp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
|
||
namespace BetterGenshinImpact.GameTask.AutoFishing.Model;
|
||
|
||
public class Fishpond
|
||
{
|
||
/// <summary>
|
||
/// 鱼池位置
|
||
/// </summary>
|
||
public Rect FishpondRect { get; set; }
|
||
|
||
/// <summary>
|
||
/// 抛竿落点位置
|
||
/// </summary>
|
||
public Rect? TargetRect { get; set; }
|
||
|
||
/// <summary>
|
||
/// 鱼池中的鱼
|
||
/// </summary>
|
||
public List<OneFish> Fishes { get; set; } = [];
|
||
|
||
public Fishpond(List<OneFish> fishes)
|
||
{
|
||
Fishes = fishes;
|
||
|
||
FishpondRect = CalculateFishpondRect();
|
||
}
|
||
|
||
/// <summary>
|
||
/// </summary>
|
||
/// <param name="result"></param>
|
||
/// <param name="includeTarget">是否包含抛竿落点</param>
|
||
/// <param name="ignoreObtained">是否忽略“获得”物品的图标</param>
|
||
public Fishpond(DetectionResult result, bool includeTarget = false, bool ignoreObtained = false)
|
||
{
|
||
Print(result);
|
||
foreach (var box in result.Boxes)
|
||
{
|
||
// 可信度太低的直接放弃
|
||
if (box.Confidence < 0.4)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
Rect rect = new Rect(box.Bounds.X, box.Bounds.Y, box.Bounds.Width, box.Bounds.Height);
|
||
if (box.Class.Name == "rod" || box.Class.Name == "err rod")
|
||
{
|
||
TargetRect = rect;
|
||
continue;
|
||
}
|
||
else if (ignoreObtained)
|
||
{
|
||
// todo:特殊鱼的图标以及新获得的图标是不一样的,要特殊处理
|
||
// todo:不是很重要但有机会可以从构造函数里分离逻辑
|
||
// 忽略界面左侧提示的“获得”物品的图标,当上一竿获得鱼时,会对当前竿产生干扰
|
||
// 使用估算大小和位置的方式来判断并剔除
|
||
if (box.Bounds.Width < result.Image.Width * 0.036 && box.Bounds.Height < result.Image.Width * 0.036)
|
||
{
|
||
Rect huode = new Rect((int)(0.04375 * result.Image.Width), (int)(0.4666 * result.Image.Height), (int)(0.1 * result.Image.Width), (int)(0.1 * result.Image.Width));
|
||
if (huode.Contains(rect))
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
// 忽略界面中央提示的“获得”物品的图标
|
||
if (box.Bounds.Width > result.Image.Width * 0.03 && box.Bounds.Width < result.Image.Width * 0.06 &&
|
||
box.Bounds.Height > result.Image.Width * 0.03 && box.Bounds.Height < result.Image.Width * 0.06)
|
||
{
|
||
Rect huode = new Rect((int)(0.4 * result.Image.Width), (int)(0.445 * result.Image.Height), (int)(0.2 * result.Image.Width), (int)(0.06125 * result.Image.Width));
|
||
if (huode.Contains(rect))
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
if (includeTarget)
|
||
{
|
||
if (box.Class.Name == "koi") //进入抛竿的时候只看koihead
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
|
||
var fish = new OneFish(box.Class.Name, rect, box.Confidence);
|
||
Fishes.Add(fish);
|
||
}
|
||
|
||
// 可信度最高的鱼放在最前面
|
||
Fishes = [.. Fishes.OrderByDescending(fish => fish.Confidence)];
|
||
|
||
FishpondRect = CalculateFishpondRect();
|
||
}
|
||
|
||
private void Print(DetectionResult result)
|
||
{
|
||
Debug.Write("鱼塘YOLO识别结果:");
|
||
foreach (var box in result.Boxes)
|
||
{
|
||
Debug.Write(box.ToString());
|
||
}
|
||
Debug.WriteLine("");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算鱼塘位置
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public Rect CalculateFishpondRect()
|
||
{
|
||
if (Fishes.Count == 0)
|
||
{
|
||
return default;
|
||
}
|
||
|
||
var left = int.MaxValue;
|
||
var top = int.MaxValue;
|
||
var right = int.MinValue;
|
||
var bottom = int.MinValue;
|
||
foreach (var fish in Fishes)
|
||
{
|
||
if (fish.Rect.Left < left)
|
||
{
|
||
left = fish.Rect.Left;
|
||
}
|
||
|
||
if (fish.Rect.Top < top)
|
||
{
|
||
top = fish.Rect.Top;
|
||
}
|
||
|
||
if (fish.Rect.Right > right)
|
||
{
|
||
right = fish.Rect.Right;
|
||
}
|
||
|
||
if (fish.Rect.Bottom > bottom)
|
||
{
|
||
bottom = fish.Rect.Bottom;
|
||
}
|
||
}
|
||
|
||
return new Rect(left, top, right - left, bottom - top);
|
||
}
|
||
}
|