perf: 拆分

This commit is contained in:
status102
2025-06-07 20:41:42 +08:00
parent 47aca4d711
commit cd606c2ed0
2 changed files with 86 additions and 87 deletions

View File

@@ -3911,10 +3911,9 @@
"specialParams_doc": [
"前后帧干员role+cost区域RGB像素变化阈值",
"变化像素数量阈值",
"干员头像区域RGB变化阈值",
"变化像素数量"
"干员头像区域模板匹配分数阈值"
],
"specialParams": [10, 10, 10, 100]
"specialParams": [10, 10, 98]
},
"BattleOpersFlag": {
"templThreshold": 0.65,

View File

@@ -75,13 +75,8 @@ BattlefieldMatcher::ResultOpt BattlefieldMatcher::analyze() const
BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> BattlefieldMatcher::deployment_analyze() const
{
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));
};
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);
@@ -93,6 +88,10 @@ BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> Battlefield
}
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;
@@ -100,84 +99,6 @@ BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> Battlefield
const Rect& cooling_move = Task.get("BattleOperCooling")->rect_move;
const Rect& avatar_move = Task.get("BattleOperAvatar")->rect_move;
const Rect& cost_move = Task.get("BattleOperCost")->rect_move;
const auto& cache_task = Task.get("BattleOperCache");
while (!m_image_prev.empty() && m_image.cols == m_image_prev.cols && m_image.rows == m_image_prev.rows) {
MultiMatcher flags_prev_ana(m_image_prev);
flags_prev_ana.set_task_info(flag_task_ptr);
flags_prev_ana.set_log_tracing(false);
auto flags_prev_opt = flags_prev_ana.analyze();
if (!flags_prev_opt) {
break; // 新图有干员, 但上一帧没有
}
auto& flags_prev = flags_prev_opt.value();
if (flags.size() != flags_prev.size()) {
break; // 新图干员数量和上一帧不一致
}
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;
cv::Scalar avg, avg_prev;
for (int 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::Mat cache_det;
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.info(__FUNCTION__, "oper cache changed, count:", count);
is_same = false;
break; // 新图干员缓存和上一帧不一致
}
}
if (!is_same) {
break;
}
cv::Mat match;
#ifdef ASST_DEBUG
[[maybe_unused]] cv::Mat image_mask;
cv::bitwise_and(m_image, m_image, image_mask, mask);
#endif // ASST_DEBUG
/*
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);
m_score.emplace_back(score);
if (score < 0.02) { // 当有一个干员从不可用变为可用时, score为0.96
Log.info(__FUNCTION__, "hit cache, score:", score);
return { .status = MatchStatus::HitCache };
}
else {
Log.info(__FUNCTION__, "miss cache, score:", score);
is_same = false;
#ifndef ASST_DEBUG
break;
#endif // ASST_DEBUG
}
break;
}
std::vector<battle::DeploymentOper> oper_result;
size_t index = 0;
@@ -241,6 +162,85 @@ BattlefieldMatcher::MatchResult<std::vector<battle::DeploymentOper>> Battlefield
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
{
static const std::unordered_map<std::string, battle::Role> RoleMap = {