diff --git a/README.md b/README.md index cf9e91d17d..83f3e4cc00 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ A game assistance for Arknights 1. `options`.`connectType`字段值为`1` 2. `emulator`.`Custom`.`adb`.`addresses`字段填写为要连接的地址,请注意这是个数组,会以此尝试所有的(若不填写,或`addresses`中所有的都没连上,则会使用`adb devices`自动查找) -目前对非16:9分辨率的支持效果很不好,几乎是不可用状态,后期将逐步优化 +目前对非16:9分辨率的支持效果很不好,刷理智和公招识别勉强可用,其他功能几乎是不可用的状态,后期将逐步优化 ### 设置操作延时 diff --git a/src/MeoAssistance/AbstractImageAnalyzer.cpp b/src/MeoAssistance/AbstractImageAnalyzer.cpp index 7dc85203f9..4c776ba954 100644 --- a/src/MeoAssistance/AbstractImageAnalyzer.cpp +++ b/src/MeoAssistance/AbstractImageAnalyzer.cpp @@ -1,6 +1,7 @@ #include "AbstractImageAnalyzer.h" #include "AsstUtils.hpp" +#include "Controller.h" asst::AbstractImageAnalyzer::AbstractImageAnalyzer(const cv::Mat& image) : m_image(image), m_roi(empty_rect_to_full(Rect(), image)) @@ -40,6 +41,11 @@ void asst::AbstractImageAnalyzer::set_roi(const Rect& roi) noexcept m_roi = empty_rect_to_full(roi, m_image); } +void asst::AbstractImageAnalyzer::correct_roi() noexcept +{ + m_roi = ctrler.shaped_correct(m_roi); +} + asst::Rect asst::AbstractImageAnalyzer::empty_rect_to_full(const Rect& rect, const cv::Mat& image) noexcept { return rect.empty() ? Rect(0, 0, image.cols, image.rows) : rect; diff --git a/src/MeoAssistance/AbstractImageAnalyzer.h b/src/MeoAssistance/AbstractImageAnalyzer.h index 165bceb5b2..378d60105d 100644 --- a/src/MeoAssistance/AbstractImageAnalyzer.h +++ b/src/MeoAssistance/AbstractImageAnalyzer.h @@ -20,6 +20,7 @@ namespace asst virtual void set_image(const cv::Mat& image, const Rect& roi); virtual void set_roi(const Rect& roi) noexcept; virtual bool analyze() = 0; + virtual void correct_roi() noexcept; std::string calc_hash() const; // 使用m_roi std::string calc_hash(const Rect& roi) const; // 使用参数roi diff --git a/src/MeoAssistance/AsstDef.h b/src/MeoAssistance/AsstDef.h index f1916fb8ae..48d9539954 100644 --- a/src/MeoAssistance/AsstDef.h +++ b/src/MeoAssistance/AsstDef.h @@ -16,6 +16,12 @@ namespace asst { constexpr double DoubleDiff = 1e-12; + constexpr static int WindowWidthDefault = 1280; + constexpr static int WindowHeightDefault = 720; + + constexpr static double TemplThresholdDefault = 0.9; + constexpr static double HistThresholdDefault = 0.9; + struct Point { Point() = default; diff --git a/src/MeoAssistance/AsstUtils.hpp b/src/MeoAssistance/AsstUtils.hpp index 856440dc9a..1e649ace82 100644 --- a/src/MeoAssistance/AsstUtils.hpp +++ b/src/MeoAssistance/AsstUtils.hpp @@ -1,10 +1,11 @@ #pragma once -#include #include #include #include +#include + namespace asst { namespace utils diff --git a/src/MeoAssistance/Controller.cpp b/src/MeoAssistance/Controller.cpp index 2cfb1e80db..bbe0e1e3cb 100644 --- a/src/MeoAssistance/Controller.cpp +++ b/src/MeoAssistance/Controller.cpp @@ -80,19 +80,19 @@ bool asst::Controller::connect_adb(const std::string& address) m_emulator_info.adb.display_height = (std::min)(size_value1, size_value2); constexpr double DefaultRatio = - static_cast(GeneralConfiger::WindowWidthDefault) / static_cast(GeneralConfiger::WindowHeightDefault); + static_cast(WindowWidthDefault) / static_cast(WindowHeightDefault); double cur_ratio = static_cast(m_emulator_info.adb.display_width) / static_cast(m_emulator_info.adb.display_height); if (cur_ratio >= DefaultRatio // 说明是宽屏或默认16:9,按照高度计算缩放 || std::fabs(cur_ratio - DefaultRatio) < DoubleDiff) { - int scale_width = cur_ratio * GeneralConfiger::WindowHeightDefault; - m_scale_size = std::make_pair(scale_width, GeneralConfiger::WindowHeightDefault); - m_control_scale = static_cast(m_emulator_info.adb.display_height) / static_cast(GeneralConfiger::WindowHeightDefault); + int scale_width = cur_ratio * WindowHeightDefault; + m_scale_size = std::make_pair(scale_width, WindowHeightDefault); + m_control_scale = static_cast(m_emulator_info.adb.display_height) / static_cast(WindowHeightDefault); } else { // 否则可能是偏正方形的屏幕,按宽度计算 - int scale_height = GeneralConfiger::WindowWidthDefault / cur_ratio; - m_scale_size = std::make_pair(GeneralConfiger::WindowWidthDefault, scale_height); - m_control_scale = static_cast(m_emulator_info.adb.display_width) / static_cast(GeneralConfiger::WindowWidthDefault); + int scale_height = WindowWidthDefault / cur_ratio; + m_scale_size = std::make_pair(WindowWidthDefault, scale_height); + m_control_scale = static_cast(m_emulator_info.adb.display_width) / static_cast(WindowWidthDefault); } m_emulator_info.adb.click = utils::string_replace_all(utils::string_replace_all(m_emulator_info.adb.click, "[Adb]", m_adb_path), "[Address]", address); @@ -123,18 +123,51 @@ asst::Controller::~Controller() asst::Rect asst::Controller::shaped_correct(const Rect& rect) const { - if (rect.width == 0 || rect.height == 0) { + if (rect.empty()) { return rect; } // 明日方舟在异形屏上,有的地方是按比例缩放的,有的地方又是直接位移。没法整,这里简单粗暴一点截一个长条 Rect dst = rect; - if (m_scale_size.first != GeneralConfiger::WindowWidthDefault) { // 说明是宽屏 - dst.x = 0; - dst.width = m_scale_size.first - 1; + if (m_scale_size.first != WindowWidthDefault) { // 说明是宽屏 + if (rect.width < WindowWidthDefault / 2) { + if (rect.x + rect.width < WindowWidthDefault / 2) { // 整个矩形都在左半边 + dst.x = 0; + dst.width = m_scale_size.first / 2; + } + else if (rect.x >= WindowWidthDefault / 2) { // 整个矩形都在右半边 + dst.x = m_scale_size.first / 2; + dst.width = m_scale_size.first / 2; + } + else { // 整个矩形横跨了中线 + dst.x = 0; + dst.width = m_scale_size.first; + } + } + else { + dst.x = 0; + dst.width = m_scale_size.first; + } } - else if (m_scale_size.second != GeneralConfiger::WindowHeightDefault) { // 说明是偏方形屏 - dst.y = 0; - dst.height = m_scale_size.second - 1; + else if (m_scale_size.second != WindowHeightDefault) { // 说明是偏方形屏 + if (rect.height < WindowHeightDefault / 2) { + if (rect.y + rect.height < WindowHeightDefault / 2) { // 整个矩形都在上半边 + dst.y = 0; + dst.height = m_scale_size.second / 2; + } + else if (rect.y >= WindowHeightDefault / 2) { // 整个矩形都在下半边 + dst.y = m_scale_size.second / 2; + dst.height = m_scale_size.second / 2; // 整个矩形横跨了中线 + } + else { + dst.y = 0; + dst.height = m_scale_size.second; + } + } + + else { + dst.y = 0; + dst.height = m_scale_size.second; + } } return dst; } diff --git a/src/MeoAssistance/GeneralConfiger.h b/src/MeoAssistance/GeneralConfiger.h index e939039636..2ce9381537 100644 --- a/src/MeoAssistance/GeneralConfiger.h +++ b/src/MeoAssistance/GeneralConfiger.h @@ -37,9 +37,6 @@ namespace asst public: virtual ~GeneralConfiger() = default; - constexpr static int WindowWidthDefault = 1280; - constexpr static int WindowHeightDefault = 720; - const std::string& get_version() const noexcept { return m_version; diff --git a/src/MeoAssistance/MatchImageAnalyzer.cpp b/src/MeoAssistance/MatchImageAnalyzer.cpp index 567f7521f6..f3aec15c10 100644 --- a/src/MeoAssistance/MatchImageAnalyzer.cpp +++ b/src/MeoAssistance/MatchImageAnalyzer.cpp @@ -56,6 +56,12 @@ bool asst::MatchImageAnalyzer::match_templ(const cv::Mat& templ) cv::Mat matched; cv::Mat image_roi = m_image(utils::make_rect(m_roi)); + if (templ.rows > image_roi.cols || templ.cols > image_roi.cols) { + log.error("templ size is too large", + "image_roi size:", image_roi.cols, image_roi.cols, + "templ size:", templ.cols, templ.rows); + return false; + } if (m_mask_range.first == m_mask_range.second) { cv::matchTemplate(image_roi, templ, matched, cv::TM_CCOEFF_NORMED); } diff --git a/src/MeoAssistance/ProcessTask.cpp b/src/MeoAssistance/ProcessTask.cpp index 9840f45acd..21d6803aee 100644 --- a/src/MeoAssistance/ProcessTask.cpp +++ b/src/MeoAssistance/ProcessTask.cpp @@ -74,7 +74,7 @@ bool ProcessTask::run() exec_click_task(rect); break; case ProcessTaskAction::ClickRand: { - static const Rect full_rect(0, 0, GeneralConfiger::WindowWidthDefault, GeneralConfiger::WindowHeightDefault); + static const Rect full_rect(0, 0, WindowWidthDefault, WindowHeightDefault); exec_click_task(full_rect); } break; case ProcessTaskAction::SwipeToTheLeft: @@ -167,12 +167,18 @@ void asst::ProcessTask::exec_swipe_task(ProcessTaskAction action) if (!delay_random()) { return; } - auto& width = resource.cfg().WindowWidthDefault; - auto& height = resource.cfg().WindowWidthDefault; - const static Rect right_rect(width * 0.8, height * 0.4, width * 0.1, height * 0.2); + const static Rect right_rect = ctrler.shaped_correct( + Rect(WindowWidthDefault * 0.8, + WindowWidthDefault * 0.4, + WindowWidthDefault * 0.1, + WindowWidthDefault * 0.2)); - const static Rect left_rect(width * 0.1, height * 0.4, width * 0.1, height * 0.2); + const static Rect left_rect = ctrler.shaped_correct( + Rect(WindowWidthDefault * 0.1, + WindowWidthDefault * 0.4, + WindowWidthDefault * 0.1, + WindowWidthDefault * 0.2)); switch (action) { case asst::ProcessTaskAction::SwipeToTheLeft: diff --git a/src/MeoAssistance/ProcessTaskImageAnalyzer.cpp b/src/MeoAssistance/ProcessTaskImageAnalyzer.cpp index 9bfe647192..41dfb69bb3 100644 --- a/src/MeoAssistance/ProcessTaskImageAnalyzer.cpp +++ b/src/MeoAssistance/ProcessTaskImageAnalyzer.cpp @@ -22,6 +22,7 @@ bool asst::ProcessTaskImageAnalyzer::match_analyze(std::shared_ptr tas } const auto match_task_ptr = std::dynamic_pointer_cast(task_ptr); m_match_analyzer->set_task_info(*match_task_ptr); + m_match_analyzer->correct_roi(); if (m_match_analyzer->analyze()) { m_result = match_task_ptr; @@ -69,6 +70,7 @@ bool asst::ProcessTaskImageAnalyzer::ocr_analyze(std::shared_ptr task_ // 识别区域文字,并加入缓存 auto analyze_roi = [&](const Rect& roi, bool is_appeared = false) -> bool { m_ocr_analyzer->set_roi(roi); + m_ocr_analyzer->correct_roi(); bool ret = m_ocr_analyzer->analyze(); const auto& ocr_result = m_ocr_analyzer->get_result(); @@ -88,8 +90,8 @@ bool asst::ProcessTaskImageAnalyzer::ocr_analyze(std::shared_ptr task_ // 在曾经识别到过的历史区域里识别 for (const Rect& region : ocr_task_ptr->region_of_appeared) { - static auto& max_width = resource.cfg().WindowWidthDefault; - static auto& max_height = resource.cfg().WindowHeightDefault; + static auto& max_width = WindowWidthDefault; + static auto& max_height = WindowHeightDefault; bool ret = analyze_roi(region.center_zoom(2.0, max_width, max_height), true); if (ret) { log.trace("ProcessTaskImageAnalyzer::ocr_analyze | found in appeared"); diff --git a/src/MeoAssistance/TaskData.cpp b/src/MeoAssistance/TaskData.cpp index 6db20ffb02..64f59f2a7c 100644 --- a/src/MeoAssistance/TaskData.cpp +++ b/src/MeoAssistance/TaskData.cpp @@ -114,11 +114,9 @@ bool asst::TaskData::parse(const json::value& json) m_templ_required.emplace(match_task_info_ptr->templ_name); match_task_info_ptr->templ_threshold = task_json.get( - "templThreshold", - TemplResource::TemplThresholdDefault); + "templThreshold", TemplThresholdDefault); match_task_info_ptr->hist_threshold = task_json.get( - "histThreshold", - TemplResource::HistThresholdDefault); + "histThreshold", HistThresholdDefault); match_task_info_ptr->cache = task_json.get("cache", true); if (task_json.exist("maskRange")) { match_task_info_ptr->mask_range = std::make_pair( @@ -211,8 +209,8 @@ bool asst::TaskData::parse(const json::value& json) else { task_info_ptr->roi = Rect( 0, 0, - GeneralConfiger::WindowWidthDefault, - GeneralConfiger::WindowHeightDefault); + WindowWidthDefault, + WindowHeightDefault); } if (task_json.exist("next")) { diff --git a/src/MeoAssistance/TemplResource.h b/src/MeoAssistance/TemplResource.h index c932b07d37..5324f52530 100644 --- a/src/MeoAssistance/TemplResource.h +++ b/src/MeoAssistance/TemplResource.h @@ -12,8 +12,6 @@ namespace asst class TemplResource : public AbstractResource { public: - constexpr static double TemplThresholdDefault = 0.9; - constexpr static double HistThresholdDefault = 0.9; virtual ~TemplResource() = default;