mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
refactor: 干员名识别封装
This commit is contained in:
@@ -3606,10 +3606,10 @@
|
||||
"bin_expansion",
|
||||
"trim_threshold_low",
|
||||
"trim_threshold_high",
|
||||
"左侧收缩时检测图的底部收缩",
|
||||
"左侧收缩时检测图的底部屏蔽高度",
|
||||
"左侧收缩时连续n像素低于bin_thresh"
|
||||
],
|
||||
"specialParams": [140, 2, 0, 0, -3, 10]
|
||||
"specialParams": [140, 2, 0, 0, 3, 10]
|
||||
},
|
||||
"BattleQuickFormationSkill1": {
|
||||
"algorithm": "JustReturn",
|
||||
|
||||
@@ -297,6 +297,7 @@
|
||||
<ClInclude Include="Vision\FeatureMatcher.h" />
|
||||
<ClInclude Include="Utils\LibraryHolder.hpp" />
|
||||
<ClInclude Include="Vision\Battle\SupportListAnalyzer.h" />
|
||||
<ClInclude Include="Vision\Miscellaneous\OperNameAnalyzer.h" />
|
||||
<ClInclude Include="Vision\Roguelike\RoguelikeParameterAnalyzer.h" />
|
||||
<ClInclude Include="Vision\VisionHelper.h" />
|
||||
<ClInclude Include="Vision\Battle\BattleFormationAnalyzer.h" />
|
||||
@@ -492,6 +493,7 @@
|
||||
<ClCompile Include="Vision\Battle\SupportListAnalyzer.cpp" />
|
||||
<ClCompile Include="Vision\Config\FeatureMatcherConfig.cpp" />
|
||||
<ClCompile Include="Vision\FeatureMatcher.cpp" />
|
||||
<ClCompile Include="Vision\Miscellaneous\OperNameAnalyzer.cpp" />
|
||||
<ClCompile Include="Vision\Roguelike\RoguelikeParameterAnalyzer.cpp" />
|
||||
<ClCompile Include="Vision\VisionHelper.cpp" />
|
||||
<ClCompile Include="Vision\Battle\BattleFormationAnalyzer.cpp" />
|
||||
|
||||
@@ -1334,6 +1334,9 @@
|
||||
<ClInclude Include="Task\Roguelike\RoguelikeInputSeedTaskPlugin.h">
|
||||
<Filter>Source\Task\Roguelike</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Vision\Miscellaneous\OperNameAnalyzer.h">
|
||||
<Filter>Source\Vision\Miscellaneous</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vision\VisionHelper.cpp">
|
||||
@@ -1851,6 +1854,9 @@
|
||||
<ClCompile Include="Task\Roguelike\RoguelikeInputSeedTaskPlugin.cpp">
|
||||
<Filter>Source\Task\Roguelike</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Vision\Miscellaneous\OperNameAnalyzer.cpp">
|
||||
<Filter>Source\Vision\Miscellaneous</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="meojson.natvis" />
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "UseSupportUnitTaskPlugin.h"
|
||||
#include "Utils/ImageIo.hpp"
|
||||
#include "Utils/Logger.hpp"
|
||||
#include "Vision/Miscellaneous/OperNameAnalyzer.h"
|
||||
#include "Vision/MultiMatcher.h"
|
||||
#include "Vision/RegionOCRer.h"
|
||||
|
||||
@@ -353,7 +354,7 @@ std::vector<asst::BattleFormationTask::QuickFormationOper>
|
||||
{
|
||||
const auto& ocr_replace = Task.get<OcrTaskInfo>("CharsNameOcrReplace");
|
||||
std::vector<asst::BattleFormationTask::QuickFormationOper> opers_result;
|
||||
cv::Mat select, ocr, gray, bin;
|
||||
cv::Mat select;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
std::string task_name = "BattleQuickFormation-OperNameFlag" + std::to_string(i);
|
||||
|
||||
@@ -364,46 +365,14 @@ std::vector<asst::BattleFormationTask::QuickFormationOper>
|
||||
continue;
|
||||
}
|
||||
for (const auto& flag : multi.get_result()) {
|
||||
auto roi = flag.rect.move(ocr_task->rect_move);
|
||||
if (roi.x < 0) {
|
||||
roi.x = 0;
|
||||
roi.width = roi.width + roi.x;
|
||||
}
|
||||
if (roi.y < 0) {
|
||||
roi.y = 0;
|
||||
roi.height = roi.height + roi.y;
|
||||
}
|
||||
if (roi.x + roi.width > image.cols) {
|
||||
roi.width = image.cols - roi.x;
|
||||
}
|
||||
if (roi.y + roi.height > image.rows) {
|
||||
roi.height = image.rows - roi.y;
|
||||
}
|
||||
ocr = make_roi(image, roi);
|
||||
cv::cvtColor(ocr, gray, cv::COLOR_BGR2GRAY);
|
||||
cv::inRange(gray, ocr_task->special_params[0], 255, bin);
|
||||
for (int r = bin.cols - 1; r >= 0; --r) {
|
||||
if (cv::hasNonZero(bin.col(r))) { // 右边界向左收缩
|
||||
bin = bin.adjustROI(0, 0, 0, -(bin.cols - r - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bin = bin.adjustROI(0, ocr_task->special_params[4], 0, 0); // 底部收缩排除白线
|
||||
int width = ocr_task->special_params[5];
|
||||
for (int r = bin.cols - width - 1; r >= 0; --r) {
|
||||
if (!cv::hasNonZero(bin.colRange(r, r + width))) { // 左边界排除无文字区域
|
||||
ocr = ocr.adjustROI(0, 0, -r - 3, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegionOCRer region(ocr);
|
||||
OperNameAnalyzer region(image);
|
||||
region.set_task_info(ocr_task);
|
||||
region.set_roi(asst::Rect(0, 0, ocr.cols, ocr.rows));
|
||||
region.set_roi(flag.rect.move(ocr_task->rect_move));
|
||||
region.set_bin_threshold(ocr_task->special_params[0]);
|
||||
region.set_bin_expansion(ocr_task->special_params[1]);
|
||||
region.set_bin_trim_threshold(ocr_task->special_params[2], ocr_task->special_params[3]);
|
||||
region.set_bottom_line_height(ocr_task->special_params[4]);
|
||||
region.set_width_threshold(ocr_task->special_params[5]);
|
||||
region.set_replace(ocr_replace->replace_map, ocr_replace->replace_full);
|
||||
region.set_use_raw(true);
|
||||
if (!region.analyze()) [[unlikely]] {
|
||||
|
||||
40
src/MaaCore/Vision/Miscellaneous/OperNameAnalyzer.cpp
Normal file
40
src/MaaCore/Vision/Miscellaneous/OperNameAnalyzer.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "OperNameAnalyzer.h"
|
||||
|
||||
#include "Utils/NoWarningCV.h"
|
||||
#include "Vision/RegionOCRer.h"
|
||||
|
||||
asst::OperNameAnalyzer::ResultOpt asst::OperNameAnalyzer::analyze() const
|
||||
{
|
||||
cv::Mat gray, bin;
|
||||
cv::Mat ocr = make_roi(m_image, m_roi);
|
||||
cv::cvtColor(ocr, gray, cv::COLOR_BGR2GRAY);
|
||||
cv::inRange(gray, m_params.bin_threshold_lower, m_params.bin_threshold_upper, bin);
|
||||
for (int r = bin.cols - 1; r >= 0; --r) {
|
||||
if (cv::hasNonZero(bin.col(r))) { // 右边界向左收缩
|
||||
bin = bin.adjustROI(0, 0, 0, -(bin.cols - r - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bin = bin.adjustROI(0, -m_bottom_line_height, 0, 0); // 底部收缩排除白线
|
||||
int move = 0;
|
||||
for (int r = bin.cols - m_width_threshold - 1; r >= 0; --r) {
|
||||
if (!cv::hasNonZero(bin.colRange(r, r + m_width_threshold))) { // 左边界排除无文字区域
|
||||
move = r + m_width_threshold - 3;
|
||||
ocr = ocr.adjustROI(0, 0, -move, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegionOCRer region(ocr);
|
||||
region.set_params(m_params);
|
||||
region.set_use_raw(true);
|
||||
if (region.analyze()) {
|
||||
m_result = region.get_result();
|
||||
m_result.rect.x += move; // 修正偏移
|
||||
m_result.rect = m_roi.move(m_result.rect);
|
||||
return m_result;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
42
src/MaaCore/Vision/Miscellaneous/OperNameAnalyzer.h
Normal file
42
src/MaaCore/Vision/Miscellaneous/OperNameAnalyzer.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <optional>
|
||||
#include "Vision/Config/OCRerConfig.h"
|
||||
#include "Vision/VisionHelper.h"
|
||||
#include "Vision/OCRer.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
class OperNameAnalyzer : public VisionHelper, public OCRerConfig
|
||||
{
|
||||
public:
|
||||
using Result = OCRer::Result;
|
||||
using ResultOpt = std::optional<Result>;
|
||||
|
||||
public:
|
||||
using VisionHelper::VisionHelper;
|
||||
virtual ~OperNameAnalyzer() override = default;
|
||||
|
||||
ResultOpt analyze() const;
|
||||
|
||||
void set_use_raw(bool use_raw) { m_use_raw = use_raw; }
|
||||
|
||||
void set_bottom_line_height(int height) { m_bottom_line_height = height; }
|
||||
|
||||
void set_width_threshold(int threshold) { m_width_threshold = threshold; }
|
||||
|
||||
// FIXME: 老接口太难重构了,先弄个这玩意兼容下,后续慢慢全删掉
|
||||
const auto& get_result() const noexcept { return m_result; }
|
||||
|
||||
protected:
|
||||
using OCRerConfig::set_without_det;
|
||||
|
||||
virtual void _set_roi(const Rect& roi) override { set_roi(roi); }
|
||||
|
||||
private:
|
||||
// FIXME: 老接口太难重构了,先弄个这玩意兼容下,后续慢慢全删掉
|
||||
mutable Result m_result;
|
||||
bool m_use_raw = true;
|
||||
int m_bottom_line_height = 3; // 底部线条高度
|
||||
int m_width_threshold = 5; // 宽度阈值
|
||||
};
|
||||
}; // namespace asst
|
||||
Reference in New Issue
Block a user