// using BetterGenshinImpact.Core.Recognition; // using BetterGenshinImpact.Core.Recognition.OCR; // using BetterGenshinImpact.Core.Recognition.OpenCv; // using BetterGenshinImpact.Helpers; // using BetterGenshinImpact.Helpers.Extensions; // using BetterGenshinImpact.View.Drawable; // using OpenCvSharp; // using OpenCvSharp.Extensions; // using Sdcb.PaddleOCR; // using System; // using System.Collections.Generic; // using System.Drawing; // using System.Linq; // using System.Text.RegularExpressions; // using Point = OpenCvSharp.Point; // // namespace BetterGenshinImpact.GameTask.Model; // // /// // /// 屏幕上的某块矩形区域或者点,方便用于识别以及坐标系转换 // /// 一般层级如下: // /// 桌面 -> 窗口捕获区域 -> 窗口内的矩形区域 -> 矩形区域内识别到的图像区域 // /// // [Serializable] // public class RectArea : IDisposable // { // /// // /// 当前所属的坐标系层级 // /// 桌面 = 0 // /// 游戏窗口 = 1 // /// 顶层一定是桌面 // /// Desktop -> GameCaptureArea -> Part -> ? // /// // public int CoordinateLevelNum { get; set; } = 0; // // public int X { get; set; } // public int Y { get; set; } // public int Width { get; set; } // public int Height { get; set; } // // public RectArea? Owner { get; set; } // // private Bitmap? _srcBitmap; // private Mat? _srcMat; // private Mat? _srcGreyMat; // // public Bitmap SrcBitmap // { // get // { // if (_srcBitmap != null) // { // return _srcBitmap; // } // // if (_srcMat == null) // { // throw new Exception("SrcBitmap和SrcMat不能同时为空"); // } // // _srcBitmap = _srcMat.ToBitmap(); // return _srcBitmap; // } // } // // public Mat SrcMat // { // get // { // if (_srcMat != null) // { // return _srcMat; // } // // if (_srcBitmap == null) // { // throw new Exception("SrcBitmap和SrcMat不能同时为空"); // } // // _srcMat = _srcBitmap.ToMat(); // return _srcMat; // } // } // // public Mat SrcGreyMat // { // get // { // _srcGreyMat ??= new Mat(); // Cv2.CvtColor(SrcMat, _srcGreyMat, ColorConversionCodes.BGR2GRAY); // return _srcGreyMat; // } // } // // /// // /// 存放OCR识别的结果文本 // /// // public string Text { get; set; } = string.Empty; // // public RectArea() // { // } // // public RectArea(int x, int y, int width, int height, RectArea? owner = null) // { // X = x; // Y = y; // Width = width; // Height = height; // Owner = owner; // CoordinateLevelNum = owner?.CoordinateLevelNum + 1 ?? 0; // } // // public RectArea(Bitmap bitmap, int x, int y, RectArea? owner = null) : this(x, y, 0, 0, owner) // { // _srcBitmap = bitmap; // Width = bitmap.Width; // Height = bitmap.Height; // } // // public RectArea(Mat mat, int x, int y, RectArea? owner = null) : this(x, y, 0, 0, owner) // { // _srcMat = mat; // Width = mat.Width; // Height = mat.Height; // } // // public RectArea(Mat mat, Point p, RectArea? owner = null) : this(mat, p.X, p.Y, owner) // { // } // // public RectArea(Rect rect, RectArea? owner = null) : this(rect.X, rect.Y, rect.Width, rect.Height, owner) // { // } // // //public RectArea(Mat mat, RectArea? owner = null) // //{ // // _srcMat = mat; // // X = 0; // // Y = 0; // // Width = mat.Width; // // Height = mat.Height; // // Owner = owner; // // CoordinateLevelNum = owner?.CoordinateLevelNum + 1 ?? 0; // //} // // public Rect ConvertRelativePositionTo(int coordinateLevelNum) // { // int newX = X, newY = Y; // var father = Owner; // while (true) // { // if (father == null) // { // throw new Exception("找不到对应的坐标系"); // } // // if (father.CoordinateLevelNum == coordinateLevelNum) // { // break; // } // // newX += father.X; // newY += father.Y; // // father = father.Owner; // } // // return new Rect(newX, newY, Width, Height); // } // // public Rect ConvertRelativePositionToDesktop() // { // return ConvertRelativePositionTo(0); // } // // public Rect ConvertRelativePositionToCaptureArea() // { // return ConvertRelativePositionTo(1); // } // // public Rect ToRect() // { // return new Rect(X, Y, Width, Height); // } // // public bool PositionIsInDesktop() // { // return CoordinateLevelNum == 0; // } // // public bool IsEmpty() // { // return Width == 0 && Height == 0 && X == 0 && Y == 0; // } // // /// // /// 语义化包装 // /// // /// // public bool IsExist() // { // return !IsEmpty(); // } // // public bool HasImage() // { // return _srcBitmap != null || _srcMat != null; // } // // /// // /// 在本区域内查找最优识别对象 // /// // /// // /// 成功找到后做什么 // /// 失败后做什么 // /// 返回最优的一个识别结果RectArea // /// // public RectArea Find(RecognitionObject ro, Action? successAction = null, Action? failAction = null) // { // if (!HasImage()) // { // throw new Exception("当前对象内没有图像内容,无法完成 Find 操作"); // } // // if (ro == null) // { // throw new Exception("识别对象不能为null"); // } // // if (RecognitionTypes.TemplateMatch.Equals(ro.RecognitionType)) // { // Mat roi; // Mat? template; // if (ro.Use3Channels) // { // template = ro.TemplateImageMat; // roi = SrcMat; // Cv2.CvtColor(roi, roi, ColorConversionCodes.BGRA2BGR); // } // else // { // template = ro.TemplateImageGreyMat; // roi = SrcGreyMat; // } // // if (template == null) // { // throw new Exception($"[TemplateMatch]识别对象{ro.Name}的模板图片不能为null"); // } // // if (ro.RegionOfInterest != Rect.Empty) // { // // 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)) // // { // // Logger.LogError("输入图像{W1}x{H1},模板ROI位置{X2}x{Y2},区域{H2}x{W2},边界溢出!", roi.Width, roi.Height, 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 = new RectArea(template.Clone(), p.X + ro.RegionOfInterest.X, p.Y + ro.RegionOfInterest.Y, this); // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.PutRect(ro.Name, newRa // .ConvertRelativePositionToCaptureArea() // .ToRectDrawable(ro.DrawOnWindowPen, ro.Name)); // } // // successAction?.Invoke(newRa); // return newRa; // } // else // { // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.RemoveRect(ro.Name); // } // // failAction?.Invoke(); // return new RectArea(); // } // } // else if (RecognitionTypes.OcrMatch.Equals(ro.RecognitionType)) // { // if (ro.AllContainMatchText.Count == 0 && ro.OneContainMatchText.Count == 0 && ro.RegexMatchText.Count == 0) // { // throw new Exception($"[OCR]识别对象{ro.Name}的匹配文本不能全为空"); // } // // var roi = SrcGreyMat; // if (ro.RegionOfInterest != Rect.Empty) // { // roi = new Mat(SrcGreyMat, ro.RegionOfInterest); // } // // var result = OcrFactory.Paddle.OcrResult(roi); // var text = StringUtils.RemoveAllSpace(result.Text); // // 替换可能出错的文本 // foreach (var entry in ro.ReplaceDictionary) // { // foreach (var replaceStr in entry.Value) // { // text = text.Replace(entry.Key, replaceStr); // } // } // // int successContainCount = 0, successRegexCount = 0; // bool successOneContain = false; // // 包含匹配 全部包含才成功 // foreach (var s in ro.AllContainMatchText) // { // if (text.Contains(s)) // { // successContainCount++; // } // } // // // 包含匹配 包含一个就成功 // foreach (var s in ro.OneContainMatchText) // { // if (text.Contains(s)) // { // successOneContain = true; // break; // } // } // // // 正则匹配 // foreach (var re in ro.RegexMatchText) // { // if (Regex.IsMatch(text, re)) // { // successRegexCount++; // } // } // // if (successContainCount == ro.AllContainMatchText.Count // && successRegexCount == ro.RegexMatchText.Count // && (ro.OneContainMatchText.Count == 0 || successOneContain)) // { // var newRa = new RectArea(roi, X + ro.RegionOfInterest.X, Y + ro.RegionOfInterest.Y, this); // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, result.ToRectDrawableListOffset(ro.RegionOfInterest.X, ro.RegionOfInterest.Y)); // } // // successAction?.Invoke(newRa); // return newRa; // } // else // { // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.RemoveRect(ro.Name); // } // // failAction?.Invoke(); // return new RectArea(); // } // } // else // { // throw new Exception($"RectArea不支持的识别类型{ro.RecognitionType}"); // } // } // // /// // /// 在本区域内查找识别对象 // /// 返回所有找到的结果 // /// 仅支持: // /// RecognitionTypes.TemplateMatch // /// RecognitionTypes.Ocr // /// // /// // /// 成功找到后做什么 // /// 失败后做什么 // /// 无内嵌图片的 RectArea List // /// // public List FindMulti(RecognitionObject ro, Action>? successAction = null, Action? failAction = null) // { // if (!HasImage()) // { // throw new Exception("当前对象内没有图像内容,无法完成 Find 操作"); // } // // if (ro == null) // { // throw new Exception("识别对象不能为null"); // } // // if (RecognitionTypes.TemplateMatch.Equals(ro.RecognitionType)) // { // Mat roi; // Mat? template; // if (ro.Use3Channels) // { // template = ro.TemplateImageMat; // roi = SrcMat; // Cv2.CvtColor(roi, roi, ColorConversionCodes.BGRA2BGR); // } // else // { // template = ro.TemplateImageGreyMat; // roi = SrcGreyMat; // } // // if (template == null) // { // throw new Exception($"[TemplateMatch]识别对象{ro.Name}的模板图片不能为null"); // } // // if (ro.RegionOfInterest != Rect.Empty) // { // // TODO roi 是可以加缓存的 // roi = new Mat(roi, ro.RegionOfInterest); // } // // var rectList = MatchTemplateHelper.MatchOnePicForOnePic(roi, template, ro.TemplateMatchMode, ro.MaskMat, ro.Threshold); // if (rectList.Count > 0) // { // var resRaList = rectList.Select(r => this.Derive(r + new Point(ro.RegionOfInterest.X, ro.RegionOfInterest.Y))).ToList(); // // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, // resRaList.Select(ra => ra.ConvertRelativePositionToCaptureArea() // .ToRectDrawable(ro.DrawOnWindowPen, ro.Name)).ToList()); // } // // successAction?.Invoke(resRaList); // return resRaList; // } // else // { // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.RemoveRect(ro.Name); // } // // failAction?.Invoke(); // return []; // } // } // else if (RecognitionTypes.Ocr.Equals(ro.RecognitionType)) // { // var roi = SrcGreyMat; // if (ro.RegionOfInterest != Rect.Empty) // { // roi = new Mat(SrcGreyMat, ro.RegionOfInterest); // } // // var result = OcrFactory.Paddle.OcrResult(roi); // // if (result.Regions.Length > 0) // { // var resRaList = result.Regions.Select(r => // { // var newRa = this.Derive(r.Rect.BoundingRect() + new Point(ro.RegionOfInterest.X, ro.RegionOfInterest.Y)); // newRa.Text = r.Text; // return newRa; // }).ToList(); // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.PutOrRemoveRectList(ro.Name, result.ToRectDrawableListOffset(ro.RegionOfInterest.X, ro.RegionOfInterest.Y)); // } // // successAction?.Invoke(resRaList); // return resRaList; // } // else // { // if (ro.DrawOnWindow && !string.IsNullOrEmpty(ro.Name)) // { // VisionContext.Instance().DrawContent.RemoveRect(ro.Name); // } // // failAction?.Invoke(); // return []; // } // } // else // { // throw new Exception($"RectArea多目标识别不支持的识别类型{ro.RecognitionType}"); // } // } // // /// // /// 找到识别对象并点击中心 // /// // /// // /// // public RectArea ClickCenter(RecognitionObject ro) // { // var ra = Find(ro); // if (!ra.IsEmpty()) // { // ra.ClickCenter(); // } // // return ra; // } // // /// // /// 当前对象点击中心 // /// // public void ClickCenter() // { // // 把坐标系转换到桌面再点击 // if (CoordinateLevelNum == 0) // { // ToRect().ClickCenter(); // } // else // { // ConvertRelativePositionToDesktop().ClickCenter(); // } // } // // /// // /// 剪裁图片 // /// // /// // /// // public RectArea Crop(Rect rect) // { // return new RectArea(SrcMat[rect], rect.X, rect.Y, this); // } // // /// // /// 派生区域(无图片) // /// // /// // /// // public RectArea Derive(Rect rect) // { // return new RectArea(rect, this); // } // // /// // /// 派生2x2区域(无图片) // /// 方便用于点击 // /// // /// // /// // /// // public RectArea DerivePoint(int x, int y) // { // return new RectArea(new Rect(x, y, 2, 2), this); // } // // /// // /// OCR识别 // /// // /// 所有结果 // public PaddleOcrResult OcrResult() // { // return OcrFactory.Paddle.OcrResult(SrcGreyMat); // } // // public void Dispose() // { // _srcGreyMat?.Dispose(); // _srcMat?.Dispose(); // _srcBitmap?.Dispose(); // } // }