From 605bc05495380be3ba23c298d9d3456d013ef40e Mon Sep 17 00:00:00 2001 From: jw098 Date: Fri, 1 Nov 2024 01:18:34 -0700 Subject: [PATCH] green filter (#497) --- SerialPrograms/CMakeLists.txt | 2 + SerialPrograms/SerialPrograms.pro | 2 + .../ImageTools/ImageFilter.cpp | 12 +++ .../CommonFramework/ImageTools/ImageFilter.h | 8 ++ .../ImageTools/SolidColorTest.h | 5 +- .../Kernels_ImageFilter_Basic.cpp | 21 +++++ .../ImageFilters/Kernels_ImageFilter_Basic.h | 6 +- .../Kernels_ImageFilter_Green_Default.cpp | 90 +++++++++++++++++++ 8 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp diff --git a/SerialPrograms/CMakeLists.txt b/SerialPrograms/CMakeLists.txt index 58e3ef831..da51665b9 100644 --- a/SerialPrograms/CMakeLists.txt +++ b/SerialPrograms/CMakeLists.txt @@ -688,6 +688,8 @@ file(GLOB MAIN_SOURCES Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_AVX2.cpp Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_AVX512.cpp Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_SSE42.cpp + Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp + Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.h Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness.cpp Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness.h Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_Default.cpp diff --git a/SerialPrograms/SerialPrograms.pro b/SerialPrograms/SerialPrograms.pro index fa3d40c2a..8f4cdea9a 100644 --- a/SerialPrograms/SerialPrograms.pro +++ b/SerialPrograms/SerialPrograms.pro @@ -350,6 +350,7 @@ SOURCES += \ Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_AVX2.cpp \ Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_AVX512.cpp \ Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic_x64_SSE42.cpp \ + Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp \ Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness.cpp \ Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_Default.cpp \ Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness_arm64_NEON.cpp \ @@ -1437,6 +1438,7 @@ HEADERS += \ Source/Kernels/BinaryMatrix/Kernels_SparseBinaryMatrixCore.h \ Source/Kernels/BinaryMatrix/Kernels_SparseBinaryMatrixCore.tpp \ Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.h \ + Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.h \ Source/Kernels/ImageScaleBrightness/Kernels_ImageScaleBrightness.h \ Source/Kernels/ImageStats/Kernels_ImagePixelSumSqr.h \ Source/Kernels/ImageStats/Kernels_ImagePixelSumSqrDev.h \ diff --git a/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.cpp b/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.cpp index a88c49dd1..5be6f90a3 100644 --- a/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.cpp +++ b/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.cpp @@ -143,6 +143,18 @@ std::vector> to_blackwhite_rgb32_range( return ret; } +ImageRGB32 filter_green( + const ImageViewRGB32& image, + Color replace_with, + uint8_t rgb_gap +){ + ImageRGB32 ret(image.width(), image.height()); + Kernels::filter_green( + image.data(), image.bytes_per_row(), image.width(), image.height(), + ret.data(), ret.bytes_per_row(), (uint32_t)replace_with, rgb_gap + ); + return ret; +} diff --git a/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.h b/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.h index 287632cda..1bd1f0c14 100644 --- a/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.h +++ b/SerialPrograms/Source/CommonFramework/ImageTools/ImageFilter.h @@ -119,6 +119,14 @@ std::vector> to_blackwhite_rgb32_range( ); +// keep all pixels where green is the dominant RGB value. otherwise, replace the pixel with `replace_with` +// `rgb_gap` is the amount that green has to exceed the red or blue value, in order to keep the pixel. +ImageRGB32 filter_green( + const ImageViewRGB32& image, + Color replace_with, + uint8_t rgb_gap = 0 +); + } diff --git a/SerialPrograms/Source/CommonFramework/ImageTools/SolidColorTest.h b/SerialPrograms/Source/CommonFramework/ImageTools/SolidColorTest.h index b8b61fbcb..b6d5f32c8 100644 --- a/SerialPrograms/Source/CommonFramework/ImageTools/SolidColorTest.h +++ b/SerialPrograms/Source/CommonFramework/ImageTools/SolidColorTest.h @@ -30,7 +30,10 @@ bool is_grey( double max_stddev_sum = 10 ); -// expected_color_ratio: ratio of color channels to match, e.g. if a color is (127, 127, 254), it's color ratio is (0.25, 0.25, 0.5) +// expected_color_ratio: ratio of color channels to match, +// for a color {r, g, b}: the color ratio is {r/(r+g+b), g/(r+g+b), b/(r+g+b)} +// the sum of the ratios should add up to 1.0. +// e.g. if a color is (127, 127, 254), it's color ratio is (0.25, 0.25, 0.5) bool is_solid( const ImageStats& stats, const FloatPixel& expected_color_ratio, diff --git a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.cpp b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.cpp index 46144d942..de3fcc505 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.cpp @@ -365,6 +365,27 @@ void to_blackwhite_rgb32_range( return to_blackwhite_rgb32_range_Default(image, bytes_per_row, width, height, filter, filter_count); } +size_t filter_green_Default( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, uint8_t rgb_gap +); + + +size_t filter_green( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, uint8_t rgb_gap +){ + if (width * height > 0xffffffff){ + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Image is too large. more than 2^32 pixels."); + } + return filter_green_Default( + in, in_bytes_per_row, width, height, + out, out_bytes_per_row, replacement, rgb_gap + ); +} + } diff --git a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.h b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.h index 7d991226a..8d1cd26f6 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.h +++ b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Basic.h @@ -109,7 +109,11 @@ void to_blackwhite_rgb32_range( - +size_t filter_green( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, uint8_t rgb_gap +); diff --git a/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp new file mode 100644 index 000000000..5a19bcf40 --- /dev/null +++ b/SerialPrograms/Source/Kernels/ImageFilters/Kernels_ImageFilter_Green_Default.cpp @@ -0,0 +1,90 @@ +/* Image Filters Basic (Default) + * + * From: https://github.com/PokemonAutomation/Arduino-Source + * + */ + +#include +#include +#include "Kernels_ImageFilter_Basic_Routines.h" + +namespace PokemonAutomation{ +namespace Kernels{ + + +class ImageFilter_Green_Default{ +public: + static const size_t VECTOR_SIZE = 1; + +public: + ImageFilter_Green_Default(uint32_t replacement_color, uint8_t rgb_gap) + : m_replacement_color(replacement_color) + , m_rgb_gap(rgb_gap) + , m_count(0) + {} + + PA_FORCE_INLINE size_t count() const{ + return m_count; + } + + PA_FORCE_INLINE void process_full(uint32_t* out, const uint32_t* in){ + uint32_t pixel = in[0]; + uint64_t ret = 1; + + uint16_t red = ((pixel >> 16) & 0xff); + uint16_t green = ((pixel >> 8) & 0xff); + uint16_t blue = ((pixel) & 0xff); + + ret &= (green >= red + m_rgb_gap) && (green >= blue + m_rgb_gap); + + + m_count += ret; + out[0] = ret ? pixel : m_replacement_color; + } + PA_FORCE_INLINE void process_partial(uint32_t* out, const uint32_t* in, size_t left){ + process_full(out, in); + } + +private: + const uint32_t m_replacement_color; + const uint16_t m_rgb_gap; + size_t m_count; +}; + + +size_t filter_green_Default( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement_color, uint8_t rgb_gap +){ + ImageFilter_Green_Default filter(replacement_color, rgb_gap); + filter_per_pixel(in, in_bytes_per_row, width, height, filter, out, out_bytes_per_row); + return filter.count(); +} + + + + + + + + + + + + + + + + + + + + + + + + + +} +}