diff --git a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp index d9525c6875..1301c2cb61 100644 --- a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp +++ b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp @@ -4,7 +4,6 @@ * */ -#include #include "Common/Cpp/Color.h" #include "Kernels/Waterfill/Kernels_Waterfill_Session.h" #include "Kernels/Waterfill/Kernels_Waterfill_Types.h" @@ -21,7 +20,6 @@ using std::cout; using std::endl; - namespace PokemonAutomation{ using namespace Kernels::Waterfill; @@ -39,25 +37,28 @@ std::pair remove_center_pixels( // Sort all pixels by distance from center. size_t center_x = (size_t)(object.center_of_gravity_x() - object.min_x); size_t center_y = (size_t)(object.center_of_gravity_y() - object.min_y); - std::map distances; + std::vector distances; + distances.reserve(object.area); for (size_t r = 0; r < height; r++){ for (size_t c = 0; c < width; c++){ if (matrix.get(c, r)){ size_t dist_x = c - center_x; size_t dist_y = r - center_y; uint64_t distance_sqr = (uint64_t)dist_x*dist_x + (uint64_t)dist_y*dist_y; - distances[distance_sqr]++; + distances.emplace_back(distance_sqr); } } } +// cout << "total = " << total << endl; + // Filter out pixels close to center size_t count = 0; uint64_t distance_sqr_th = 0; - for (auto& item : distances){ - count += item.second; + for (uint64_t item : distances){ + count++; if (count >= num_pixels_to_remove){ - distance_sqr_th = item.first; + distance_sqr_th = item; break; } } diff --git a/SerialPrograms/Source/Pokemon/Pokemon_ShinySparkleSet.cpp b/SerialPrograms/Source/Pokemon/Pokemon_ShinySparkleSet.cpp index 4efa1960b7..b4ff3d19ad 100644 --- a/SerialPrograms/Source/Pokemon/Pokemon_ShinySparkleSet.cpp +++ b/SerialPrograms/Source/Pokemon/Pokemon_ShinySparkleSet.cpp @@ -4,8 +4,8 @@ * */ +#include "Common/Cpp/Logging/AbstractLogger.h" #include "CommonFramework/ImageTypes/ImageViewRGB32.h" -#include "CommonFramework/Logging/Logger.h" #include "Pokemon_ShinySparkleSet.h" namespace PokemonAutomation{ diff --git a/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_ShinySparkleSet.cpp b/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_ShinySparkleSet.cpp index 0a5e317821..a4ddd8dd3f 100644 --- a/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_ShinySparkleSet.cpp +++ b/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_ShinySparkleSet.cpp @@ -4,8 +4,10 @@ * */ +#include #include #include "Common/Cpp/Concurrency/SpinLock.h" +#include "Common/Cpp/Concurrency/AsyncTask.h" #include "Kernels/Waterfill/Kernels_Waterfill_Session.h" #include "CommonFramework/Tools/GlobalThreadPools.h" #include "CommonTools/Images/BinaryImage_FilterRgb32.h" @@ -85,29 +87,52 @@ void ShinySparkleSetSwSh::update_alphas(){ +void find_sparkles( + size_t screen_area, + SpinLock& lock, + ShinySparkleSetSwSh& sparkles, + const WaterfillObject& object +){ + RadialSparkleDetector radial_sparkle(screen_area, object); + if (radial_sparkle.is_ball()){ + WriteSpinLock lg(lock); + sparkles.balls.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); + return; + } + if (radial_sparkle.is_star()){ + WriteSpinLock lg(lock); + sparkles.stars.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); + return; + } + if (is_line_sparkle(object)){ + WriteSpinLock lg(lock); + sparkles.lines.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); + return; + } + if (is_square_sparkle(object)){ + WriteSpinLock lg(lock); + sparkles.squares.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); + return; + } +} ShinySparkleSetSwSh find_sparkles(size_t screen_area, WaterfillSession& session){ + SpinLock lock; ShinySparkleSetSwSh sparkles; auto finder = session.make_iterator(20); WaterfillObject object; + std::deque tasks; while (finder->find_next(object, true)){ - RadialSparkleDetector radial_sparkle(screen_area, object); - if (radial_sparkle.is_ball()){ - sparkles.balls.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); - continue; - } - if (radial_sparkle.is_star()){ - sparkles.stars.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); - continue; - } - if (is_line_sparkle(object)){ - sparkles.lines.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); - continue; - } - if (is_square_sparkle(object)){ - sparkles.squares.emplace_back(object.min_x, object.min_y, object.max_x, object.max_y); - continue; - } + tasks.emplace_back(GlobalThreadPools::computation_realtime().dispatch_now_blocking( + [&, screen_area, object = std::move(object)]{ + find_sparkles( + screen_area, + lock, + sparkles, + object + ); + } + )); } return sparkles; } diff --git a/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_SparkleDetectorSquare.cpp b/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_SparkleDetectorSquare.cpp index 61647da557..cf798ef72d 100644 --- a/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_SparkleDetectorSquare.cpp +++ b/SerialPrograms/Source/PokemonSwSh/Inference/ShinyDetection/PokemonSwSh_SparkleDetectorSquare.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include "Kernels/Waterfill/Kernels_Waterfill.h" #include "Kernels/Waterfill/Kernels_Waterfill_Session.h" @@ -12,6 +13,10 @@ #include "CommonTools/Images/DistanceToLine.h" #include "PokemonSwSh_SparkleDetectorSquare.h" +//#include +//using std::cout; +//using std::endl; + namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonSwSh{ @@ -313,7 +318,7 @@ double normalize_angle_0_360_new(double angle){ // Get all the pixels that border the background. -std::multimap> get_edge_pixels( +std::vector>> get_edge_pixels( const PackedBinaryMatrix& object, const WaterfillObject& background, size_t center_x, size_t center_y, @@ -322,7 +327,7 @@ std::multimap> get_edge_pixels( size_t width = object.width(); size_t height = object.height(); - std::multimap> edge_pixels; + std::vector>> edge_pixels; if (background.area == 0){ // No background. Grab the entire edge. for (size_t r = 0; r < height; r++){ @@ -337,7 +342,7 @@ std::multimap> get_edge_pixels( (ptrdiff_t)c - (ptrdiff_t)center_x ) * 57.295779513082320877; angle = normalize_angle_0_360_new(angle - base_angle); - edge_pixels.emplace( + edge_pixels.emplace_back( angle, std::pair{c, r} ); @@ -365,7 +370,7 @@ std::multimap> get_edge_pixels( (ptrdiff_t)c - (ptrdiff_t)center_x ) * 57.295779513082320877; angle = normalize_angle_0_360_new(angle - base_angle); - edge_pixels.emplace( + edge_pixels.emplace_back( angle, std::pair{c, r} ); @@ -376,6 +381,32 @@ std::multimap> get_edge_pixels( } +template +typename std::vector>::const_iterator lower_bound( + const std::vector>& sorted_vector, + const Key& target +){ + return std::lower_bound( + sorted_vector.begin(), sorted_vector.end(), target, + [](const std::pair& element, const Key& key) { + return element.first < key; + } + ); +} +template +typename std::vector>::const_iterator upper_bound( + const std::vector>& sorted_vector, + const Key& target +){ + return std::upper_bound( + sorted_vector.begin(), sorted_vector.end(), target, + [](const Key& key, const std::pair& element) { + return key < element.first; + } + ); +} + + double area_of_triangle( ptrdiff_t x0, ptrdiff_t y0, ptrdiff_t x1, ptrdiff_t y1, @@ -393,7 +424,7 @@ double area_of_triangle( // [point_hi_x, point_hi_y] // double sum_squares_from_line( - const std::multimap>& points_by_angle, + const std::vector>>& points_by_angle, double point_lo_angle, size_t point_lo_x, size_t point_lo_y, double point_hi_angle, size_t point_hi_x, size_t point_hi_y ){ @@ -404,8 +435,8 @@ double sum_squares_from_line( // double sum = 0; double sum_sqr = 0; - auto iter0 = points_by_angle.lower_bound(point_lo_angle); - auto iter1 = points_by_angle.lower_bound(point_hi_angle); + auto iter0 = lower_bound(points_by_angle, point_lo_angle); + auto iter1 = lower_bound(points_by_angle, point_hi_angle); DistanceToLine calc( point_lo_x, point_lo_y, point_hi_x, point_hi_y @@ -522,7 +553,7 @@ bool is_square_sparkle(const Kernels::Waterfill::WaterfillObject& object, double // Get all the edge pixels. - std::multimap> edge_pixels = get_edge_pixels( + std::vector>> edge_pixels = get_edge_pixels( matrix, background, center_x, center_y, far_corner0.angle ); @@ -533,6 +564,13 @@ bool is_square_sparkle(const Kernels::Waterfill::WaterfillObject& object, double // for (const auto& item : points_by_angle){ // cout << item.first << " : distance = " << item.second.distance << ", (" << item.second.x << "," << item.second.y << ")" << endl; // } + std::sort( + edge_pixels.begin(), + edge_pixels.end(), + [](const auto& a, const auto& b) { + return a.first < b.first; + } + ); PackedBinaryMatrix test(width, height);