mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-25 10:05:49 +08:00
* bug fix:拉条过程中内存没有及时释放 * 新增LiftAndHold行为用于举竿、检测预抛竿时鼠标左键是否被意外松开、终止任务;抛竿开始后5秒内如从未找到落点,则返回失败,并配有单元测试;添加抛竿时无鱼饵适用鱼的单元测试;调整变量名 * 新增一个钓鱼昼夜设置枚举DontChange及其逻辑(枚举值为3),表示不调整时间直接开钓 * 针对可能是游戏中的雾气/滤镜/小黄鸭之类不明原因干扰了钓鱼拉条框的识别,修改了CV算法,使其不严格按照黄色(255,255,192)找矩形,而是按一定HSV范围寻找,并加强过滤;添加上述不明原因案例的测试用例 * 将MySimpleParallel改造为支持两个以上子行为;将“检查抛竿结果”行为合并到“下杆中”并行节点,以去除检查的等待时间,由此希望能应对鱼过快上钩的情况
100 lines
4.0 KiB
C#
100 lines
4.0 KiB
C#
using OpenCvSharp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
|
||
namespace BetterGenshinImpact.GameTask.AutoFishing
|
||
{
|
||
public class AutoFishingImageRecognition
|
||
{
|
||
/// <summary>
|
||
/// 钓鱼条矩形识别
|
||
/// </summary>
|
||
/// <param name="src"></param>
|
||
/// <returns></returns>
|
||
public static List<Rect>? GetFishBarRect(Mat src)
|
||
{
|
||
try
|
||
{
|
||
// 拉条框的黄色是:RGB 255, 255, 192 ~ HSV 43, 63, 255
|
||
// var testPixel = rgbMat.At<Vec3b>(105, 968);
|
||
using Mat rgbMat = src.CvtColor(ColorConversionCodes.BGR2HSV_FULL);
|
||
|
||
var lowYellow = new Scalar(43 - 3, 63 - 20, 255 - 10);
|
||
var highYellow = new Scalar(43 + 3, 63 + 40, 255);
|
||
using Mat mask = rgbMat.InRange(lowYellow, highYellow);
|
||
|
||
Cv2.Threshold(mask, mask, 0, 255, ThresholdTypes.Binary); //二值化
|
||
|
||
Cv2.FindContours(mask, out var contours, out _, RetrievalModes.External,
|
||
ContourApproximationModes.ApproxSimple, null);
|
||
if (contours.Length > 0)
|
||
{
|
||
var boxes = contours.Select(Cv2.MinAreaRect).Where(r => r.Angle % 90 <= 1) // 剔除倾斜的
|
||
.Select(r => r.BoundingRect()).ToList();
|
||
|
||
boxes = boxes.Where(r => r.Height >= 10 && r.Width >= 5).ToList(); // 剔除太小的
|
||
return boxes;
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.WriteLine(e);
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 匹配 “鱼儿上钩拉!”文字区域
|
||
/// </summary>
|
||
/// <param name="src"></param>
|
||
/// <param name="liftingWordsAreaRect"></param>
|
||
/// <returns></returns>
|
||
public static Rect MatchFishBiteWords(Mat src, Rect liftingWordsAreaRect)
|
||
{
|
||
try
|
||
{
|
||
Cv2.CvtColor(src, src, ColorConversionCodes.BGR2RGB);
|
||
var lowPurple = new Scalar(253, 253, 253);
|
||
var highPurple = new Scalar(255, 255, 255);
|
||
Cv2.InRange(src, lowPurple, highPurple, src);
|
||
Cv2.Threshold(src, src, 0, 255, ThresholdTypes.Binary);
|
||
var kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(20, 20),
|
||
new OpenCvSharp.Point(-1, -1));
|
||
Cv2.Dilate(src, src, kernel); //膨胀
|
||
|
||
Cv2.FindContours(src, out var contours, out _, RetrievalModes.External,
|
||
ContourApproximationModes.ApproxSimple, null);
|
||
if (contours.Length > 0)
|
||
{
|
||
var boxes = contours.Select(Cv2.BoundingRect);
|
||
var rects = boxes.ToList();
|
||
if (rects.Count > 1)
|
||
{
|
||
rects.Sort((a, b) => b.Height.CompareTo(a.Height));
|
||
}
|
||
|
||
//VisionContext.Instance().DrawContent.PutRect("FishBiteTipsDebug",
|
||
// rects[0].ToWindowsRectangleOffset(liftingWordsAreaRect.X, liftingWordsAreaRect.Y)
|
||
// .ToRectDrawable());
|
||
if (rects[0].Height < src.Height
|
||
&& rects[0].Width * 1.0 / rects[0].Height >= 3 // 长宽比判断
|
||
&& liftingWordsAreaRect.Width > rects[0].Width * 3 // 文字范围3倍小于钓鱼条范围的
|
||
&& liftingWordsAreaRect.Width * 1.0 / 2 > rects[0].X // 中轴线判断左
|
||
&& liftingWordsAreaRect.Width * 1.0 / 2 < rects[0].X + rects[0].Width) // 中轴线判断右
|
||
{
|
||
return rects[0];
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.WriteLine(e);
|
||
}
|
||
|
||
return Rect.Empty;
|
||
}
|
||
}
|
||
} |