mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-02 10:40:31 +08:00
Compare commits
9 Commits
docs/task-
...
rft/battle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
210eceb856 | ||
|
|
cd606c2ed0 | ||
|
|
47aca4d711 | ||
|
|
2bc4c99a34 | ||
|
|
51ecf9323c | ||
|
|
931a403b7c | ||
|
|
3d375d24a7 | ||
|
|
c7ef04f2ce | ||
|
|
43c1e4bece |
@@ -3905,6 +3905,16 @@
|
||||
"将干员滑动到场上的 最小滑动 duration"
|
||||
]
|
||||
},
|
||||
"BattleOperCache": {
|
||||
"template": "empty.png",
|
||||
"rectMove": [-38, 7, 55, 23],
|
||||
"specialParams_doc": [
|
||||
"前后帧干员role+cost区域RGB像素变化阈值",
|
||||
"变化像素数量阈值",
|
||||
"干员头像区域模板匹配分数阈值"
|
||||
],
|
||||
"specialParams": [10, 10, 98]
|
||||
},
|
||||
"BattleOpersFlag": {
|
||||
"templThreshold": 0.65,
|
||||
"roi": [0, 588, 1280, 18],
|
||||
|
||||
@@ -110,6 +110,8 @@ public:
|
||||
|
||||
private:
|
||||
void append_callback(AsstMsg msg, const json::value& detail);
|
||||
|
||||
public:
|
||||
static void append_callback_for_inst(AsstMsg msg, const json::value& detail, Assistant* inst);
|
||||
|
||||
private:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <future>
|
||||
#include <thread>
|
||||
|
||||
#include "Assistant.h"
|
||||
#include "Config/GeneralConfig.h"
|
||||
#include "Config/Miscellaneous/AvatarCacheManager.h"
|
||||
#include "Config/Miscellaneous/BattleDataConfig.h"
|
||||
@@ -96,16 +97,13 @@ bool asst::BattleHelper::abandon()
|
||||
return ProcessTask(this_task(), { "RoguelikeBattleExitBegin" }).run();
|
||||
}
|
||||
|
||||
bool asst::BattleHelper::update_deployment_(
|
||||
bool asst::BattleHelper::analyze_deployment(
|
||||
std::vector<battle::DeploymentOper>& cur_opers,
|
||||
const std::vector<battle::DeploymentOper>& old_deployment_opers,
|
||||
const bool analyze_unknown)
|
||||
{
|
||||
LogTraceFunction;
|
||||
|
||||
// ————————————————————————————————————————
|
||||
// 准备 lambda 函数
|
||||
// ————————————————————————————————————————
|
||||
// 设置干员名与部署位类型(近战/远程)
|
||||
auto set_oper_name = [&](DeploymentOper& oper, const std::string& name) {
|
||||
oper.name = name;
|
||||
@@ -113,16 +111,12 @@ bool asst::BattleHelper::update_deployment_(
|
||||
oper.is_usual_location = battle::get_role_usual_location(oper.role) == oper.location_type;
|
||||
};
|
||||
|
||||
// ————————————————————————————————————————
|
||||
// 初始化变量
|
||||
// ————————————————————————————————————————
|
||||
m_cur_deployment_opers = std::vector<battle::DeploymentOper>();
|
||||
m_cur_deployment_opers.reserve(cur_opers.size());
|
||||
std::vector<DeploymentOper> unknown_opers;
|
||||
|
||||
// ————————————————————————————————————————
|
||||
// 匹配已知干员
|
||||
// ————————————————————————————————————————
|
||||
for (auto& oper : cur_opers) {
|
||||
bool is_analyzed = false;
|
||||
if (!old_deployment_opers.empty()) {
|
||||
@@ -132,7 +126,7 @@ bool asst::BattleHelper::update_deployment_(
|
||||
views::transform([&](const battle::DeploymentOper& temp_oper) {
|
||||
return std::make_pair(temp_oper.name, temp_oper.avatar);
|
||||
});
|
||||
const auto& result = analyze_oper_with_cache(oper, avatar);
|
||||
const auto& result = match_oper_with_avatar(oper, avatar);
|
||||
if (result) {
|
||||
set_oper_name(oper, result->templ_info.name);
|
||||
remove_cooling_from_battlefield(oper);
|
||||
@@ -141,7 +135,7 @@ bool asst::BattleHelper::update_deployment_(
|
||||
}
|
||||
if (!is_analyzed) {
|
||||
// 之前的干员都没匹配上,那就把所有的干员都加进去
|
||||
const auto& result2 = analyze_oper_with_cache(oper, AvatarCache.get_avatars(oper.role));
|
||||
const auto& result2 = match_oper_with_avatar(oper, AvatarCache.get_avatars(oper.role));
|
||||
if (result2) {
|
||||
set_oper_name(oper, result2->templ_info.name);
|
||||
remove_cooling_from_battlefield(oper);
|
||||
@@ -163,9 +157,7 @@ bool asst::BattleHelper::update_deployment_(
|
||||
}
|
||||
}
|
||||
|
||||
// ————————————————————————————————————————
|
||||
// 匹配未知非冷却干员
|
||||
// ————————————————————————————————————————
|
||||
if (ranges::count_if(unknown_opers, [](const DeploymentOper& it) { return !it.cooling; }) > 0) {
|
||||
// 一个都没匹配上的,挨个点开来看一下
|
||||
LogTraceScope("rec unknown opers");
|
||||
@@ -231,6 +223,7 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable, b
|
||||
}
|
||||
}
|
||||
|
||||
static cv::Mat image_prev; // 缓存的上次图像
|
||||
cv::Mat image = init || reusable.empty() ? m_inst_helper.ctrler()->get_image() : reusable;
|
||||
if (init) {
|
||||
auto draw_future = std::async(std::launch::async, [&]() { save_map(image); });
|
||||
@@ -245,14 +238,38 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable, b
|
||||
else {
|
||||
oper_analyzer.set_object_of_interest({ .deployment = true });
|
||||
}
|
||||
if (init) {
|
||||
image_prev = cv::Mat(); // 重新开始时清空上次图像
|
||||
}
|
||||
else {
|
||||
oper_analyzer.set_image_prev(image_prev);
|
||||
}
|
||||
auto oper_result_opt = oper_analyzer.analyze();
|
||||
if (!oper_result_opt) {
|
||||
image_prev = image.clone(); // 记录上次图像
|
||||
if (!oper_result_opt || oper_result_opt->deployment.status == BattlefieldMatcher::MatchStatus::Invalid) {
|
||||
check_in_battle(image);
|
||||
return false;
|
||||
}
|
||||
const auto old_deployment_opers = std::move(m_cur_deployment_opers);
|
||||
|
||||
if (!update_deployment_(oper_result_opt->deployment, old_deployment_opers, false)) {
|
||||
if (oper_result_opt->deployment.status == BattlefieldMatcher::MatchStatus::HitCache) {
|
||||
m_cur_deployment_opers = old_deployment_opers;
|
||||
for (const auto& oper : m_cur_deployment_opers) {
|
||||
Log.info(__FUNCTION__, "hit cache, oper count:", m_cur_deployment_opers.size(), "name:", oper.name);
|
||||
}
|
||||
if (m_cur_deployment_opers.empty()) {
|
||||
Log.info(__FUNCTION__, "hit cache, no oper");
|
||||
}
|
||||
Assistant::append_callback_for_inst(
|
||||
AsstMsg::SubTaskExtraInfo,
|
||||
json::value { { "what", "BattleCacheTest" },
|
||||
{ "details",
|
||||
{
|
||||
{ "hit", true },
|
||||
{ "score", oper_analyzer.get_score() },
|
||||
} } },
|
||||
m_inst_helper.inst());
|
||||
}
|
||||
else if (!analyze_deployment(oper_result_opt->deployment.value, old_deployment_opers, false)) {
|
||||
// 发现未知干员,暂停游戏后再重新识别干员
|
||||
do {
|
||||
pause();
|
||||
@@ -285,10 +302,32 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable, b
|
||||
check_in_battle(image);
|
||||
return false;
|
||||
}
|
||||
update_deployment_(oper_result_opt->deployment, old_deployment_opers, true);
|
||||
analyze_deployment(oper_result_opt->deployment.value, old_deployment_opers, true);
|
||||
pause();
|
||||
cancel_oper_selection();
|
||||
image = m_inst_helper.ctrler()->get_image();
|
||||
|
||||
std::vector<std::string> names;
|
||||
for (const auto& oper : oper_result_opt->deployment.value) {
|
||||
names.emplace_back(oper.name);
|
||||
}
|
||||
Log.info("miss cache with unknown, oper count:", m_cur_deployment_opers.size(), "name:", names);
|
||||
}
|
||||
else {
|
||||
std::vector<std::string> names;
|
||||
for (const auto& oper : oper_result_opt->deployment.value) {
|
||||
names.emplace_back(oper.name);
|
||||
}
|
||||
Log.info("miss cache, oper count:", m_cur_deployment_opers.size(), "name:", names);
|
||||
Assistant::append_callback_for_inst(
|
||||
AsstMsg::SubTaskExtraInfo,
|
||||
json::value { { "what", "BattleCacheTest" },
|
||||
{ "details",
|
||||
{
|
||||
{ "hit", false },
|
||||
{ "score", oper_analyzer.get_score() },
|
||||
} } },
|
||||
m_inst_helper.inst());
|
||||
}
|
||||
|
||||
if (init) {
|
||||
@@ -1002,7 +1041,7 @@ std::optional<asst::Rect> asst::BattleHelper::get_oper_rect_on_deployment(const
|
||||
template <typename T>
|
||||
requires asst::ranges::range<T> && asst::OperAvatarPair<asst::ranges::range_value_t<T>>
|
||||
std::optional<asst::BestMatcher::Result>
|
||||
asst::BattleHelper::analyze_oper_with_cache(const asst::battle::DeploymentOper& oper, T&& avatar_cache)
|
||||
asst::BattleHelper::match_oper_with_avatar(const asst::battle::DeploymentOper& oper, T&& avatar_cache)
|
||||
{
|
||||
BestMatcher avatar_analyzer(oper.avatar);
|
||||
avatar_analyzer.set_method(MatchMethod::Ccoeff);
|
||||
|
||||
@@ -47,9 +47,10 @@ protected:
|
||||
bool speed_up();
|
||||
bool abandon();
|
||||
|
||||
// 获取并分析部署区的干员
|
||||
bool update_deployment(bool init = false, const cv::Mat& reusable = cv::Mat(), bool need_oper_cost = false);
|
||||
// 更新部署区的干员,仅当存在未识别干员且不处于冷却中return false
|
||||
bool update_deployment_(
|
||||
// 分析部署区的干员, 拿到名字, 仅当存在未识别干员且不处于冷却中return false
|
||||
bool analyze_deployment(
|
||||
std::vector<battle::DeploymentOper>& cur_opers,
|
||||
const std::vector<battle::DeploymentOper>& old_deployment_opers,
|
||||
bool stop_on_unknown);
|
||||
@@ -96,10 +97,11 @@ protected:
|
||||
std::string analyze_detail_page_oper_name(const cv::Mat& image);
|
||||
std::optional<Rect> get_oper_rect_on_deployment(const std::string& name) const;
|
||||
|
||||
// 从干员头像list中, 匹配干员
|
||||
template <typename T>
|
||||
requires asst::ranges::range<T> && OperAvatarPair<asst::ranges::range_value_t<T>>
|
||||
std::optional<asst::BestMatcher::Result>
|
||||
analyze_oper_with_cache(const battle::DeploymentOper& oper, T&& avatar_cache);
|
||||
match_oper_with_avatar(const battle::DeploymentOper& oper, T&& avatar_cache);
|
||||
|
||||
// 从场上干员和已占用格子中移除冷却中的干员
|
||||
void remove_cooling_from_battlefield(const battle::DeploymentOper& oper);
|
||||
@@ -116,6 +118,7 @@ protected:
|
||||
std::unordered_map<std::string, std::chrono::steady_clock::time_point> m_last_use_skill_time;
|
||||
int m_camera_count = 0;
|
||||
std::pair<double, double> m_camera_shift = { 0., 0. };
|
||||
cv::Mat m_image_prev_for_deploy; // 缓存图像, 用于判断部署区干员是否变化, 仅用于更新部署区
|
||||
|
||||
/* 实时更新的数据 */
|
||||
bool m_in_battle = false;
|
||||
|
||||
@@ -259,7 +259,7 @@ bool asst::CombatRecordRecognitionTask::analyze_deployment()
|
||||
show_img(oper_analyzer);
|
||||
if (analyzed) {
|
||||
m_battle_start_frame = i;
|
||||
deployment = std::move(oper_result_opt->deployment);
|
||||
deployment = std::move(oper_result_opt->deployment.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -389,8 +389,8 @@ bool asst::CombatRecordRecognitionTask::slice_video()
|
||||
const auto& cur_opers = result_opt->deployment;
|
||||
bool continuity = true;
|
||||
int pre_distance = 0;
|
||||
for (auto iter = cur_opers.begin(); iter != cur_opers.end(); ++iter) {
|
||||
if (iter == cur_opers.begin()) {
|
||||
for (auto iter = cur_opers.value.begin(); iter != cur_opers.value.end(); ++iter) {
|
||||
if (iter == cur_opers.value.begin()) {
|
||||
continue;
|
||||
}
|
||||
int distance = std::abs(iter->rect.x - (iter - 1)->rect.x);
|
||||
@@ -402,7 +402,7 @@ bool asst::CombatRecordRecognitionTask::slice_video()
|
||||
|
||||
bool oper_is_clicked = !result_opt->speed_button || !result_opt->pause_button;
|
||||
bool oper_auto_retreat =
|
||||
in_segment && continuity && !m_clips.empty() && cur_opers.size() != m_clips.back().deployment.size();
|
||||
in_segment && continuity && !m_clips.empty() && cur_opers.value.size() != m_clips.back().deployment.size();
|
||||
|
||||
if (oper_is_clicked || oper_auto_retreat) {
|
||||
if (m_clips.empty()) {
|
||||
@@ -429,7 +429,7 @@ bool asst::CombatRecordRecognitionTask::slice_video()
|
||||
ClipInfo info;
|
||||
info.start_frame_index = i; // 后处理会加个 offset
|
||||
info.end_frame_index = i;
|
||||
info.deployment = cur_opers;
|
||||
info.deployment = cur_opers.value;
|
||||
info.start_frame = frame;
|
||||
m_clips.emplace_back(std::move(info));
|
||||
|
||||
|
||||
@@ -23,6 +23,31 @@ asst::DebugTask::DebugTask(const AsstCallback& callback, Assistant* inst) :
|
||||
|
||||
bool asst::DebugTask::run()
|
||||
{
|
||||
auto image = imread(utils::path("C:/users/status102/desktop/fight-.png"));
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
BattlefieldMatcher match(image);
|
||||
match.set_object_of_interest({ .deployment = true });
|
||||
auto result = match.analyze();
|
||||
if (!result) {
|
||||
Log.error("BattlefieldMatcher analyze failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time);
|
||||
Log.info(__FUNCTION__, "cost:", cost.count(), "ms");
|
||||
auto cd1 = imread(utils::path("C:\\Users\\status102\\desktop/deploy_cost0.png"));
|
||||
auto cd2 = imread(utils::path("C:\\Users\\status102\\desktop/deploy_cost1.png"));
|
||||
BattlefieldMatcher match(cd2);
|
||||
match.set_image_prev(cd1);
|
||||
match.set_object_of_interest({ .deployment = true });
|
||||
if (match.analyze()) {
|
||||
Log.info("active");
|
||||
}
|
||||
else {
|
||||
Log.info("inactive");
|
||||
}
|
||||
callback(AsstMsg::SubTaskCompleted, json::value { { "subtask", "DebugTask" } });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ bool asst::SSSBattleProcessTask::update_deployment_with_skip(const cv::Mat& reus
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_same_time).count() > 30000) {
|
||||
// 30s 能回 60 费,基本上已经到了挂机的时候,放缓检查的速度
|
||||
Log.trace("30s is unchanged and the waiting time is extended to 1s");
|
||||
interval_time = 1000;
|
||||
// interval_time = 1000;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -39,7 +39,7 @@ BattlefieldMatcher::ResultOpt BattlefieldMatcher::analyze() const
|
||||
result.pause_button = pause_button_analyze();
|
||||
if (!result.pause_button && !hp_flag_analyze() && !kills_flag_analyze() && !cost_symbol_analyze()) {
|
||||
// flag 表明当前画面是在战斗场景的,不在的就没必要识别了
|
||||
return std::nullopt;
|
||||
return std::nullopt; // 测试时注释
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +73,10 @@ BattlefieldMatcher::ResultOpt BattlefieldMatcher::analyze() const
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<battle::DeploymentOper> BattlefieldMatcher::deployment_analyze() const
|
||||
BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> BattlefieldMatcher::deployment_analyze() const
|
||||
{
|
||||
const auto& flag_task_ptr = Task.get("BattleOpersFlag");
|
||||
MultiMatcher flags_analyzer(m_image);
|
||||
flags_analyzer.set_task_info(flag_task_ptr);
|
||||
flags_analyzer.set_task_info("BattleOpersFlag");
|
||||
|
||||
#ifndef ASST_DEBUG
|
||||
flags_analyzer.set_log_tracing(false);
|
||||
@@ -89,6 +88,10 @@ std::vector<battle::DeploymentOper> BattlefieldMatcher::deployment_analyze() con
|
||||
}
|
||||
auto& flags = flag_opt.value();
|
||||
sort_by_horizontal_(flags);
|
||||
if (hit_deployment_cache(flags)) {
|
||||
Log.info("Hit deployment cache, skip analyze");
|
||||
return { .status = MatchStatus::HitCache };
|
||||
}
|
||||
|
||||
const Rect& click_move = Task.get("BattleOperClickRange")->rect_move;
|
||||
const Rect& role_move = Task.get("BattleOperRoleRange")->rect_move;
|
||||
@@ -156,7 +159,86 @@ std::vector<battle::DeploymentOper> BattlefieldMatcher::deployment_analyze() con
|
||||
oper_result.emplace_back(std::move(oper));
|
||||
}
|
||||
|
||||
return oper_result;
|
||||
return { .value = std::move(oper_result), .status = MatchStatus::Success };
|
||||
}
|
||||
|
||||
bool asst::BattlefieldMatcher::hit_deployment_cache(const asst::MultiMatcher::ResultsVec& flags) const
|
||||
{
|
||||
if (m_image_prev.empty() || m_image.cols != m_image_prev.cols || m_image.rows != m_image_prev.rows) {
|
||||
return false;
|
||||
}
|
||||
const auto& cache_task = Task.get("BattleOperCache");
|
||||
const Rect& click_move = Task.get("BattleOperClickRange")->rect_move;
|
||||
const Rect& avatar_move = Task.get("BattleOperAvatar")->rect_move;
|
||||
const auto& dist = [](const asst::Rect& a, const asst::Rect& b) {
|
||||
return std::sqrt(std::pow(a.x - b.x, 2) + std::pow(a.y - b.y, 2));
|
||||
};
|
||||
|
||||
MultiMatcher flags_prev_ana(m_image_prev);
|
||||
flags_prev_ana.set_task_info("BattleOpersFlag");
|
||||
flags_prev_ana.set_log_tracing(false);
|
||||
auto flags_prev_opt = flags_prev_ana.analyze();
|
||||
if (!flags_prev_opt) {
|
||||
return false; // 新图有干员, 但上一帧没有
|
||||
}
|
||||
auto& flags_prev = flags_prev_opt.value();
|
||||
if (flags.size() != flags_prev.size()) {
|
||||
return false; // 新图干员数量和上一帧不一致
|
||||
}
|
||||
sort_by_horizontal_(flags_prev);
|
||||
bool is_same = true;
|
||||
cv::Mat mask = cv::Mat(m_image.rows, m_image.cols, CV_8UC1, cv::Scalar(0));
|
||||
cv::Mat avai_image, avai_image_prev, cache_det;
|
||||
cv::Scalar avg, avg_prev;
|
||||
for (size_t i = 0; i < flags.size(); ++i) {
|
||||
if (dist(flags[i].rect, flags_prev[i].rect) > 3) {
|
||||
is_same = false;
|
||||
break; // 新图干员位置和上一帧不一致
|
||||
}
|
||||
|
||||
const auto& flag_res = flags[i];
|
||||
const auto& avatar_rect = flag_res.rect.move(click_move).move(avatar_move);
|
||||
mask(make_rect<cv::Rect>(avatar_rect)).setTo(cv::Scalar(255));
|
||||
|
||||
cv::absdiff(
|
||||
m_image(make_rect<cv::Rect>(flag_res.rect.move(cache_task->rect_move))),
|
||||
m_image_prev(make_rect<cv::Rect>(flag_res.rect.move(cache_task->rect_move))),
|
||||
cache_det);
|
||||
cv::inRange(cache_det, cv::Scalar::all(cache_task->special_params[0]), cv::Scalar::all(255), cache_det);
|
||||
int count = cv::countNonZero(cache_det);
|
||||
if (count > cache_task->special_params[1]) { // 用于区分干员可用状态变化
|
||||
Log.debug(__FUNCTION__, "oper cache changed, count:", count);
|
||||
is_same = false;
|
||||
break; // 新图干员缓存和上一帧不一致
|
||||
}
|
||||
}
|
||||
if (!is_same) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cv::Mat match;
|
||||
/*
|
||||
const auto& deploy_rect = Rect::bounding_box(
|
||||
flags.front().rect, // 首干员c标
|
||||
flags.front().rect.move(click_move).move(avatar_move), // 首干员头像
|
||||
flags.back().rect.move(click_move).move(avatar_move)); // 尾干员头像
|
||||
mask(make_rect<cv::Rect>(deploy_rect)).setTo(cv::Scalar(255));
|
||||
mask.rowRange(60, 84).setTo(cv::Scalar(0)); // 剔除cd时间的区域
|
||||
*/
|
||||
cv::Rect cut_rect = cv::boundingRect(mask);
|
||||
cv::matchTemplate(m_image(cut_rect), m_image_prev(cut_rect), match, cv::TM_SQDIFF_NORMED, mask(cut_rect));
|
||||
double score;
|
||||
cv::minMaxLoc(match, nullptr, &score);
|
||||
double threshold = static_cast<double>(cache_task->special_params[2]) / 100;
|
||||
if ((1 - score) > threshold) {
|
||||
LogInfo << __FUNCTION__ << "hit cache, score:" << score;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LogInfo << __FUNCTION__ << "miss cache, score:" << score;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
battle::Role BattlefieldMatcher::oper_role_analyze(const Rect& roi) const
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Vision/VisionHelper.h"
|
||||
|
||||
#include "Common/AsstBattleDef.h"
|
||||
#include "Vision/MultiMatcher.h"
|
||||
|
||||
namespace asst
|
||||
{
|
||||
@@ -36,7 +37,8 @@ public:
|
||||
struct Result
|
||||
{
|
||||
ObjectOfInterest object_of_interest;
|
||||
std::vector<battle::DeploymentOper> deployment;
|
||||
|
||||
BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> deployment;
|
||||
MatchResult<std::pair<int, int>> kills; // kills / total_kills
|
||||
MatchResult<int> costs;
|
||||
|
||||
@@ -54,14 +56,19 @@ public:
|
||||
void set_object_of_interest(ObjectOfInterest obj);
|
||||
void set_total_kills_prompt(int prompt);
|
||||
void set_image_prev(const cv::Mat& image);
|
||||
|
||||
std::vector<double> get_score() const { return m_score; }
|
||||
|
||||
ResultOpt analyze() const;
|
||||
|
||||
protected:
|
||||
bool hp_flag_analyze() const;
|
||||
bool kills_flag_analyze() const;
|
||||
bool pause_button_analyze() const;
|
||||
|
||||
std::vector<battle::DeploymentOper> deployment_analyze() const; // 识别干员
|
||||
// 识别干员
|
||||
MatchResult<std::vector<battle::DeploymentOper>> deployment_analyze() const;
|
||||
// 识别干员是否命中缓存
|
||||
bool hit_deployment_cache(const asst::MultiMatcher::ResultsVec& flags) const;
|
||||
battle::Role oper_role_analyze(const Rect& roi) const;
|
||||
bool oper_cooling_analyze(const Rect& roi) const;
|
||||
int oper_cost_analyze(const Rect& roi) const;
|
||||
@@ -79,6 +86,7 @@ protected:
|
||||
|
||||
ObjectOfInterest m_object_of_interest; // 待识别的目标
|
||||
int m_total_kills_prompt = 0; // 之前的击杀总数,因为击杀数经常识别不准所以依赖外部传入作为参考
|
||||
cv::Mat m_image_prev; // 缓存图像, 用于判断费用, 击杀数是否变化. 无变化则不重新识别
|
||||
cv::Mat m_image_prev; // 缓存图像, 用于判断费用, 击杀数, 待部署区是否变化. 无变化则不重新识别
|
||||
mutable std::vector<double> m_score; // 识别分数, 测试代码
|
||||
};
|
||||
} // namespace asst
|
||||
|
||||
@@ -1353,6 +1353,12 @@ namespace MaaWpfGui.Main
|
||||
string what = details["what"]?.ToString() ?? string.Empty;
|
||||
switch (what)
|
||||
{
|
||||
case "BattleCacheTest":
|
||||
{
|
||||
Instances.CopilotViewModel.AddLog($"hit cache: {subTaskDetails["hit"]}, score: [{string.Join(",", subTaskDetails["score"].Select(i => i.ToObject<double>().ToString("0.######")))}]", UiLogColor.Info);
|
||||
break;
|
||||
}
|
||||
|
||||
case "StageDrops":
|
||||
{
|
||||
string allDrops = string.Empty;
|
||||
|
||||
Reference in New Issue
Block a user