From ce24e3072f02d4f6a102d3eb4aaffccc532f0316 Mon Sep 17 00:00:00 2001 From: Developer-Butters Date: Mon, 29 Jun 2026 15:30:44 -0500 Subject: [PATCH 1/4] Map detector revision Split out changes to PLZA Map detector from the helioptile fix. --- .../Inference/Map/PokemonLZA_MapDetector.cpp | 194 ++++++++++------ .../Inference/Map/PokemonLZA_MapDetector.h | 208 +++++++++++------- 2 files changed, 259 insertions(+), 143 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp index 756b02a2cb..84b6cd88fd 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp @@ -3,79 +3,137 @@ * From: https://github.com/PokemonAutomation/ * */ - +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonTools/Images/WaterfillUtilities.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "PokemonLZA_MapDetector.h" #include "PokemonLZA_MapIconDetector.h" -namespace PokemonAutomation{ -namespace NintendoSwitch{ -namespace PokemonLZA{ - - - -MapDetector::MapDetector(Color color, VideoOverlay* overlay) - : m_b_button( - color, - ButtonType::ButtonB, - {0.760730, 0.937023, 0.241416, 0.064885}, - overlay - ) - , m_x_button( - color, - ButtonType::ButtonX, - {0.005000, 0.150000, 0.025000, 0.110000}, - overlay - ) - , m_y_button( - color, - ButtonType::ButtonY, - {0.005000, 0.210000, 0.025000, 0.110000}, - overlay - ) -{} - -void MapDetector::make_overlays(VideoOverlaySet& items) const{ - m_b_button.make_overlays(items); - m_x_button.make_overlays(items); - m_y_button.make_overlays(items); -} - -bool MapDetector::detect(const ImageViewRGB32& screen){ - const bool detected = m_b_button.detect(screen) - && m_x_button.detect(screen) - && m_y_button.detect(screen); - - if (detected){ - for (MapIconDetector* detector : m_map_icon_detectors){ - detector->detect(screen); - } - } - return detected; -} - -std::vector MapDetector::detected_map_icons() const{ - std::vector ret; - for (MapIconDetector* detector : m_map_icon_detectors){ - const auto& detected_boxes = detector->last_detected(); - for (const auto& box: detected_boxes){ - ret.emplace_back(box.name, box.box); - } - } - return ret; -} + //#include + //using std::cout; + //using std::endl; +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { + + namespace { + + // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. + class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { + public: + TravelSpotMatcher() + : WaterfillTemplateMatcher( + "PokemonLZA/MapIcons/TravelSpotIcon.png", + Color(0xff004080), + Color(0xff80ffff), + 50 + ) + { + } + + static const TravelSpotMatcher& instance() { + static TravelSpotMatcher matcher; + return matcher; + } + + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { + size_t min_w = 8 * input_resolution.width / 3840; + size_t min_h = 8 * input_resolution.height / 2160; + return image.width() >= min_w && image.height() >= min_h; + } + }; + + + + } // anonymous namespace -void MapDetector::reset_state(){ - m_b_button.reset_state(); - m_x_button.reset_state(); - m_y_button.reset_state(); - for (MapIconDetector* detector : m_map_icon_detectors){ - detector->reset_state(); - } -} + MapDetector::MapDetector(Color color, VideoOverlay* overlay) + : m_color(color) + , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) + , m_x_button( + color, + ButtonType::ButtonX, + { 0.005000, 0.150000, 0.025000, 0.110000 }, + overlay + ) + , m_y_button( + color, + ButtonType::ButtonY, + { 0.005000, 0.210000, 0.025000, 0.110000 }, + overlay + ) + { + } -} -} -} + void MapDetector::make_overlays(VideoOverlaySet& items) const { + items.add(m_color, m_travel_icon); + m_x_button.make_overlays(items); + m_y_button.make_overlays(items); + } + + bool MapDetector::detect(const ImageViewRGB32& screen) { + // cout << "MapDetector::detect()" << endl; + const bool detected = detect_travel_spot(screen) + && m_x_button.detect(screen) + && m_y_button.detect(screen); + + if (detected) { + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->detect(screen); + } + } + return detected; + } + + + bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { + // Progressive cyan filters to handle capture-card color variance. + static const std::vector> CYAN_FILTERS{ + // Brighter cyan/teal. + {0xff004898, 0xff70ffff}, + {0xff003878, 0xff80ffff}, + // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). + {0xff002860, 0xff90ffff}, + {0xff001c50, 0xffa0ffff}, + }; + + double rel = screen.height() / 2160.0; + size_t min_area = size_t(50.0 * rel * rel); + + return match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_travel_icon), + TravelSpotMatcher::instance(), + CYAN_FILTERS, + { min_area, SIZE_MAX }, + 100.0, + [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } + ); + } + std::vector MapDetector::detected_map_icons() const { + std::vector ret; + for (MapIconDetector* detector : m_map_icon_detectors) { + const auto& detected_boxes = detector->last_detected(); + for (const auto& box : detected_boxes) { + ret.emplace_back(box.name, box.box); + } + } + return ret; + } + + void MapDetector::reset_state() { + m_x_button.reset_state(); + m_y_button.reset_state(); + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->reset_state(); + } + } + + + + } + } +} \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h index cd7eb7a4b5..84b6cd88fd 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h @@ -3,79 +3,137 @@ * From: https://github.com/PokemonAutomation/ * */ - -#ifndef PokemonAutomation_PokemonLZA_MapDetector_H -#define PokemonAutomation_PokemonLZA_MapDetector_H - -#include "CommonTools/VisualDetector.h" -#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" -#include "CommonTools/DetectedBoxes.h" - -namespace PokemonAutomation{ -namespace NintendoSwitch{ -namespace PokemonLZA{ - - -class MapIconDetector; - - -// Detect whether the map view is opened or not -class MapDetector : public StaticScreenDetector{ -public: - MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); - - // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. - // After detection session is done, call `detected_map_icons()` to get last detected map icons. - void attach_map_icon_detector(MapIconDetector& detector){ - m_map_icon_detectors.push_back(&detector); +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonTools/Images/WaterfillUtilities.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" +#include "PokemonLZA_MapDetector.h" +#include "PokemonLZA_MapIconDetector.h" + + //#include + //using std::cout; + //using std::endl; + +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { + + namespace { + + // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. + class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { + public: + TravelSpotMatcher() + : WaterfillTemplateMatcher( + "PokemonLZA/MapIcons/TravelSpotIcon.png", + Color(0xff004080), + Color(0xff80ffff), + 50 + ) + { + } + + static const TravelSpotMatcher& instance() { + static TravelSpotMatcher matcher; + return matcher; + } + + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { + size_t min_w = 8 * input_resolution.width / 3840; + size_t min_h = 8 * input_resolution.height / 2160; + return image.width() >= min_w && image.height() >= min_h; + } + }; + + + + } // anonymous namespace + + + + MapDetector::MapDetector(Color color, VideoOverlay* overlay) + : m_color(color) + , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) + , m_x_button( + color, + ButtonType::ButtonX, + { 0.005000, 0.150000, 0.025000, 0.110000 }, + overlay + ) + , m_y_button( + color, + ButtonType::ButtonY, + { 0.005000, 0.210000, 0.025000, 0.110000 }, + overlay + ) + { + } + + void MapDetector::make_overlays(VideoOverlaySet& items) const { + items.add(m_color, m_travel_icon); + m_x_button.make_overlays(items); + m_y_button.make_overlays(items); + } + + bool MapDetector::detect(const ImageViewRGB32& screen) { + // cout << "MapDetector::detect()" << endl; + const bool detected = detect_travel_spot(screen) + && m_x_button.detect(screen) + && m_y_button.detect(screen); + + if (detected) { + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->detect(screen); + } + } + return detected; + } + + + bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { + // Progressive cyan filters to handle capture-card color variance. + static const std::vector> CYAN_FILTERS{ + // Brighter cyan/teal. + {0xff004898, 0xff70ffff}, + {0xff003878, 0xff80ffff}, + // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). + {0xff002860, 0xff90ffff}, + {0xff001c50, 0xffa0ffff}, + }; + + double rel = screen.height() / 2160.0; + size_t min_area = size_t(50.0 * rel * rel); + + return match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_travel_icon), + TravelSpotMatcher::instance(), + CYAN_FILTERS, + { min_area, SIZE_MAX }, + 100.0, + [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } + ); + } + std::vector MapDetector::detected_map_icons() const { + std::vector ret; + for (MapIconDetector* detector : m_map_icon_detectors) { + const auto& detected_boxes = detector->last_detected(); + for (const auto& box : detected_boxes) { + ret.emplace_back(box.name, box.box); + } + } + return ret; + } + + void MapDetector::reset_state() { + m_x_button.reset_state(); + m_y_button.reset_state(); + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->reset_state(); + } + } + + + + } } - - virtual void make_overlays(VideoOverlaySet& items) const override; - - // This is not const so that detectors can save/cache state. - virtual bool detect(const ImageViewRGB32& screen) override; - - // Return last detected map icons from attached MapIconDetectors. - std::vector detected_map_icons() const; - - void reset_state() override; - -private: - ButtonDetector m_b_button; - ButtonDetector m_x_button; - ButtonDetector m_y_button; - std::vector m_map_icon_detectors; -}; - -class MapWatcher : public DetectorToFinder{ -public: - MapWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) - ) - : DetectorToFinder("MapWatcher", hold_duration, color, overlay) - {} -}; -class MapOverWatcher : public DetectorToFinder{ -public: - MapOverWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) - ) - : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) - {} -}; - - - - - - - - -} -} -} -#endif +} \ No newline at end of file From fc8d26ee860cb5fa3da563a89c7abdbec33636db Mon Sep 17 00:00:00 2001 From: Developer-Butters Date: Mon, 29 Jun 2026 15:32:50 -0500 Subject: [PATCH 2/4] Revert "Map detector revision" This reverts commit 206b565729dbf67cb8da13b6f17fd7a432f48bbd. --- .../Inference/Map/PokemonLZA_MapDetector.cpp | 194 ++++++---------- .../Inference/Map/PokemonLZA_MapDetector.h | 208 +++++++----------- 2 files changed, 143 insertions(+), 259 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp index 84b6cd88fd..756b02a2cb 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp @@ -3,137 +3,79 @@ * From: https://github.com/PokemonAutomation/ * */ -#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" -#include "CommonTools/Images/WaterfillUtilities.h" -#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" + #include "PokemonLZA_MapDetector.h" #include "PokemonLZA_MapIconDetector.h" - //#include - //using std::cout; - //using std::endl; - -namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { - - namespace { - - // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. - class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { - public: - TravelSpotMatcher() - : WaterfillTemplateMatcher( - "PokemonLZA/MapIcons/TravelSpotIcon.png", - Color(0xff004080), - Color(0xff80ffff), - 50 - ) - { - } - - static const TravelSpotMatcher& instance() { - static TravelSpotMatcher matcher; - return matcher; - } - - virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { - size_t min_w = 8 * input_resolution.width / 3840; - size_t min_h = 8 * input_resolution.height / 2160; - return image.width() >= min_w && image.height() >= min_h; - } - }; - - - - } // anonymous namespace - - - - MapDetector::MapDetector(Color color, VideoOverlay* overlay) - : m_color(color) - , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) - , m_x_button( - color, - ButtonType::ButtonX, - { 0.005000, 0.150000, 0.025000, 0.110000 }, - overlay - ) - , m_y_button( - color, - ButtonType::ButtonY, - { 0.005000, 0.210000, 0.025000, 0.110000 }, - overlay - ) - { - } - - void MapDetector::make_overlays(VideoOverlaySet& items) const { - items.add(m_color, m_travel_icon); - m_x_button.make_overlays(items); - m_y_button.make_overlays(items); - } - - bool MapDetector::detect(const ImageViewRGB32& screen) { - // cout << "MapDetector::detect()" << endl; - const bool detected = detect_travel_spot(screen) - && m_x_button.detect(screen) - && m_y_button.detect(screen); - - if (detected) { - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->detect(screen); - } - } - return detected; - } - - - bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { - // Progressive cyan filters to handle capture-card color variance. - static const std::vector> CYAN_FILTERS{ - // Brighter cyan/teal. - {0xff004898, 0xff70ffff}, - {0xff003878, 0xff80ffff}, - // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). - {0xff002860, 0xff90ffff}, - {0xff001c50, 0xffa0ffff}, - }; - - double rel = screen.height() / 2160.0; - size_t min_area = size_t(50.0 * rel * rel); +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + + +MapDetector::MapDetector(Color color, VideoOverlay* overlay) + : m_b_button( + color, + ButtonType::ButtonB, + {0.760730, 0.937023, 0.241416, 0.064885}, + overlay + ) + , m_x_button( + color, + ButtonType::ButtonX, + {0.005000, 0.150000, 0.025000, 0.110000}, + overlay + ) + , m_y_button( + color, + ButtonType::ButtonY, + {0.005000, 0.210000, 0.025000, 0.110000}, + overlay + ) +{} + +void MapDetector::make_overlays(VideoOverlaySet& items) const{ + m_b_button.make_overlays(items); + m_x_button.make_overlays(items); + m_y_button.make_overlays(items); +} + +bool MapDetector::detect(const ImageViewRGB32& screen){ + const bool detected = m_b_button.detect(screen) + && m_x_button.detect(screen) + && m_y_button.detect(screen); + + if (detected){ + for (MapIconDetector* detector : m_map_icon_detectors){ + detector->detect(screen); + } + } + return detected; +} + +std::vector MapDetector::detected_map_icons() const{ + std::vector ret; + for (MapIconDetector* detector : m_map_icon_detectors){ + const auto& detected_boxes = detector->last_detected(); + for (const auto& box: detected_boxes){ + ret.emplace_back(box.name, box.box); + } + } + return ret; +} - return match_template_by_waterfill( - screen.size(), - extract_box_reference(screen, m_travel_icon), - TravelSpotMatcher::instance(), - CYAN_FILTERS, - { min_area, SIZE_MAX }, - 100.0, - [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } - ); - } - std::vector MapDetector::detected_map_icons() const { - std::vector ret; - for (MapIconDetector* detector : m_map_icon_detectors) { - const auto& detected_boxes = detector->last_detected(); - for (const auto& box : detected_boxes) { - ret.emplace_back(box.name, box.box); - } - } - return ret; - } - void MapDetector::reset_state() { - m_x_button.reset_state(); - m_y_button.reset_state(); - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->reset_state(); - } - } +void MapDetector::reset_state(){ + m_b_button.reset_state(); + m_x_button.reset_state(); + m_y_button.reset_state(); + for (MapIconDetector* detector : m_map_icon_detectors){ + detector->reset_state(); + } +} - } - } -} \ No newline at end of file +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h index 84b6cd88fd..cd7eb7a4b5 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h @@ -3,137 +3,79 @@ * From: https://github.com/PokemonAutomation/ * */ -#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" -#include "CommonTools/Images/WaterfillUtilities.h" -#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" -#include "PokemonLZA_MapDetector.h" -#include "PokemonLZA_MapIconDetector.h" - - //#include - //using std::cout; - //using std::endl; - -namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { - - namespace { - - // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. - class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { - public: - TravelSpotMatcher() - : WaterfillTemplateMatcher( - "PokemonLZA/MapIcons/TravelSpotIcon.png", - Color(0xff004080), - Color(0xff80ffff), - 50 - ) - { - } - - static const TravelSpotMatcher& instance() { - static TravelSpotMatcher matcher; - return matcher; - } - - virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { - size_t min_w = 8 * input_resolution.width / 3840; - size_t min_h = 8 * input_resolution.height / 2160; - return image.width() >= min_w && image.height() >= min_h; - } - }; - - - - } // anonymous namespace - - - - MapDetector::MapDetector(Color color, VideoOverlay* overlay) - : m_color(color) - , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) - , m_x_button( - color, - ButtonType::ButtonX, - { 0.005000, 0.150000, 0.025000, 0.110000 }, - overlay - ) - , m_y_button( - color, - ButtonType::ButtonY, - { 0.005000, 0.210000, 0.025000, 0.110000 }, - overlay - ) - { - } - - void MapDetector::make_overlays(VideoOverlaySet& items) const { - items.add(m_color, m_travel_icon); - m_x_button.make_overlays(items); - m_y_button.make_overlays(items); - } - - bool MapDetector::detect(const ImageViewRGB32& screen) { - // cout << "MapDetector::detect()" << endl; - const bool detected = detect_travel_spot(screen) - && m_x_button.detect(screen) - && m_y_button.detect(screen); - - if (detected) { - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->detect(screen); - } - } - return detected; - } - - - bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { - // Progressive cyan filters to handle capture-card color variance. - static const std::vector> CYAN_FILTERS{ - // Brighter cyan/teal. - {0xff004898, 0xff70ffff}, - {0xff003878, 0xff80ffff}, - // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). - {0xff002860, 0xff90ffff}, - {0xff001c50, 0xffa0ffff}, - }; - - double rel = screen.height() / 2160.0; - size_t min_area = size_t(50.0 * rel * rel); - - return match_template_by_waterfill( - screen.size(), - extract_box_reference(screen, m_travel_icon), - TravelSpotMatcher::instance(), - CYAN_FILTERS, - { min_area, SIZE_MAX }, - 100.0, - [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } - ); - } - std::vector MapDetector::detected_map_icons() const { - std::vector ret; - for (MapIconDetector* detector : m_map_icon_detectors) { - const auto& detected_boxes = detector->last_detected(); - for (const auto& box : detected_boxes) { - ret.emplace_back(box.name, box.box); - } - } - return ret; - } - - void MapDetector::reset_state() { - m_x_button.reset_state(); - m_y_button.reset_state(); - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->reset_state(); - } - } - - - - } + +#ifndef PokemonAutomation_PokemonLZA_MapDetector_H +#define PokemonAutomation_PokemonLZA_MapDetector_H + +#include "CommonTools/VisualDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" +#include "CommonTools/DetectedBoxes.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + +class MapIconDetector; + + +// Detect whether the map view is opened or not +class MapDetector : public StaticScreenDetector{ +public: + MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); + + // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. + // After detection session is done, call `detected_map_icons()` to get last detected map icons. + void attach_map_icon_detector(MapIconDetector& detector){ + m_map_icon_detectors.push_back(&detector); } -} \ No newline at end of file + + virtual void make_overlays(VideoOverlaySet& items) const override; + + // This is not const so that detectors can save/cache state. + virtual bool detect(const ImageViewRGB32& screen) override; + + // Return last detected map icons from attached MapIconDetectors. + std::vector detected_map_icons() const; + + void reset_state() override; + +private: + ButtonDetector m_b_button; + ButtonDetector m_x_button; + ButtonDetector m_y_button; + std::vector m_map_icon_detectors; +}; + +class MapWatcher : public DetectorToFinder{ +public: + MapWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("MapWatcher", hold_duration, color, overlay) + {} +}; +class MapOverWatcher : public DetectorToFinder{ +public: + MapOverWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) + ) + : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) + {} +}; + + + + + + + + +} +} +} +#endif From 19af7d08c10ffd3fd8fdb2ff673da018a49364b9 Mon Sep 17 00:00:00 2001 From: Developer-Butters Date: Mon, 29 Jun 2026 15:35:58 -0500 Subject: [PATCH 3/4] Map detector revision Split out changes to PLZA Map detector from the helioptile fix. --- .../Inference/Map/PokemonLZA_MapDetector.cpp | 194 ++++++++++++------ .../Inference/Map/PokemonLZA_MapDetector.h | 102 ++++----- 2 files changed, 180 insertions(+), 116 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp index 756b02a2cb..84b6cd88fd 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp @@ -3,79 +3,137 @@ * From: https://github.com/PokemonAutomation/ * */ - +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonTools/Images/WaterfillUtilities.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "PokemonLZA_MapDetector.h" #include "PokemonLZA_MapIconDetector.h" -namespace PokemonAutomation{ -namespace NintendoSwitch{ -namespace PokemonLZA{ - - - -MapDetector::MapDetector(Color color, VideoOverlay* overlay) - : m_b_button( - color, - ButtonType::ButtonB, - {0.760730, 0.937023, 0.241416, 0.064885}, - overlay - ) - , m_x_button( - color, - ButtonType::ButtonX, - {0.005000, 0.150000, 0.025000, 0.110000}, - overlay - ) - , m_y_button( - color, - ButtonType::ButtonY, - {0.005000, 0.210000, 0.025000, 0.110000}, - overlay - ) -{} - -void MapDetector::make_overlays(VideoOverlaySet& items) const{ - m_b_button.make_overlays(items); - m_x_button.make_overlays(items); - m_y_button.make_overlays(items); -} - -bool MapDetector::detect(const ImageViewRGB32& screen){ - const bool detected = m_b_button.detect(screen) - && m_x_button.detect(screen) - && m_y_button.detect(screen); - - if (detected){ - for (MapIconDetector* detector : m_map_icon_detectors){ - detector->detect(screen); - } - } - return detected; -} - -std::vector MapDetector::detected_map_icons() const{ - std::vector ret; - for (MapIconDetector* detector : m_map_icon_detectors){ - const auto& detected_boxes = detector->last_detected(); - for (const auto& box: detected_boxes){ - ret.emplace_back(box.name, box.box); - } - } - return ret; -} + //#include + //using std::cout; + //using std::endl; +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { + + namespace { + + // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. + class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { + public: + TravelSpotMatcher() + : WaterfillTemplateMatcher( + "PokemonLZA/MapIcons/TravelSpotIcon.png", + Color(0xff004080), + Color(0xff80ffff), + 50 + ) + { + } + + static const TravelSpotMatcher& instance() { + static TravelSpotMatcher matcher; + return matcher; + } + + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { + size_t min_w = 8 * input_resolution.width / 3840; + size_t min_h = 8 * input_resolution.height / 2160; + return image.width() >= min_w && image.height() >= min_h; + } + }; + + + + } // anonymous namespace -void MapDetector::reset_state(){ - m_b_button.reset_state(); - m_x_button.reset_state(); - m_y_button.reset_state(); - for (MapIconDetector* detector : m_map_icon_detectors){ - detector->reset_state(); - } -} + MapDetector::MapDetector(Color color, VideoOverlay* overlay) + : m_color(color) + , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) + , m_x_button( + color, + ButtonType::ButtonX, + { 0.005000, 0.150000, 0.025000, 0.110000 }, + overlay + ) + , m_y_button( + color, + ButtonType::ButtonY, + { 0.005000, 0.210000, 0.025000, 0.110000 }, + overlay + ) + { + } -} -} -} + void MapDetector::make_overlays(VideoOverlaySet& items) const { + items.add(m_color, m_travel_icon); + m_x_button.make_overlays(items); + m_y_button.make_overlays(items); + } + + bool MapDetector::detect(const ImageViewRGB32& screen) { + // cout << "MapDetector::detect()" << endl; + const bool detected = detect_travel_spot(screen) + && m_x_button.detect(screen) + && m_y_button.detect(screen); + + if (detected) { + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->detect(screen); + } + } + return detected; + } + + + bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { + // Progressive cyan filters to handle capture-card color variance. + static const std::vector> CYAN_FILTERS{ + // Brighter cyan/teal. + {0xff004898, 0xff70ffff}, + {0xff003878, 0xff80ffff}, + // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). + {0xff002860, 0xff90ffff}, + {0xff001c50, 0xffa0ffff}, + }; + + double rel = screen.height() / 2160.0; + size_t min_area = size_t(50.0 * rel * rel); + + return match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_travel_icon), + TravelSpotMatcher::instance(), + CYAN_FILTERS, + { min_area, SIZE_MAX }, + 100.0, + [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } + ); + } + std::vector MapDetector::detected_map_icons() const { + std::vector ret; + for (MapIconDetector* detector : m_map_icon_detectors) { + const auto& detected_boxes = detector->last_detected(); + for (const auto& box : detected_boxes) { + ret.emplace_back(box.name, box.box); + } + } + return ret; + } + + void MapDetector::reset_state() { + m_x_button.reset_state(); + m_y_button.reset_state(); + for (MapIconDetector* detector : m_map_icon_detectors) { + detector->reset_state(); + } + } + + + + } + } +} \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h index cd7eb7a4b5..96882c9a8b 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h @@ -11,63 +11,68 @@ #include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" #include "CommonTools/DetectedBoxes.h" -namespace PokemonAutomation{ -namespace NintendoSwitch{ -namespace PokemonLZA{ +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { -class MapIconDetector; + class MapIconDetector; -// Detect whether the map view is opened or not -class MapDetector : public StaticScreenDetector{ -public: - MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); + // Detect whether the map view is opened or not + class MapDetector : public StaticScreenDetector { + public: + MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); - // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. - // After detection session is done, call `detected_map_icons()` to get last detected map icons. - void attach_map_icon_detector(MapIconDetector& detector){ - m_map_icon_detectors.push_back(&detector); - } + // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. + // After detection session is done, call `detected_map_icons()` to get last detected map icons. + void attach_map_icon_detector(MapIconDetector& detector) { + m_map_icon_detectors.push_back(&detector); + } - virtual void make_overlays(VideoOverlaySet& items) const override; + virtual void make_overlays(VideoOverlaySet& items) const override; - // This is not const so that detectors can save/cache state. - virtual bool detect(const ImageViewRGB32& screen) override; + // This is not const so that detectors can save/cache state. + virtual bool detect(const ImageViewRGB32& screen) override; - // Return last detected map icons from attached MapIconDetectors. - std::vector detected_map_icons() const; + // Return last detected map icons from attached MapIconDetectors. + std::vector detected_map_icons() const; - void reset_state() override; + void reset_state() override; -private: - ButtonDetector m_b_button; - ButtonDetector m_x_button; - ButtonDetector m_y_button; - std::vector m_map_icon_detectors; -}; + private: + bool detect_travel_spot(const ImageViewRGB32& screen); -class MapWatcher : public DetectorToFinder{ -public: - MapWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) - ) - : DetectorToFinder("MapWatcher", hold_duration, color, overlay) - {} -}; -class MapOverWatcher : public DetectorToFinder{ -public: - MapOverWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) - ) - : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) - {} -}; + private: + Color m_color; + ImageFloatBox m_travel_icon; + ButtonDetector m_x_button; + ButtonDetector m_y_button; + std::vector m_map_icon_detectors; + }; + class MapWatcher : public DetectorToFinder { + public: + MapWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("MapWatcher", hold_duration, color, overlay) + { + } + }; + class MapOverWatcher : public DetectorToFinder { + public: + MapOverWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) + ) + : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) + { + } + }; @@ -75,7 +80,8 @@ class MapOverWatcher : public DetectorToFinder{ + + } + } } -} -} -#endif +#endif \ No newline at end of file From 129d07056da99fc24453432d41e08b6765916e26 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Tue, 30 Jun 2026 00:19:39 -0700 Subject: [PATCH 4/4] Just replace with the one from the other PR. --- .../Inference/Map/PokemonLZA_MapDetector.cpp | 248 +++++++++--------- .../Inference/Map/PokemonLZA_MapDetector.h | 104 ++++---- 2 files changed, 174 insertions(+), 178 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp index 84b6cd88fd..c7da41ade2 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.cpp @@ -9,131 +9,129 @@ #include "PokemonLZA_MapDetector.h" #include "PokemonLZA_MapIconDetector.h" - //#include - //using std::cout; - //using std::endl; - -namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { - - namespace { - - // Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. - class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher { - public: - TravelSpotMatcher() - : WaterfillTemplateMatcher( - "PokemonLZA/MapIcons/TravelSpotIcon.png", - Color(0xff004080), - Color(0xff80ffff), - 50 - ) - { - } - - static const TravelSpotMatcher& instance() { - static TravelSpotMatcher matcher; - return matcher; - } - - virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override { - size_t min_w = 8 * input_resolution.width / 3840; - size_t min_h = 8 * input_resolution.height / 2160; - return image.width() >= min_w && image.height() >= min_h; - } - }; - - - - } // anonymous namespace - - - - MapDetector::MapDetector(Color color, VideoOverlay* overlay) - : m_color(color) - , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) - , m_x_button( - color, - ButtonType::ButtonX, - { 0.005000, 0.150000, 0.025000, 0.110000 }, - overlay - ) - , m_y_button( - color, - ButtonType::ButtonY, - { 0.005000, 0.210000, 0.025000, 0.110000 }, - overlay - ) - { - } - - void MapDetector::make_overlays(VideoOverlaySet& items) const { - items.add(m_color, m_travel_icon); - m_x_button.make_overlays(items); - m_y_button.make_overlays(items); - } - - bool MapDetector::detect(const ImageViewRGB32& screen) { - // cout << "MapDetector::detect()" << endl; - const bool detected = detect_travel_spot(screen) - && m_x_button.detect(screen) - && m_y_button.detect(screen); - - if (detected) { - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->detect(screen); - } - } - return detected; - } - - - bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen) { - // Progressive cyan filters to handle capture-card color variance. - static const std::vector> CYAN_FILTERS{ - // Brighter cyan/teal. - {0xff004898, 0xff70ffff}, - {0xff003878, 0xff80ffff}, - // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). - {0xff002860, 0xff90ffff}, - {0xff001c50, 0xffa0ffff}, - }; - - double rel = screen.height() / 2160.0; - size_t min_area = size_t(50.0 * rel * rel); - - return match_template_by_waterfill( - screen.size(), - extract_box_reference(screen, m_travel_icon), - TravelSpotMatcher::instance(), - CYAN_FILTERS, - { min_area, SIZE_MAX }, - 100.0, - [](Kernels::Waterfill::WaterfillObject&) -> bool { return true; } - ); - } - std::vector MapDetector::detected_map_icons() const { - std::vector ret; - for (MapIconDetector* detector : m_map_icon_detectors) { - const auto& detected_boxes = detector->last_detected(); - for (const auto& box : detected_boxes) { - ret.emplace_back(box.name, box.box); - } - } - return ret; - } - - void MapDetector::reset_state() { - m_x_button.reset_state(); - m_y_button.reset_state(); - for (MapIconDetector* detector : m_map_icon_detectors) { - detector->reset_state(); - } - } - - +//#include +//using std::cout; +//using std::endl; + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +namespace{ + +// Matches the cyan "Travel Spots" feather icon shown next to the Y button on the map screen. +class TravelSpotMatcher : public ImageMatch::WaterfillTemplateMatcher{ +public: + TravelSpotMatcher() + : WaterfillTemplateMatcher( + "PokemonLZA/MapIcons/TravelSpotIcon.png", + Color(0xff004080), + Color(0xff80ffff), + 50 + ) + {} + + static const TravelSpotMatcher& instance(){ + static TravelSpotMatcher matcher; + return matcher; + } + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override{ + size_t min_w = 8 * input_resolution.width / 3840; + size_t min_h = 8 * input_resolution.height / 2160; + return image.width() >= min_w && image.height() >= min_h; + } +}; + + + +} // anonymous namespace + + + +MapDetector::MapDetector(Color color, VideoOverlay* overlay) + : m_color(color) + , m_travel_icon(0.040000, 0.235000, 0.030000, 0.068500) + , m_x_button( + color, + ButtonType::ButtonX, + {0.005000, 0.150000, 0.025000, 0.110000}, + overlay + ) + , m_y_button( + color, + ButtonType::ButtonY, + {0.005000, 0.210000, 0.025000, 0.110000}, + overlay + ) +{} + +void MapDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(m_color, m_travel_icon); + m_x_button.make_overlays(items); + m_y_button.make_overlays(items); +} + +bool MapDetector::detect(const ImageViewRGB32& screen){ +// cout << "MapDetector::detect()" << endl; + const bool detected = detect_travel_spot(screen) + && m_x_button.detect(screen) + && m_y_button.detect(screen); + + if (detected){ + for (MapIconDetector* detector : m_map_icon_detectors){ + detector->detect(screen); + } + } + return detected; +} + + +bool MapDetector::detect_travel_spot(const ImageViewRGB32& screen){ + // Progressive cyan filters to handle capture-card color variance. + static const std::vector> CYAN_FILTERS{ + // Brighter cyan/teal. + {0xff004898, 0xff70ffff}, + {0xff003878, 0xff80ffff}, + // Darker/desaturated cyan seen in some captures (e.g. 1080p hyperspace_True). + {0xff002860, 0xff90ffff}, + {0xff001c50, 0xffa0ffff}, + }; + + double rel = screen.height() / 2160.0; + size_t min_area = size_t(50.0 * rel * rel); + + return match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_travel_icon), + TravelSpotMatcher::instance(), + CYAN_FILTERS, + {min_area, SIZE_MAX}, + 100.0, + [](Kernels::Waterfill::WaterfillObject&) -> bool{ return true; } + ); +} +std::vector MapDetector::detected_map_icons() const{ + std::vector ret; + for (MapIconDetector* detector : m_map_icon_detectors){ + const auto& detected_boxes = detector->last_detected(); + for (const auto& box: detected_boxes){ + ret.emplace_back(box.name, box.box); } } -} \ No newline at end of file + return ret; +} + +void MapDetector::reset_state(){ + m_x_button.reset_state(); + m_y_button.reset_state(); + for (MapIconDetector* detector : m_map_icon_detectors){ + detector->reset_state(); + } +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h index 96882c9a8b..9ba955ba25 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h +++ b/SerialPrograms/Source/PokemonLZA/Inference/Map/PokemonLZA_MapDetector.h @@ -11,68 +11,66 @@ #include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" #include "CommonTools/DetectedBoxes.h" -namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ - class MapIconDetector; +class MapIconDetector; - // Detect whether the map view is opened or not - class MapDetector : public StaticScreenDetector { - public: - MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); +// Detect whether the map view is opened or not +class MapDetector : public StaticScreenDetector{ +public: + MapDetector(Color color = COLOR_RED, VideoOverlay* overlay = nullptr); - // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. - // After detection session is done, call `detected_map_icons()` to get last detected map icons. - void attach_map_icon_detector(MapIconDetector& detector) { - m_map_icon_detectors.push_back(&detector); - } + // Attach MapIconDetector. Those will be called if a map is detected to detect map icons. + // After detection session is done, call `detected_map_icons()` to get last detected map icons. + void attach_map_icon_detector(MapIconDetector& detector){ + m_map_icon_detectors.push_back(&detector); + } - virtual void make_overlays(VideoOverlaySet& items) const override; + virtual void make_overlays(VideoOverlaySet& items) const override; - // This is not const so that detectors can save/cache state. - virtual bool detect(const ImageViewRGB32& screen) override; + // This is not const so that detectors can save/cache state. + virtual bool detect(const ImageViewRGB32& screen) override; - // Return last detected map icons from attached MapIconDetectors. - std::vector detected_map_icons() const; + // Return last detected map icons from attached MapIconDetectors. + std::vector detected_map_icons() const; - void reset_state() override; + void reset_state() override; - private: - bool detect_travel_spot(const ImageViewRGB32& screen); +private: + bool detect_travel_spot(const ImageViewRGB32& screen); - private: - Color m_color; - ImageFloatBox m_travel_icon; - ButtonDetector m_x_button; - ButtonDetector m_y_button; - std::vector m_map_icon_detectors; - }; +private: + Color m_color; + ImageFloatBox m_travel_icon; + ButtonDetector m_x_button; + ButtonDetector m_y_button; + std::vector m_map_icon_detectors; +}; - class MapWatcher : public DetectorToFinder { - public: - MapWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) - ) - : DetectorToFinder("MapWatcher", hold_duration, color, overlay) - { - } - }; - class MapOverWatcher : public DetectorToFinder { - public: - MapOverWatcher( - Color color = COLOR_RED, - VideoOverlay* overlay = nullptr, - std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) - ) - : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) - { - } - }; +class MapWatcher : public DetectorToFinder{ +public: + MapWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("MapWatcher", hold_duration, color, overlay) + {} +}; +class MapOverWatcher : public DetectorToFinder{ +public: + MapOverWatcher( + Color color = COLOR_RED, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(200) + ) + : DetectorToFinder("MapWatcher", FinderType::GONE, hold_duration, color, overlay) + {} +}; @@ -81,7 +79,7 @@ namespace PokemonAutomation { - } - } } -#endif \ No newline at end of file +} +} +#endif