mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
* 分解圣遗物基础设施建设 * 分解圣遗物独立任务基本功能完成:单独的启动按钮,正则表达式逐一筛选;代码文件整理到单独的文件夹 * 自动分解5星圣遗物功能初步完成 * 修复上次修改快速分解产生的问题,主要点击分解按钮时的bug,还有与五星分解步骤衔接的问题 * 针对切换队伍时,多语言识别效果不佳的情况,将用户设定的队伍名作为正则表达式进行模糊匹配,并在LogInfo输出相关提示;传送任务对任务取消进行单独的异常处理 * 一个便于测试分解圣遗物OCR识别和正则匹配结果的弹窗
127 lines
3.7 KiB
C#
127 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using OpenCvSharp;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
|
|
namespace BetterGenshinImpact.Core.Recognition.OpenCv;
|
|
|
|
public class OpenCvCommonHelper
|
|
{
|
|
/// <summary>
|
|
/// 计算灰度图中某个颜色的像素个数
|
|
/// </summary>
|
|
/// <param name="mat"></param>
|
|
/// <param name="color"></param>
|
|
/// <returns></returns>
|
|
public static int CountGrayMatColor(Mat mat, byte color)
|
|
{
|
|
Debug.Assert(mat.Depth() == MatType.CV_8U);
|
|
return SplitChannal(mat, m => CountGrayMatColorC1(m, color)).Sum();
|
|
}
|
|
|
|
private static IEnumerable<T> SplitChannal<T>(Mat mat, Func<Mat, T> func)
|
|
{
|
|
if (mat.Empty()) return [];
|
|
if (mat.Channels() == 1)
|
|
{
|
|
return [func.Invoke(mat)];
|
|
}
|
|
|
|
Mat[]? channels = null;
|
|
try
|
|
{
|
|
channels = mat.Split();
|
|
return channels.AsParallel().Select(func);
|
|
}
|
|
finally
|
|
{
|
|
// 释放所有分离出的通道内存
|
|
if (channels is not null)
|
|
foreach (var ch in channels)
|
|
ch.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 仅限单通道,统计等于color的颜色
|
|
/// </summary>
|
|
/// <param name="mat">矩阵</param>
|
|
/// <param name="color">值</param>
|
|
/// <returns></returns>
|
|
public static int CountGrayMatColorC1(Mat mat, byte color)
|
|
{
|
|
Debug.Assert(mat.Depth() == MatType.CV_8U);
|
|
Debug.Assert(mat.Channels() == 1);
|
|
using var dst = new Mat();
|
|
Cv2.Compare(mat, color, dst, CmpType.EQ);
|
|
return Cv2.CountNonZero(dst);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 仅限单通道,统计颜色在lowColor和highColor中范围
|
|
/// </summary>
|
|
/// <param name="mat">矩阵</param>
|
|
/// <param name="lowColor">低</param>
|
|
/// <param name="highColor">高</param>
|
|
/// <returns></returns>
|
|
public static int CountGrayMatColorC1(Mat mat, byte lowColor, byte highColor)
|
|
{
|
|
using var mask = new Mat();
|
|
// 使用InRange直接生成二值掩膜
|
|
Cv2.InRange(mat, new Scalar(lowColor), new Scalar(highColor), mask);
|
|
return Cv2.CountNonZero(mask);
|
|
}
|
|
|
|
public static int CountGrayMatColor(Mat mat, byte lowColor, byte highColor)
|
|
{
|
|
return SplitChannal(mat, m => CountGrayMatColorC1(m, lowColor, highColor)).Sum();
|
|
}
|
|
|
|
public static Mat Threshold(Mat src, Scalar low, Scalar high)
|
|
{
|
|
using var mask = new Mat();
|
|
using var rgbMat = new Mat();
|
|
|
|
Cv2.CvtColor(src, rgbMat, ColorConversionCodes.BGR2RGB);
|
|
Cv2.InRange(rgbMat, low, high, mask);
|
|
// Cv2.Threshold(mask, mask, 0, 255, ThresholdTypes.Binary); //二值化 //不需要
|
|
return mask.Clone();
|
|
}
|
|
|
|
public static Mat InRangeHsv(Mat src, Scalar low, Scalar high)
|
|
{
|
|
using var rgbMat = src.CvtColor(ColorConversionCodes.BGR2HSV);
|
|
return rgbMat.InRange(low, high);
|
|
}
|
|
|
|
public static Mat InRangeHsvFull(Mat src, Scalar low, Scalar high)
|
|
{
|
|
using var rgbMat = src.CvtColor(ColorConversionCodes.BGR2HSV_FULL);
|
|
return rgbMat.InRange(low, high);
|
|
}
|
|
|
|
public static Scalar CommonHSV2OpenCVHSVFull(Scalar commonHSV)
|
|
{
|
|
return new Scalar(commonHSV.Val0 / 255 * 180, commonHSV.Val1 * 255, commonHSV.Val2 * 255);
|
|
}
|
|
|
|
public static Mat Threshold(Mat src, Scalar s)
|
|
{
|
|
return Threshold(src, s, s);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 和二值化的颜色刚好相反
|
|
/// </summary>
|
|
/// <param name="src"></param>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
public static Mat CreateMask(Mat src, Scalar s)
|
|
{
|
|
var mask = new Mat();
|
|
Cv2.InRange(src, s, s, mask);
|
|
return ~ mask;
|
|
}
|
|
}
|