diff --git a/src/MaaCore/Task/Fight/StageDropsTaskPlugin.cpp b/src/MaaCore/Task/Fight/StageDropsTaskPlugin.cpp index 754f73557e..7c50dc70f8 100644 --- a/src/MaaCore/Task/Fight/StageDropsTaskPlugin.cpp +++ b/src/MaaCore/Task/Fight/StageDropsTaskPlugin.cpp @@ -4,7 +4,9 @@ #include #include +#include "Common/AsstTypes.h" #include "Common/AsstVersion.h" +#include "Config/GeneralConfig.h" #include "Config/Miscellaneous/ItemConfig.h" #include "Config/Miscellaneous/StageDropsConfig.h" #include "Config/TaskData.h" @@ -13,6 +15,7 @@ #include "Task/ProcessTask.h" #include "Task/ReportDataTask.h" #include "Utils/Logger.hpp" +#include "Vision/Matcher.h" #include "Vision/Miscellaneous/StageDropsImageAnalyzer.h" bool asst::StageDropsTaskPlugin::verify(AsstMsg msg, const json::value& details) const @@ -110,7 +113,33 @@ bool asst::StageDropsTaskPlugin::recognize_drops() } StageDropsImageAnalyzer analyzer(ctrler()->get_image()); - bool ret = analyzer.analyze(); + + bool ret = false; + while (!need_exit()) { + ret = false; + + // more materials to reveal? + + auto swipe_begin = Point { WindowWidthDefault - 40, 632 }; + + const int swipe_dist = 200; + ctrler()->swipe(swipe_begin, swipe_begin + swipe_dist * Point::left(), 500, true, 2, 0); + sleep(Config.get_options().task_delay * 3); + + auto new_img = ctrler()->get_image(); + + const auto offset_opt = analyzer.merge_image(new_img); + if (!offset_opt.has_value()) break; + const auto offset = offset_opt.value(); + Log.trace("new image offset:", offset); + if (offset <= 4) { + ret = true; + break; + } + } + + // image strip constructed, start main step + ret &= analyzer.analyze(); auto&& [code, difficulty] = analyzer.get_stage_key(); m_stage_code = std::move(code); diff --git a/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.cpp b/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.cpp index d5684eb3b8..3120ea627f 100644 --- a/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.cpp +++ b/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.cpp @@ -1,6 +1,7 @@ #include "StageDropsImageAnalyzer.h" #include +#include #include #include "Utils/Ranges.hpp" @@ -361,10 +362,41 @@ bool asst::StageDropsImageAnalyzer::analyze_drops_for_12() return !flag_analyzer.analyze(); } +std::optional asst::StageDropsImageAnalyzer::merge_image(const cv::Mat& new_img) +{ + LogTraceFunction; + + const cv::Rect ref_roi = { m_image.cols - 320, 530, 280, 100 }; + Matcher offset_match(new_img(cv::Rect { 0, ref_roi.y, new_img.cols, ref_roi.height })); + offset_match.set_templ(m_image(ref_roi)); + offset_match.set_threshold(0.7); + if (!offset_match.analyze()) { + Log.error("Unable to merge images"); + return std::nullopt; + } + const int offset = (new_img.cols - offset_match.get_result().rect.x) - (m_image.cols - ref_roi.x); + + const int rel_x = offset + m_image.cols - new_img.cols; + + const cv::Rect overlay_rect = { 540, 500, 740, 220 }; + cv::Rect overlay_rect_on_strip = overlay_rect; + overlay_rect_on_strip.x += rel_x; + + cv::Mat new_strip = cv::Mat { m_image.rows, overlay_rect_on_strip.br().x, m_image.type(), cv::Scalar(0) }; + m_image.copyTo(new_strip(cv::Rect { 0, 0, m_image.cols, m_image.rows })); + new_img(overlay_rect).copyTo(new_strip(overlay_rect_on_strip)); + + m_image = new_strip; + + return offset; +} + bool asst::StageDropsImageAnalyzer::analyze_baseline() { LogTraceFunction; + m_baseline.clear(); + auto task_ptr = Task.get("StageDrops-BaseLine"); cv::Mat preprocessed_roi; @@ -386,7 +418,9 @@ bool asst::StageDropsImageAnalyzer::analyze_baseline() cv::getStructuringElement(cv::MORPH_RECT, { 3, 1 })); // cropping after derivatives, dilation, and erosion - cv::cvtColor(preprocessed_roi(make_rect(task_ptr->roi)), preprocessed_roi, cv::COLOR_BGR2GRAY); + auto roi = make_rect(task_ptr->roi); + roi.width = WindowWidthDefault - roi.br().x + m_image.cols; // image may be wider than 1280 + cv::cvtColor(preprocessed_roi(roi), preprocessed_roi, cv::COLOR_BGR2GRAY); } cv::Mat preprocessed_bin; @@ -457,6 +491,10 @@ bool asst::StageDropsImageAnalyzer::analyze_baseline() Log.trace(__FUNCTION__, "baseline", key.to_string()); } + if (m_image.cols - (x_offset + bounding_rect.width) < 30 + max_spacing) { + Log.trace("bounding_rect.right=", x_offset + bounding_rect.width, ", more materials to reveal?"); + } // TODO: else tell caller to prevent unnecessary swipe + return !m_baseline.empty(); } diff --git a/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.h b/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.h index 15b0133bc0..322f891032 100644 --- a/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.h +++ b/src/MaaCore/Vision/Miscellaneous/StageDropsImageAnalyzer.h @@ -23,6 +23,11 @@ namespace asst // > const auto& get_drops() const noexcept { return m_drops; } + // merge a new image with a different material position into m_image + // might resize m_image. + // return offset in pixels + std::optional merge_image(const cv::Mat& new_img); + protected: bool analyze_stage_code(); bool analyze_times();