优化自动拾取的预处理环节,优化最终文字展现,使自动拾取OCR识别更加稳定 (#2211)

This commit is contained in:
辉鸭蛋
2025-09-17 01:46:41 +08:00
committed by GitHub
parent cd69a255dc
commit af707f304c
3 changed files with 295 additions and 15 deletions

View File

@@ -0,0 +1,79 @@
using System;
using System.Linq;
namespace BetterGenshinImpact.GameTask.AutoPick;
using OpenCvSharp;
public static class TextRectExtractor
{
/// <summary>
/// 从图片中提取文字范围(假定文字从最左边贴边开始,向右连续)
/// 结果矩形固定 x=0,y=0,h=原图高度,只计算连续文字宽度。
/// </summary>
public static Rect GetTextBoundingRect(Mat textMat, out Mat bin)
{
// 转换为灰度图
Mat gray = new Mat();
if (textMat.Channels() == 3)
{
Cv2.CvtColor(textMat, gray, ColorConversionCodes.BGR2GRAY);
}
else
{
gray = textMat.Clone();
}
// 使用阈值160进行二值化处理
bin = new Mat();
Cv2.Threshold(gray, bin, 160, 255, ThresholdTypes.Binary);
// 形态学操作:先腐蚀后膨胀,去除噪点并保持文字完整
Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
Cv2.Erode(bin, bin, kernel, iterations: 1);
Cv2.Dilate(bin, bin, kernel, iterations: 2);
kernel.Dispose();
gray.Dispose();
return ProjectionRect(textMat, bin);
}
private static Rect ProjectionRect(Mat textMat, Mat bin)
{
// 投影:对行做 ReduceSum得到 1 x width 的列和
using var projection = new Mat();
Cv2.Reduce(bin, projection, 0, ReduceTypes.Sum, MatType.CV_32S);
int width = projection.Cols;
projection.GetArray(out int[] colSums);
int maxGap = 30; // 允许的最大连续空列数
int gapCount = 0;
int lastNonEmpty = -1;
for (int x = 0; x < width; x++)
{
bool hasInk = colSums[x] > 0;
if (hasInk)
{
lastNonEmpty = x;
gapCount = 0;
}
else
{
gapCount++;
if (gapCount > maxGap)
{
break;
}
}
}
if (lastNonEmpty == -1)
{
// 没有检测到文字
return new Rect();
}
Rect boundingRect = new Rect(0, 0, lastNonEmpty, textMat.Height);
return boundingRect;
}
}