mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
284 lines
9.2 KiB
C#
284 lines
9.2 KiB
C#
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||
using BetterGenshinImpact.Helpers.Extensions;
|
||
using OpenCvSharp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Linq;
|
||
|
||
namespace BetterGenshinImpact.Core.Recognition;
|
||
|
||
/// <summary>
|
||
/// 识别对象
|
||
/// </summary>
|
||
[Serializable]
|
||
public class RecognitionObject
|
||
{
|
||
public RecognitionTypes RecognitionType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 感兴趣的区域
|
||
/// </summary>
|
||
public Rect RegionOfInterest { get; set; }
|
||
|
||
/// <summary>
|
||
/// 识别对象名称,可以为空
|
||
/// </summary>
|
||
public string? Name { get; set; }
|
||
|
||
#region 模板匹配
|
||
|
||
/// <summary>
|
||
/// 模板匹配的对象(彩色)
|
||
/// </summary>
|
||
public Mat? TemplateImageMat { get; set; }
|
||
|
||
/// <summary>
|
||
/// 模板匹配的对象(灰色)
|
||
/// </summary>
|
||
public Mat? TemplateImageGreyMat { get; set; }
|
||
|
||
/// <summary>
|
||
/// 模板匹配阈值。可选,默认 0.8 。
|
||
/// </summary>
|
||
public double Threshold { get; set; } = 0.8;
|
||
|
||
/// <summary>
|
||
/// 是否使用 3 通道匹配。可选,默认 false 。
|
||
/// </summary>
|
||
public bool Use3Channels { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 模板匹配算法。可选,默认 CCoeffNormed 。
|
||
/// https://docs.opencv.org/4.x/df/dfb/group__imgproc__object.html
|
||
/// </summary>
|
||
public TemplateMatchModes TemplateMatchMode { get; set; } = TemplateMatchModes.CCoeffNormed;
|
||
|
||
/// <summary>
|
||
/// 匹配模板遮罩,指定图片中的某种色彩不需要匹配
|
||
/// 使用时,需要将模板图片的背景色设置为纯绿色,即 (0, 255, 0)
|
||
/// </summary>
|
||
public bool UseMask { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 不需要匹配的颜色,默认绿色
|
||
/// UseMask = true 的时候有用
|
||
/// </summary>
|
||
public Color MaskColor { get; set; } = Color.FromArgb(0, 255, 0);
|
||
|
||
public Mat? MaskMat { get; set; }
|
||
|
||
/// <summary>
|
||
/// 匹配成功时,是否在屏幕上绘制矩形框。可选,默认 false 。
|
||
/// true 时 Name 必须有值。
|
||
/// </summary>
|
||
public bool DrawOnWindow { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// DrawOnWindow 为 true 时,绘制的矩形框的颜色。可选,默认红色。
|
||
/// </summary>
|
||
public Pen DrawOnWindowPen = new(Color.Red, 2);
|
||
|
||
/// <summary>
|
||
/// 一个模板匹配多个结果的时候最大匹配数量。可选,默认 -1,即不限制。
|
||
/// </summary>
|
||
public int MaxMatchCount { get; set; } = -1;
|
||
|
||
/// <summary>
|
||
/// 是否启用二值化后模板匹配
|
||
/// </summary>
|
||
public bool UseBinaryMatch { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 二值化阈值,默认 128
|
||
/// </summary>
|
||
public int BinaryThreshold { get; set; } = 128;
|
||
|
||
public RecognitionObject InitTemplate()
|
||
{
|
||
if (TemplateImageMat != null && TemplateImageGreyMat == null)
|
||
{
|
||
TemplateImageGreyMat = new Mat();
|
||
Cv2.CvtColor(TemplateImageMat, TemplateImageGreyMat, ColorConversionCodes.BGR2GRAY);
|
||
}
|
||
|
||
if (UseMask && TemplateImageMat != null && MaskMat == null) MaskMat = OpenCvCommonHelper.CreateMask(TemplateImageMat, MaskColor.ToScalar());
|
||
return this;
|
||
}
|
||
|
||
|
||
public static RecognitionObject TemplateMatch(Mat mat)
|
||
{
|
||
var ro = new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.TemplateMatch,
|
||
TemplateImageMat = mat,
|
||
UseMask = false,
|
||
};
|
||
|
||
return ro.InitTemplate();
|
||
}
|
||
|
||
public static RecognitionObject TemplateMatch(Mat mat, bool useMask, Color maskColor = default)
|
||
{
|
||
var ro = new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.TemplateMatch,
|
||
TemplateImageMat = mat,
|
||
UseMask = useMask,
|
||
MaskColor = maskColor == default? Color.FromArgb(0, 255, 0) : maskColor
|
||
};
|
||
|
||
return ro.InitTemplate();
|
||
}
|
||
|
||
public static RecognitionObject TemplateMatch(Mat mat, double x, double y, double w, double h)
|
||
{
|
||
var ro = new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.TemplateMatch,
|
||
TemplateImageMat = mat,
|
||
RegionOfInterest = new Rect((int)Math.Round(x), (int)Math.Round(y), (int)Math.Round(w), (int)Math.Round(h))
|
||
};
|
||
|
||
return ro.InitTemplate();
|
||
}
|
||
|
||
#endregion 模板匹配
|
||
|
||
#region 颜色匹配
|
||
|
||
/// <summary>
|
||
/// 颜色匹配方式。即 cv::ColorConversionCodes。可选,默认 4 (RGB)。
|
||
/// 常用值:4 (RGB, 3 通道), 40 (HSV, 3 通道), 6 (GRAY, 1 通道)。
|
||
/// https://docs.opencv.org/4.x/d8/d01/group__imgproc__color__conversions.html
|
||
/// </summary>
|
||
public ColorConversionCodes ColorConversionCode { get; set; } = ColorConversionCodes.BGR2RGB;
|
||
|
||
public Scalar LowerColor { get; set; }
|
||
public Scalar UpperColor { get; set; }
|
||
|
||
/// <summary>
|
||
/// 符合的点的数量要求。可选,默认 1
|
||
/// </summary>
|
||
public int MatchCount { get; set; } = 1;
|
||
|
||
#endregion 颜色匹配
|
||
|
||
#region OCR文字识别
|
||
|
||
/// <summary>
|
||
/// OCR 引擎。可选,只有 Paddle。
|
||
/// </summary>
|
||
public OcrEngineTypes OcrEngine { get; set; } = OcrEngineTypes.Paddle;
|
||
|
||
/// <summary>
|
||
/// 部分文字识别结果不准确,进行替换。可选。
|
||
/// </summary>
|
||
public Dictionary<string, string[]> ReplaceDictionary { get; set; } = [];
|
||
|
||
/// <summary>
|
||
/// 包含匹配 (用于单个确认是否存在)
|
||
/// 多个值全匹配的情况下才算成功
|
||
/// 复杂情况请用下面的正则匹配
|
||
/// </summary>
|
||
public List<string> AllContainMatchText { get; set; } = [];
|
||
|
||
/// <summary>
|
||
/// 包含匹配(用于单个确认是否存在)
|
||
/// 一个值匹配就算成功
|
||
/// </summary>
|
||
public List<string> OneContainMatchText { get; set; } = [];
|
||
|
||
/// <summary>
|
||
/// 正则匹配(用于单个确认是否存在)
|
||
/// 多个值全匹配的情况下才算成功
|
||
/// </summary>
|
||
public List<string> RegexMatchText { get; set; } = [];
|
||
|
||
/// <summary>
|
||
/// 用于多个OCR结果的匹配
|
||
/// </summary>
|
||
public string Text { get; set; } = string.Empty;
|
||
|
||
public static RecognitionObject Ocr(double x, double y, double w, double h)
|
||
{
|
||
return new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.Ocr,
|
||
RegionOfInterest = new Rect((int)Math.Round(x), (int)Math.Round(y), (int)Math.Round(w), (int)Math.Round(h))
|
||
};
|
||
}
|
||
|
||
public static RecognitionObject OcrMatch(double x, double y, double w, double h, params string[] matchTexts)
|
||
{
|
||
return new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.OcrMatch,
|
||
RegionOfInterest = new Rect((int)Math.Round(x), (int)Math.Round(y), (int)Math.Round(w), (int)Math.Round(h)),
|
||
OneContainMatchText = matchTexts?.ToList() ?? []
|
||
};
|
||
}
|
||
|
||
public static RecognitionObject Ocr(Rect rect)
|
||
{
|
||
return new RecognitionObject
|
||
{
|
||
RecognitionType = RecognitionTypes.Ocr,
|
||
RegionOfInterest = rect
|
||
};
|
||
}
|
||
|
||
public static RecognitionObject OcrThis = new()
|
||
{
|
||
RecognitionType = RecognitionTypes.Ocr
|
||
};
|
||
|
||
#endregion OCR文字识别
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 克隆当前 RecognitionObject 实例
|
||
/// </summary>
|
||
/// <returns>克隆的 RecognitionObject 实例</returns>
|
||
public RecognitionObject Clone()
|
||
{
|
||
var cloned = new RecognitionObject
|
||
{
|
||
RecognitionType = this.RecognitionType,
|
||
RegionOfInterest = this.RegionOfInterest,
|
||
Name = this.Name,
|
||
|
||
// 模板匹配相关属性
|
||
TemplateImageMat = this.TemplateImageMat, // 注意:Mat 是引用类型,克隆后仍然指向同一内存
|
||
TemplateImageGreyMat = this.TemplateImageGreyMat, // 注意:Mat 是引用类型,克隆后仍然指向同一内存
|
||
Threshold = this.Threshold,
|
||
Use3Channels = this.Use3Channels,
|
||
TemplateMatchMode = this.TemplateMatchMode,
|
||
UseMask = this.UseMask,
|
||
MaskColor = this.MaskColor,
|
||
MaskMat = this.MaskMat, // 注意:Mat 是引用类型,克隆后仍然指向同一内存
|
||
DrawOnWindow = this.DrawOnWindow,
|
||
DrawOnWindowPen = new Pen(this.DrawOnWindowPen.Color, this.DrawOnWindowPen.Width),
|
||
MaxMatchCount = this.MaxMatchCount,
|
||
|
||
// 颜色匹配相关属性
|
||
ColorConversionCode = this.ColorConversionCode,
|
||
LowerColor = this.LowerColor,
|
||
UpperColor = this.UpperColor,
|
||
MatchCount = this.MatchCount,
|
||
|
||
// OCR相关属性
|
||
OcrEngine = this.OcrEngine,
|
||
ReplaceDictionary = this.ReplaceDictionary, // 不克隆字典,因为字典通常是不可变的
|
||
AllContainMatchText = this.AllContainMatchText, // 不克隆
|
||
OneContainMatchText = this.OneContainMatchText, // 不克隆
|
||
RegexMatchText = this.RegexMatchText, // 不克隆
|
||
Text = this.Text
|
||
};
|
||
|
||
return cloned;
|
||
}
|
||
}
|