From 98cd86e8593f11db77c42172be580249d990ec02 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Thu, 21 May 2026 20:18:41 -0500 Subject: [PATCH 1/6] Home selection arrow detection --- .../PokemonHome_SelectionArrowDetector.cpp | 116 ++++++++++++++++++ .../PokemonHome_SelectionArrowDetector.h | 69 +++++++++++ SerialPrograms/cmake/SourceFiles.cmake | 2 + 3 files changed, 187 insertions(+) create mode 100644 SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp create mode 100644 SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp new file mode 100644 index 0000000000..c4b46f145d --- /dev/null +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp @@ -0,0 +1,116 @@ +/* Selection Arrow Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "Common/Cpp/Exceptions.h" +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" +#include "CommonTools/Images/WaterfillUtilities.h" +#include "PokemonHome_SelectionArrowDetector.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonHome{ + + + +class SelectionArrowMatcher : public ImageMatch::WaterfillTemplateMatcher{ +public: + // The Pokemon Home arrows are red on a light background. + SelectionArrowMatcher(const char* path) + : WaterfillTemplateMatcher( + path, + Color(0xffa00000), Color(0xffffc0c0), 100 + ) + { + m_aspect_ratio_lower = 0.9; + m_aspect_ratio_upper = 1.1; + m_area_ratio_lower = 0.85; + m_area_ratio_upper = 1.1; + } + + static const SelectionArrowMatcher& matcher(SelectionArrowType type){ + switch (type){ + case SelectionArrowType::RIGHT: + return RIGHT_ARROW(); + case SelectionArrowType::DOWN: + return DOWN_ARROW(); + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid enum."); + } + } + static const SelectionArrowMatcher& RIGHT_ARROW(){ + static SelectionArrowMatcher matcher("PokemonHome/SelectionArrowRight.png"); + return matcher; + } + static const SelectionArrowMatcher& DOWN_ARROW(){ + static SelectionArrowMatcher matcher("PokemonHome/SelectionArrowDown.png"); + return matcher; + } +}; + + + +SelectionArrowDetector::SelectionArrowDetector( + Color color, + VideoOverlay* overlay, + SelectionArrowType type, + const ImageFloatBox& box +) + : m_color(color) + , m_overlay(overlay) + , m_type(type) + , m_arrow_box(box) +{} +void SelectionArrowDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(m_color, m_arrow_box); +} +bool SelectionArrowDetector::detect(const ImageViewRGB32& screen){ + double screen_rel_size = (screen.height() / 1080.0); + double screen_rel_size_2 = screen_rel_size * screen_rel_size; + + double min_area_1080p = 700; + double rmsd_threshold = 80; + size_t min_area = size_t(screen_rel_size_2 * min_area_1080p); + + const std::vector> FILTERS = { + {0xff800000, 0xffff9090}, + {0xffa00000, 0xffffa0a0}, + {0xffc00000, 0xffffc0c0}, + {0xffd00000, 0xffffd0d0}, + }; + + bool found = match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_arrow_box), + SelectionArrowMatcher::matcher(m_type), + FILTERS, + {min_area, SIZE_MAX}, + rmsd_threshold, + [&](Kernels::Waterfill::WaterfillObject& object) -> bool { + m_last_detected = translate_to_parent(screen, m_arrow_box, object); + return true; + } + ); + + if (m_overlay){ + if (found){ + m_last_detected_box.emplace(*m_overlay, m_last_detected, COLOR_GREEN); + }else{ + m_last_detected_box.reset(); + } + } + + return found; +} + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h new file mode 100644 index 0000000000..0f1f41223f --- /dev/null +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h @@ -0,0 +1,69 @@ +/* Selection Arrow Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonHome_SelectionArrowDetector_H +#define PokemonAutomation_PokemonHome_SelectionArrowDetector_H + +#include +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "CommonTools/VisualDetector.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonHome{ + + +enum class SelectionArrowType{ + RIGHT, + DOWN, +}; + + +class SelectionArrowDetector : public StaticScreenDetector{ +public: + SelectionArrowDetector( + Color color, + VideoOverlay* overlay, + SelectionArrowType type, + const ImageFloatBox& box + ); + + const ImageFloatBox& last_detected() const{ return m_last_detected; } + + virtual void make_overlays(VideoOverlaySet& items) const override; + + virtual bool detect(const ImageViewRGB32& screen) override; + +private: + friend class SelectionArrowWatcher; + + const Color m_color; + VideoOverlay* m_overlay; + const SelectionArrowType m_type; + const ImageFloatBox m_arrow_box; + + ImageFloatBox m_last_detected; + std::optional m_last_detected_box; +}; +class SelectionArrowWatcher : public DetectorToFinder{ +public: + SelectionArrowWatcher( + Color color, + VideoOverlay* overlay, + SelectionArrowType type, + const ImageFloatBox& box, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("SelectionArrowWatcher", hold_duration, color, overlay, type, box) + {} +}; + + +} +} +} +#endif diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 487aa970bf..6b72674b32 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1577,6 +1577,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h + Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp + Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h Source/PokemonHome/Inference/PokemonHome_TeraTypeReader.cpp From e7b243f1c5c69104bd1b8098852c0ac483b8f67d Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Thu, 21 May 2026 21:27:31 -0500 Subject: [PATCH 2/6] Added origin mark reader --- .../Source/Pokemon/Pokemon_OriginMarks.cpp | 31 ++ .../Source/Pokemon/Pokemon_OriginMarks.h | 34 ++ .../PokemonHome_OriginMarkReader.cpp | 351 ++++++++++++++++++ .../Inference/PokemonHome_OriginMarkReader.h | 38 ++ SerialPrograms/cmake/SourceFiles.cmake | 4 + 5 files changed, 458 insertions(+) create mode 100644 SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.cpp create mode 100644 SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.h create mode 100644 SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp create mode 100644 SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h diff --git a/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.cpp b/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.cpp new file mode 100644 index 0000000000..3574e40c7c --- /dev/null +++ b/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.cpp @@ -0,0 +1,31 @@ +/* Pokemon Origin Marks + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "Pokemon_OriginMarks.h" + +namespace PokemonAutomation{ +namespace Pokemon{ + +const EnumStringMap& ORIGIN_MARK_SLUGS(){ + static EnumStringMap database{ + {OriginMark::KALOS, "kalos"}, + {OriginMark::ALOLA, "alola"}, + {OriginMark::GAMEBOY, "gameboy"}, + {OriginMark::GO, "go"}, + {OriginMark::LGPE, "lgpe"}, + {OriginMark::GALAR, "galar"}, + {OriginMark::BDSP, "bdsp"}, + {OriginMark::LA, "la"}, + {OriginMark::SV, "sv"}, + {OriginMark::LZA, "lza"}, + {OriginMark::NONE, "none"} + }; + return database; +} + + +} +} diff --git a/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.h b/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.h new file mode 100644 index 0000000000..be1cc0f312 --- /dev/null +++ b/SerialPrograms/Source/Pokemon/Pokemon_OriginMarks.h @@ -0,0 +1,34 @@ +/* Pokemon Origin Marks + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_Pokemon_OriginMarks_H +#define PokemonAutomation_Pokemon_OriginMarks_H + +#include "Common/Cpp/EnumStringMap.h" + +namespace PokemonAutomation{ +namespace Pokemon{ + + +enum class OriginMark{ + KALOS, + ALOLA, + GAMEBOY, + GO, + LGPE, + GALAR, + BDSP, + LA, + SV, + LZA, + NONE, +}; +const EnumStringMap& ORIGIN_MARK_SLUGS(); + + +} +} +#endif diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp new file mode 100644 index 0000000000..8073766e80 --- /dev/null +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp @@ -0,0 +1,351 @@ +/* Origin Mark Reader + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "PokemonHome_OriginMarkReader.h" +#include +#include "CommonTools/Images/WaterfillUtilities.h" +#include "Kernels/Waterfill/Kernels_Waterfill.h" +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonFramework/ImageTypes/BinaryImage.h" +#include "CommonFramework/ImageTools/ImageStats.h" +#include "CommonFramework/Logging/Logger.h" +#include "CommonFramework/Tools/DebugDumper.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" +#include +#include +#include "CommonTools/ImageMatch/ExactImageMatcher.h" +#include "CommonTools/Images/BinaryImage_FilterRgb32.h" +#include "CommonTools/Images/ImageFilter.h" +#include "CommonFramework/Globals.h" +#include "CommonTools/DetectedBoxes.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonHome{ + +using ImageMatch::WaterfillTemplateMatcher; +using namespace Kernels; +using namespace Kernels::Waterfill; + +class OriginMarkSprite { +public: + OriginMarkSprite(const std::string& slug, const std::string& resource_location) + : m_slug(slug) + { + ImageRGB32 sprite(RESOURCE_PATH() + resource_location); + + sprite = filter_rgb32_range( + sprite, + 0xff000000, 0xffffffff, + Color(0), false + ); + + PackedBinaryMatrix matrix = compress_rgb32_to_binary_min(sprite, 93, 100, 83); + std::vector objects = find_objects_inplace(matrix, 10); + + WaterfillObject object; + for (const WaterfillObject& item : objects){ + object.merge_assume_no_overlap(item); + } + + m_aspect_ratio = object.aspect_ratio(); + m_matcher = std::make_unique( + sprite.sub_image(object.min_x, object.min_y, object.width(), object.height()).copy(), + ImageMatch::WeightedExactImageMatcher::InverseStddevWeight{ 1, 64 } + ); + } + + const std::string& slug() const { return m_slug; } + double aspect_ratio() const { return m_aspect_ratio; } + const ImageMatch::WeightedExactImageMatcher& matcher() const { return *m_matcher; } + +private: + std::string m_slug; + double m_aspect_ratio; + std::unique_ptr m_matcher; +}; + +struct OriginMarkSpriteDatabase { + std::map m_mark_map; + + static OriginMarkSpriteDatabase& instance(){ + static OriginMarkSpriteDatabase data; + return data; + } + + OriginMarkSpriteDatabase(){ + for (const auto& item : Pokemon::ORIGIN_MARK_SLUGS()){ + if (item.first == OriginMark::NONE || item.first == OriginMark::GAMEBOY){ //TODO: Need to find someone with the gameboy sprite + continue; + } + m_mark_map.emplace(item.first, OriginMarkSprite(item.second, "PokemonHome/OriginMarks/" + item.second + ".png")); + } + } +}; + +class MarkIconMatcher : public ImageMatch::WaterfillTemplateMatcher{ +public: + MarkIconMatcher( + const char* path, + std::string name, + Color min_color, Color max_color, + size_t min_area, + double max_rmsd, + std::vector> filters, + double area_ratio_override = 0 + ) + : WaterfillTemplateMatcher(path, min_color, max_color, min_area) + , m_name(std::move(name)) + , m_max_rmsd(max_rmsd) + , m_filters(std::move(filters)) + { + if (area_ratio_override != 0){ + m_area_ratio = area_ratio_override; + } + } + + const std::string& name() const{ + return m_name; + } + double max_rmsd() const{ + return m_max_rmsd; + } + const std::vector>& filters() const{ + return m_filters; + } + +private: + std::string m_name; + double m_max_rmsd; + std::vector> m_filters; +}; + +const MarkIconMatcher& MarkIcon_Kalos(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/kalos.png", + "kalos", + Color(0xff61645c), Color(0xff646664), + 10, + 40.0, + { + {0xff61645c, 0xff646664}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Alola(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/alola.png", + "alola", + Color(0xff5f6456), Color(0xff6d706b), + 10, + 35.0, + { + {0xff5f6456, 0xff6d706b}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Go(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/go.png", + "go", + Color(0xff5c644e), Color(0xff798073), + 10, + 45.0, + { + {0xff5c644e, 0xff798073}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Lgpe(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/lgpe.png", + "lgpe", + Color(0xff616459), Color(0xff676d64), + 10, + 20.0, + { + {0xff616459, 0xff676d64}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Galar(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/galar.png", + "galar", + Color(0xff5e6453), Color(0xff757870), + 10, + 45.0, + { + {0xff5e6453, 0xff757870}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Bdsp(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/bdsp.png", + "bdsp", + Color(0xff5f6457), Color(0xff767972), + 10, + 45.0, + { + {0xff5f6457, 0xff767972}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_La(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/la.png", + "la", + Color(0xff606459), Color(0xff686a65), + 10, + 30.0, + { + {0xff606459, 0xff686a65}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Sv(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/sv.png", + "sv", + Color(0xff5d6450), Color(0xff747771), + 10, + 50.0, + { + {0xff5d6450, 0xff747771}, + } + ); + return ret; +} + +const MarkIconMatcher& MarkIcon_Lza(){ + static MarkIconMatcher ret( + "PokemonHome/OriginMarks/lza.png", + "lza", + Color(0xff61645b), Color(0xff646764), + 10, + 20.0, + { + {0xff61645b, 0xff646764}, + } + ); + return ret; +} + +//TODO: GAMEBOY + +const std::vector& ALL_ORIGIN_MARK_MATCHERS(){ + static const std::vector matchers = { + &MarkIcon_Kalos(), + &MarkIcon_Alola(), + &MarkIcon_Go(), + &MarkIcon_Lgpe(), + &MarkIcon_Galar(), + &MarkIcon_Bdsp(), + &MarkIcon_La(), + &MarkIcon_Sv(), + &MarkIcon_Lza(), + }; + return matchers; +} + +const MarkIconMatcher& get_mark_icon_matcher(OriginMark mark){ + switch (mark){ + case OriginMark::KALOS: + return MarkIcon_Kalos(); + case OriginMark::ALOLA: + return MarkIcon_Alola(); + case OriginMark::GO: + return MarkIcon_Go(); + case OriginMark::LGPE: + return MarkIcon_Lgpe(); + case OriginMark::GALAR: + return MarkIcon_Galar(); + case OriginMark::BDSP: + return MarkIcon_Bdsp(); + case OriginMark::LA: + return MarkIcon_La(); + case OriginMark::SV: + return MarkIcon_Sv(); + case OriginMark::LZA: + return MarkIcon_Lza(); + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid origin mark: " + std::to_string((int)mark)); + } +} + +OriginMark origin_mark_from_slug(const std::string& slug){ + for (const auto& item : Pokemon::ORIGIN_MARK_SLUGS()){ + if (item.second == slug){ + return item.first; + } + } + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid origin mark slug: " + slug); +} + +OriginMark OriginMarkReader::read_mark( + const ImageViewRGB32& original_screen, + const ImageFloatBox& box +){ + const double screen_rel_size = (original_screen.height() / 1080.0); + const double screen_rel_size_2 = screen_rel_size * screen_rel_size; + + const double min_area_1080p = 400; + const size_t min_area = size_t(screen_rel_size_2 * min_area_1080p); + + ImageViewRGB32 image = extract_box_reference(original_screen, box); + const ImageStats roi_stats = image_stats(image); + + m_last_detected.clear(); + + std::multimap> candidates; + + for (const MarkIconMatcher* matcher : ALL_ORIGIN_MARK_MATCHERS()){ + match_template_by_waterfill( + original_screen.size(), + image, + *matcher, + matcher->filters(), + { min_area, SIZE_MAX }, + matcher->max_rmsd(), + [&](Kernels::Waterfill::WaterfillObject& object) -> bool { + + m_last_detected.emplace_back( + DetectedBox{ + matcher->name(), + translate_to_parent(original_screen, box, object) + } + ); + return true; + } + ); + + if (!m_last_detected.empty()){ + return origin_mark_from_slug(m_last_detected[0].name); + } + } + + return OriginMark::NONE; +} + + +} +} +} diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h new file mode 100644 index 0000000000..92056ebf20 --- /dev/null +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h @@ -0,0 +1,38 @@ +/* Origin Mark Reader + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonHome_OriginMarkReader_H +#define PokemonAutomation_PokemonHome_OriginMarkReader_H + +#include "CommonFramework/ImageTypes/ImageViewRGB32.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "Pokemon/Pokemon_OriginMarks.h" +#include +#include "CommonTools/DetectedBoxes.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonHome{ + + +using Pokemon::OriginMark; + +class OriginMarkReader{ +public: + OriginMark read_mark( + const ImageViewRGB32& original_screen, + const ImageFloatBox& box + ); + +private: + std::vector m_last_detected; + +}; + +} +} +} +#endif diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 6b72674b32..14887c68ad 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1283,6 +1283,8 @@ file(GLOB LIBRARY_SOURCES Source/Pokemon/Pokemon_NatureChecker.h Source/Pokemon/Pokemon_Notification.cpp Source/Pokemon/Pokemon_Notification.h + Source/Pokemon/Pokemon_OriginMarks.cpp + Source/Pokemon/Pokemon_OriginMarks.h Source/Pokemon/Pokemon_ShinySparkleSet.cpp Source/Pokemon/Pokemon_ShinySparkleSet.h Source/Pokemon/Pokemon_StatsCalculation.cpp @@ -1573,6 +1575,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBattleLevelUp.h Source/PokemonHome/Inference/PokemonHome_BallReader.cpp Source/PokemonHome/Inference/PokemonHome_BallReader.h + Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp + Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp From 9185d0e9637a6437cc5d6157bbc4330c9713fcac Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Fri, 22 May 2026 10:36:18 -0500 Subject: [PATCH 3/6] Update resource locations --- .../Inference/PokemonHome_SelectionArrowDetector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp index c4b46f145d..45d84a99c3 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp @@ -42,11 +42,11 @@ class SelectionArrowMatcher : public ImageMatch::WaterfillTemplateMatcher{ } } static const SelectionArrowMatcher& RIGHT_ARROW(){ - static SelectionArrowMatcher matcher("PokemonHome/SelectionArrowRight.png"); + static SelectionArrowMatcher matcher("PokemonHome/SelectionArrows/SelectionArrowRight.png"); return matcher; } static const SelectionArrowMatcher& DOWN_ARROW(){ - static SelectionArrowMatcher matcher("PokemonHome/SelectionArrowDown.png"); + static SelectionArrowMatcher matcher("PokemonHome/SelectionArrows/SelectionArrowDown.png"); return matcher; } }; From c1a78b6fbf38e7cdf83cf7ec7010c2c8f48c11e9 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Fri, 22 May 2026 10:54:57 -0500 Subject: [PATCH 4/6] cleanup --- .../PokemonHome_OriginMarkReader.cpp | 78 ++----------------- .../Inference/PokemonHome_OriginMarkReader.h | 6 +- .../PokemonHome_SelectionArrowDetector.cpp | 12 +-- 3 files changed, 10 insertions(+), 86 deletions(-) diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp index 8073766e80..5c9412b01c 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp @@ -4,88 +4,20 @@ * */ -#include "PokemonHome_OriginMarkReader.h" #include +#include #include "CommonTools/Images/WaterfillUtilities.h" -#include "Kernels/Waterfill/Kernels_Waterfill.h" -#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" -#include "CommonFramework/ImageTypes/BinaryImage.h" #include "CommonFramework/ImageTools/ImageStats.h" -#include "CommonFramework/Logging/Logger.h" -#include "CommonFramework/Tools/DebugDumper.h" +#include "CommonTools/DetectedBoxes.h" #include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" -#include -#include #include "CommonTools/ImageMatch/ExactImageMatcher.h" -#include "CommonTools/Images/BinaryImage_FilterRgb32.h" -#include "CommonTools/Images/ImageFilter.h" -#include "CommonFramework/Globals.h" -#include "CommonTools/DetectedBoxes.h" +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "PokemonHome_OriginMarkReader.h" namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonHome{ -using ImageMatch::WaterfillTemplateMatcher; -using namespace Kernels; -using namespace Kernels::Waterfill; - -class OriginMarkSprite { -public: - OriginMarkSprite(const std::string& slug, const std::string& resource_location) - : m_slug(slug) - { - ImageRGB32 sprite(RESOURCE_PATH() + resource_location); - - sprite = filter_rgb32_range( - sprite, - 0xff000000, 0xffffffff, - Color(0), false - ); - - PackedBinaryMatrix matrix = compress_rgb32_to_binary_min(sprite, 93, 100, 83); - std::vector objects = find_objects_inplace(matrix, 10); - - WaterfillObject object; - for (const WaterfillObject& item : objects){ - object.merge_assume_no_overlap(item); - } - - m_aspect_ratio = object.aspect_ratio(); - m_matcher = std::make_unique( - sprite.sub_image(object.min_x, object.min_y, object.width(), object.height()).copy(), - ImageMatch::WeightedExactImageMatcher::InverseStddevWeight{ 1, 64 } - ); - } - - const std::string& slug() const { return m_slug; } - double aspect_ratio() const { return m_aspect_ratio; } - const ImageMatch::WeightedExactImageMatcher& matcher() const { return *m_matcher; } - -private: - std::string m_slug; - double m_aspect_ratio; - std::unique_ptr m_matcher; -}; - -struct OriginMarkSpriteDatabase { - std::map m_mark_map; - - static OriginMarkSpriteDatabase& instance(){ - static OriginMarkSpriteDatabase data; - return data; - } - - OriginMarkSpriteDatabase(){ - for (const auto& item : Pokemon::ORIGIN_MARK_SLUGS()){ - if (item.first == OriginMark::NONE || item.first == OriginMark::GAMEBOY){ //TODO: Need to find someone with the gameboy sprite - continue; - } - m_mark_map.emplace(item.first, OriginMarkSprite(item.second, "PokemonHome/OriginMarks/" + item.second + ".png")); - } - } -}; - class MarkIconMatcher : public ImageMatch::WaterfillTemplateMatcher{ public: MarkIconMatcher( @@ -348,4 +280,4 @@ OriginMark OriginMarkReader::read_mark( } } -} +} \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h index 92056ebf20..2d817ea989 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h @@ -7,11 +7,11 @@ #ifndef PokemonAutomation_PokemonHome_OriginMarkReader_H #define PokemonAutomation_PokemonHome_OriginMarkReader_H +#include #include "CommonFramework/ImageTypes/ImageViewRGB32.h" #include "CommonFramework/ImageTools/ImageBoxes.h" -#include "Pokemon/Pokemon_OriginMarks.h" -#include #include "CommonTools/DetectedBoxes.h" +#include "Pokemon/Pokemon_OriginMarks.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -35,4 +35,4 @@ class OriginMarkReader{ } } } -#endif +#endif \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp index 45d84a99c3..58c472e3bc 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp @@ -5,9 +5,9 @@ */ #include "Common/Cpp/Exceptions.h" -#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" #include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "CommonTools/Images/WaterfillUtilities.h" +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" #include "PokemonHome_SelectionArrowDetector.h" namespace PokemonAutomation{ @@ -15,7 +15,6 @@ namespace NintendoSwitch{ namespace PokemonHome{ - class SelectionArrowMatcher : public ImageMatch::WaterfillTemplateMatcher{ public: // The Pokemon Home arrows are red on a light background. @@ -51,8 +50,6 @@ class SelectionArrowMatcher : public ImageMatch::WaterfillTemplateMatcher{ } }; - - SelectionArrowDetector::SelectionArrowDetector( Color color, VideoOverlay* overlay, @@ -106,11 +103,6 @@ bool SelectionArrowDetector::detect(const ImageViewRGB32& screen){ return found; } - - - - - -} } } +} \ No newline at end of file From 1094232cbfd2ae6ee4666d3e74c90e2e1f066901 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Fri, 22 May 2026 10:58:01 -0500 Subject: [PATCH 5/6] cleanup sourcefiles --- SerialPrograms/cmake/SourceFiles.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 14887c68ad..d72cce0f4b 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1575,16 +1575,16 @@ file(GLOB LIBRARY_SOURCES Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadBattleLevelUp.h Source/PokemonHome/Inference/PokemonHome_BallReader.cpp Source/PokemonHome/Inference/PokemonHome_BallReader.h - Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp - Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h - Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp - Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h + Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp + Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.h + Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp + Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h Source/PokemonHome/Inference/PokemonHome_TeraTypeReader.cpp Source/PokemonHome/Inference/PokemonHome_TeraTypeReader.h Source/PokemonHome/PokemonHome_Panels.cpp From 426719fa29d4aa7babc4b75ded85fbd52df99707 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Fri, 22 May 2026 11:15:25 -0500 Subject: [PATCH 6/6] Remove testing code --- .../PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp index 5c9412b01c..e7a6cffe8b 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_OriginMarkReader.cpp @@ -243,7 +243,6 @@ OriginMark OriginMarkReader::read_mark( const size_t min_area = size_t(screen_rel_size_2 * min_area_1080p); ImageViewRGB32 image = extract_box_reference(original_screen, box); - const ImageStats roi_stats = image_stats(image); m_last_detected.clear();