diff --git a/CHANGELOG.md b/CHANGELOG.md index c453a0b10efffada3a2faa07739217ead76d04f2..d96fc0663d1c54211c24e035bfec905db849491d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This changelog aims to follow the guiding principles of ### Added - Implementation of Rotate 90 degrees clockwise. +- Remap function with nearest neighbour and fixed-point interpolation for 8-bit inputs. ### Changed - Increased precision of sum for 32 bit floats and expose it to OpenCV HAL. diff --git a/adapters/opencv/kleidicv_hal.cpp b/adapters/opencv/kleidicv_hal.cpp index 3912cee534c86694ea14d4f0c999ca7e74ea95f7..0a6aa9c6e78125b274f684186aa961526780212a 100644 --- a/adapters/opencv/kleidicv_hal.cpp +++ b/adapters/opencv/kleidicv_hal.cpp @@ -1305,8 +1305,6 @@ int inRange_f32(const uchar *src_data, size_t src_step, uchar *dst_data, static_cast(lower_bound), static_cast(upper_bound))); } -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP - int remap_s16(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, const int16_t *mapxy, @@ -1360,8 +1358,6 @@ int remap_s16point5(int src_type, const uchar *src_data, size_t src_step, return CV_HAL_ERROR_NOT_IMPLEMENTED; } -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP - int pyrdown(const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, int depth, int cn, int border_type) { diff --git a/adapters/opencv/kleidicv_hal.h b/adapters/opencv/kleidicv_hal.h index 35851694c46e1b06d53a8e20becc7abfd3279cc6..18cc07e2a0f980a6c6330f82f7efc4b5f2b16707 100644 --- a/adapters/opencv/kleidicv_hal.h +++ b/adapters/opencv/kleidicv_hal.h @@ -146,7 +146,6 @@ int inRange_f32(const uchar *src_data, size_t src_step, uchar *dst_data, size_t dst_step, int dst_depth, int width, int height, int cn, double lower_bound, double upper_bound); -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP int remap_s16(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width, int dst_height, const int16_t *mapxy, @@ -158,7 +157,6 @@ int remap_s16point5(int src_type, const uchar *src_data, size_t src_step, const int16_t *mapxy, size_t mapxy_step, const uint16_t *mapfrac, size_t mapfrac_step, int border_type, const double border_value[4]); -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #if KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE int warp_perspective(int src_type, const uchar *src_data, size_t src_step, @@ -385,7 +383,6 @@ static inline int kleidicv_canny_with_fallback( #define cv_hal_canny kleidicv_canny_with_fallback #endif // KLEIDICV_EXPERIMENTAL_FEATURE_CANNY -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP // remap // This condition can be removed if this HAL macro is defined in all supported // versions @@ -423,8 +420,6 @@ static inline int kleidicv_remap_s16point5_with_fallback( #define cv_hal_remap16s16u kleidicv_remap_s16point5_with_fallback #endif // cv_hal_remap16s16u -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP - // pyrdown static inline int kleidicv_pyrdown_with_fallback( const uchar *src_data, size_t src_step, int src_width, int src_height, diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index b62eb9685dfb0b6b2a754f5fe4545c2e59bd2ea9..bf178d1f57d1de8536db00d6fdae3e6699a19194 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -495,7 +495,6 @@ static void scharr_interleaved_s16_u8(benchmark::State& state) { } BENCHMARK(scharr_interleaved_s16_u8); -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP template static const ScalarType* get_random_mapxy() { auto generate_mapxy = [&]() { @@ -677,7 +676,6 @@ BENCH_REMAP_S16POINT5(remap_s16point5_u8_flip, remap_s16point5_u8, BENCH_REMAP_S16POINT5(remap_s16point5_u8_identity, remap_s16point5_u8, get_identity_mapxy, 1, KLEIDICV_BORDER_TYPE_REPLICATE, uint8_t); -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #if KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE // clang-format off diff --git a/doc/functionality.md b/doc/functionality.md index dab8381f98ddcc8ecc31c429c416aeaef7cf3a24..71f4860d8d6577a5c438652572846bf067d13c00 100644 --- a/doc/functionality.md +++ b/doc/functionality.md @@ -91,3 +91,9 @@ See `doc/opencv.md` for details of the functionality available in OpenCV. | 2x2 | x | x | | 4x4 | x | x | | 8x8 | | x | + +# Remap +| | u8 | u16 | +|--------------------------------------------|-----|-----| +| Remap int16 coordinates | x | | +| Remap int16+uint16 fixed-point coordinates | x | | diff --git a/doc/opencv.md b/doc/opencv.md index 59246297ab19f680f648077039322e8cf8e24f04..2c04dc4eccfa87123567433c3baa4d5a1fdbdf0f 100644 --- a/doc/opencv.md +++ b/doc/opencv.md @@ -205,6 +205,19 @@ Notes on parameters: * `src.depth()` - only supports `CV_8U` and `CV_32F` depths and 1 channel. * `src`, `lowerb` and `upperb` need to have the same type. +### [`cv::remap()`](https://docs.opencv.org/4.10.0/da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4) +Geometrically transforms the `src` image by taking the pixels specified by the coordinates from the `map` image. + +Notes on parameters: +* `src.step` - must be less than 2^16 +* `src.depth()` - only supports `CV_8U` depth and 1 channel. +* `borderMode` - only supports `BORDER_REPLICATE` +Supported map configurations: +* `map1` is 16SC2: channel #1 is x coordinate (column) and channel #2 is y (row) + * supported `interpolation`: `INTER_NEAREST` only +* `map1` is 16SC2 and `map2` is 16UC1: `map1` is as above, `map2` contains combined 5+5 bits of x (low) and y (high) fractions, i.e. x = x1 + x2 / 2^5 + * supported `interpolation`: `INTER_LINEAR` only + ### [`cv::pyrDown()`](https://docs.opencv.org/4.10.0/d4/d86/group__imgproc__filter.html#gaf9bba239dfca11654cb7f50f889fc2ff) Blurs and downsamples an image. diff --git a/kleidicv/CMakeLists.txt b/kleidicv/CMakeLists.txt index 41097c5e9157a4bd162b298effbd7b483987281f..1412394ab630c52de36d41f5bc97da05aa165d1c 100644 --- a/kleidicv/CMakeLists.txt +++ b/kleidicv/CMakeLists.txt @@ -50,7 +50,6 @@ option(KLEIDICV_ASSUME_128BIT_SVE2 "Internal - If turned ON 128-bit SVE2 vector option(KLEIDICV_PREFER_INTERLEAVING_LOAD_STORE "Internal - If turned ON interleaving loads and stores are preferred instead of continuous loads and stores" OFF) option(KLEIDICV_EXPERIMENTAL_FEATURE_CANNY "Internal - Enable experimental Canny algorithm" OFF) option(KLEIDICV_CANNY_ALGORITHM_CONFORM_OPENCV "Internal - If turned ON Canny algorithm creates bit exact result compared to OpenCV's original implementation" ON) -option(KLEIDICV_EXPERIMENTAL_FEATURE_REMAP "Internal - Enable experimental Remap algorithm" OFF) option(KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE "Internal - Enable experimental WarpPerspective algorithm" OFF) if(KLEIDICV_ENABLE_SME2 AND NOT KLEIDICV_LIMIT_SME2_TO_SELECTED_ALGORITHMS) diff --git a/kleidicv/include/kleidicv/config.h.in b/kleidicv/include/kleidicv/config.h.in index ac9f2991b51322f4c4519aecd32007550d144561..3e28a45356abb96058e09dcddc77c5f2734914b0 100644 --- a/kleidicv/include/kleidicv/config.h.in +++ b/kleidicv/include/kleidicv/config.h.in @@ -21,8 +21,6 @@ #cmakedefine01 KLEIDICV_CANNY_ALGORITHM_CONFORM_OPENCV -#cmakedefine01 KLEIDICV_EXPERIMENTAL_FEATURE_REMAP - #cmakedefine01 KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE // Set to '1' if compiling NEON code paths, otherwise it is set to '0'. diff --git a/kleidicv/include/kleidicv/kleidicv.h b/kleidicv/include/kleidicv/kleidicv.h index f41523adaf6d944dbe40bd9177b7a2486e67b8f8..bd4e38801a095cee0ab50ed0f1ed5d0f39b09266 100644 --- a/kleidicv/include/kleidicv/kleidicv.h +++ b/kleidicv/include/kleidicv/kleidicv.h @@ -1756,22 +1756,22 @@ KLEIDICV_API_DECLARATION(kleidicv_in_range_f32, const float *src, size_t width, size_t height, float lower_bound, float upper_bound); -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP /// Transforms the `src` image by taking the pixels specified by the coordinates /// from the `mapxy` image. /// -/// Width and height are the same for `mapxy` and for `dst`. `src` dimensions -/// may be different, but due to the 16-bit signed format, its width and height -/// must not be bigger than 32767. Coordinates outside of `src` dimensions are -/// considered border. In case of @ref KLEIDICV_BORDER_TYPE_REPLICATE, that -/// means that negative coordinates map to the first row/column (zero), and -/// those bigger than height/width - 1 map to the last row/column. +/// Width and height must be the same for `mapxy` and for `dst`. `src` +/// dimensions may be different, but due to the 16-bit signed format, elements +/// with any coordinates outside of [0, 2^16) cannot be used. Coordinates +/// outside of `src` dimensions are considered border. In case of @ref +/// KLEIDICV_BORDER_TYPE_REPLICATE, that means that negative coordinates map to +/// the first row/column (zero), and those bigger than height/width - 1 map to +/// the last row/column. /// /// @param src Pointer to the source data. Must be non-null. /// @param src_stride Distance in bytes from the start of one row to the /// start of the next row for the source data. Must /// not be less than `width * sizeof(type)`, except for -/// single-row images. +/// single-row images. Must be less than 2^16. /// @param src_width Number of elements in the source row. /// @param src_height Number of rows in the source data. /// @param dst Pointer to the destination data. Must be non-null. @@ -1779,7 +1779,8 @@ KLEIDICV_API_DECLARATION(kleidicv_in_range_f32, const float *src, /// start of the next row for the destination data. /// Must be a multiple of `sizeof(type)` and no less than /// `width * sizeof(type)`, except for single-row images. -/// @param dst_width Number of elements in the destination row. +/// @param dst_width Number of elements in the destination row. Must be at +/// least 8. /// @param dst_height Number of rows in the destination data. /// @param mapxy Pointer to the mapping data. Must be non-null. /// @param mapxy_stride Distance in bytes from the start of one row to the @@ -1813,7 +1814,6 @@ KLEIDICV_API_DECLARATION(kleidicv_remap_s16point5_u8, const uint8_t *src, kleidicv_border_type_t border_type, const uint8_t *border_value); #endif // DOXYGEN -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #ifndef DOXYGEN /// Internal - not part of the public API and its direct use is not supported. diff --git a/kleidicv/include/kleidicv/transform/remap.h b/kleidicv/include/kleidicv/transform/remap.h index 29182178ba98565066fe4a8af5b18cc332a2bf40..2332a8234a25e23092c96aab7746c3a2bf9a3cce 100644 --- a/kleidicv/include/kleidicv/transform/remap.h +++ b/kleidicv/include/kleidicv/transform/remap.h @@ -5,6 +5,7 @@ #ifndef KLEIDICV_REMAP_REMAP_H #define KLEIDICV_REMAP_REMAP_H +#include #include #include "kleidicv/ctypes.h" @@ -13,13 +14,13 @@ namespace kleidicv { template inline bool remap_s16_is_implemented( - size_t dst_width, kleidicv_border_type_t border_type, + size_t src_stride, size_t dst_width, kleidicv_border_type_t border_type, size_t channels) KLEIDICV_STREAMING_COMPATIBLE { if constexpr (std::is_same::value) { - return (dst_width >= 8 && - border_type == - kleidicv_border_type_t::KLEIDICV_BORDER_TYPE_REPLICATE && - channels == 1); + return ( + src_stride <= std::numeric_limits::max() && dst_width >= 8 && + border_type == kleidicv_border_type_t::KLEIDICV_BORDER_TYPE_REPLICATE && + channels == 1); } else { return false; } @@ -27,13 +28,13 @@ inline bool remap_s16_is_implemented( template inline bool remap_s16point5_is_implemented( - size_t dst_width, kleidicv_border_type_t border_type, + size_t src_stride, size_t dst_width, kleidicv_border_type_t border_type, size_t channels) KLEIDICV_STREAMING_COMPATIBLE { if constexpr (std::is_same::value) { - return (dst_width >= 8 && - border_type == - kleidicv_border_type_t::KLEIDICV_BORDER_TYPE_REPLICATE && - channels == 1); + return ( + src_stride <= std::numeric_limits::max() && dst_width >= 8 && + border_type == kleidicv_border_type_t::KLEIDICV_BORDER_TYPE_REPLICATE && + channels == 1); } else { return false; } diff --git a/kleidicv/src/transform/remap_api.cpp b/kleidicv/src/transform/remap_api.cpp index 28f7228fa4d752c36353f881d49eb33de199cf61..52dda620355845e6d5f6ee4fb8e636f2ed43ce4d 100644 --- a/kleidicv/src/transform/remap_api.cpp +++ b/kleidicv/src/transform/remap_api.cpp @@ -6,7 +6,6 @@ #include "kleidicv/kleidicv.h" #include "kleidicv/transform/remap.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP KLEIDICV_MULTIVERSION_C_API(kleidicv_remap_s16_u8, &kleidicv::neon::remap_s16, &kleidicv::sve2::remap_s16, nullptr); @@ -15,4 +14,3 @@ KLEIDICV_MULTIVERSION_C_API( kleidicv_remap_s16point5_u8, &kleidicv::neon::remap_s16point5, &kleidicv::sve2::remap_s16point5, KLEIDICV_SME2_IMPL_IF(&kleidicv::sme2::remap_s16point5)); -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP diff --git a/kleidicv/src/transform/remap_neon.cpp b/kleidicv/src/transform/remap_neon.cpp index 9d47bd7b7a7fa3c1736b48fa226fb6a8cd0be6d8..71638894382e76e15d8222eeb233de1a7e926205 100644 --- a/kleidicv/src/transform/remap_neon.cpp +++ b/kleidicv/src/transform/remap_neon.cpp @@ -8,7 +8,6 @@ #include "kleidicv/neon.h" #include "kleidicv/transform/remap.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP namespace kleidicv::neon { template @@ -24,7 +23,7 @@ class RemapS16 { RemapS16(Rows src_rows, size_t src_width, size_t src_height) : src_rows_{src_rows}, - v_src_stride_{vdupq_n_s16(static_cast(src_rows_.stride()))}, + v_src_stride_{vdupq_n_u16(static_cast(src_rows_.stride()))}, v_xmax_{vdupq_n_s16(static_cast(src_width - 1))}, v_ymax_{vdupq_n_s16(static_cast(src_height - 1))} {} @@ -67,7 +66,7 @@ class RemapS16 { private: Rows src_rows_; - int16x8_t v_src_stride_; + uint16x8_t v_src_stride_; int16x8_t v_xmax_; int16x8_t v_ymax_; }; // end of class RemapS16 @@ -85,7 +84,8 @@ kleidicv_error_t remap_s16(const T *src, size_t src_stride, size_t src_width, CHECK_IMAGE_SIZE(src_width, src_height); CHECK_IMAGE_SIZE(dst_width, dst_height); - if (!remap_s16_is_implemented(dst_width, border_type, channels)) { + if (!remap_s16_is_implemented(src_stride, dst_width, border_type, + channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } @@ -114,7 +114,7 @@ class RemapS16Point5 { RemapS16Point5(Rows src_rows, size_t src_width, size_t src_height) : src_rows_{src_rows}, - v_src_stride_{vdupq_n_s16(static_cast(src_rows_.stride()))}, + v_src_stride_{vdup_n_u16(static_cast(src_rows_.stride()))}, v_xmax_{vdupq_n_s16(static_cast(src_width - 1))}, v_ymax_{vdupq_n_s16(static_cast(src_height - 1))} {} @@ -175,7 +175,7 @@ class RemapS16Point5 { uint16x4_t nyfrac) { // Calculate offsets from coordinates (y * stride + x) // a: top left, b: top right, c: bottom left, d: bottom right - uint32x4_t offset = vmlal_u16(x0, y0, vget_low_u16(v_src_stride_)); + uint32x4_t offset = vmlal_u16(x0, y0, v_src_stride_); uint64_t acc = static_cast(src_rows_[vgetq_lane_u32(offset, 0)]) | (static_cast(src_rows_[vgetq_lane_u32(offset, 1)]) << 16) | @@ -183,7 +183,7 @@ class RemapS16Point5 { (static_cast(src_rows_[vgetq_lane_u32(offset, 3)]) << 48); uint16x4_t a = vreinterpret_u16_u64(vset_lane_u64(acc, vdup_n_u64(0), 0)); - offset = vmlal_u16(x1, y0, vget_low_u16(v_src_stride_)); + offset = vmlal_u16(x1, y0, v_src_stride_); acc = static_cast(src_rows_[vgetq_lane_u32(offset, 0)]) | (static_cast(src_rows_[vgetq_lane_u32(offset, 1)]) << 16) | @@ -193,7 +193,7 @@ class RemapS16Point5 { uint16x4_t line0 = vmla_u16(vmul_u16(xfrac, b), nxfrac, a); - offset = vmlal_u16(x0, y1, vget_low_u16(v_src_stride_)); + offset = vmlal_u16(x0, y1, v_src_stride_); acc = static_cast(src_rows_[vgetq_lane_u32(offset, 0)]) | (static_cast(src_rows_[vgetq_lane_u32(offset, 1)]) << 16) | @@ -204,7 +204,7 @@ class RemapS16Point5 { uint32x4_t line0_lerpd = vmlal_u16( vdupq_n_u32(REMAP16POINT5_FRAC_MAX_SQUARE / 2), line0, nyfrac); - offset = vmlal_u16(x1, y1, vget_low_u16(v_src_stride_)); + offset = vmlal_u16(x1, y1, v_src_stride_); acc = static_cast(src_rows_[vgetq_lane_u32(offset, 0)]) | (static_cast(src_rows_[vgetq_lane_u32(offset, 1)]) << 16) | @@ -218,7 +218,7 @@ class RemapS16Point5 { } Rows src_rows_; - int16x8_t v_src_stride_; + uint16x4_t v_src_stride_; int16x8_t v_xmax_; int16x8_t v_ymax_; }; // end of class RemapS16Point5 @@ -238,7 +238,8 @@ kleidicv_error_t remap_s16point5( CHECK_IMAGE_SIZE(src_width, src_height); CHECK_IMAGE_SIZE(dst_width, dst_height); - if (!remap_s16point5_is_implemented(dst_width, border_type, channels)) { + if (!remap_s16point5_is_implemented(src_stride, dst_width, border_type, + channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } @@ -272,4 +273,3 @@ KLEIDICV_INSTANTIATE_TEMPLATE_REMAP_S16(uint8_t); KLEIDICV_INSTANTIATE_TEMPLATE_REMAP_S16Point5(uint8_t); } // namespace kleidicv::neon -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP diff --git a/kleidicv/src/transform/remap_sc.h b/kleidicv/src/transform/remap_sc.h index 3c204ac34686c9201853f256db87fbe3331c7c9f..c0b965ed53c33a2ed3705c7c2f78b0d8656ee4b5 100644 --- a/kleidicv/src/transform/remap_sc.h +++ b/kleidicv/src/transform/remap_sc.h @@ -15,7 +15,6 @@ #include "kleidicv/sve2.h" #include "kleidicv/transform/remap.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP namespace KLEIDICV_TARGET_NAMESPACE { #if !KLEIDICV_TARGET_SME2 @@ -125,7 +124,8 @@ kleidicv_error_t remap_s16_sc(const T* src, size_t src_stride, size_t src_width, CHECK_IMAGE_SIZE(src_width, src_height); CHECK_IMAGE_SIZE(dst_width, dst_height); - if (!remap_s16_is_implemented(dst_width, border_type, channels)) { + if (!remap_s16_is_implemented(src_stride, dst_width, border_type, + channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } @@ -403,7 +403,8 @@ kleidicv_error_t remap_s16point5_sc( CHECK_IMAGE_SIZE(src_width, src_height); CHECK_IMAGE_SIZE(dst_width, dst_height); - if (!remap_s16point5_is_implemented(dst_width, border_type, channels)) { + if (!remap_s16point5_is_implemented(src_stride, dst_width, border_type, + channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } @@ -427,6 +428,5 @@ kleidicv_error_t remap_s16point5_sc( } } // namespace KLEIDICV_TARGET_NAMESPACE -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #endif // KLEIDICV_REMAP_SC_H diff --git a/kleidicv/src/transform/remap_sme2.cpp b/kleidicv/src/transform/remap_sme2.cpp index 03280dc760f745e0dd08d10e33ef3a89090878fc..426ccda3f5f3ce4971b5c6ce986967184233a65a 100644 --- a/kleidicv/src/transform/remap_sme2.cpp +++ b/kleidicv/src/transform/remap_sme2.cpp @@ -4,7 +4,6 @@ #include "remap_sc.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP namespace kleidicv::sme2 { template @@ -33,4 +32,3 @@ kleidicv_error_t remap_s16point5(const T *src, size_t src_stride, KLEIDICV_INSTANTIATE_TEMPLATE_REMAP_S16Point5(uint8_t); } // namespace kleidicv::sme2 -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP diff --git a/kleidicv/src/transform/remap_sve2.cpp b/kleidicv/src/transform/remap_sve2.cpp index 13276480f05273c270ae015b70d54994d0a89d44..f71f2fb93c588a5f3a564f1516a4174d306f221c 100644 --- a/kleidicv/src/transform/remap_sve2.cpp +++ b/kleidicv/src/transform/remap_sve2.cpp @@ -4,7 +4,6 @@ #include "remap_sc.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP namespace kleidicv::sve2 { template @@ -54,4 +53,3 @@ KLEIDICV_INSTANTIATE_TEMPLATE_REMAP_S16(uint8_t); KLEIDICV_INSTANTIATE_TEMPLATE_REMAP_S16Point5(uint8_t); } // namespace kleidicv::sve2 -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP diff --git a/kleidicv_thread/src/kleidicv_thread.cpp b/kleidicv_thread/src/kleidicv_thread.cpp index 5368e978ab37ca1a2564fe7e30006f169b8e5d56..b6fcecc6b4d0a78ba70983890397d78569688984 100644 --- a/kleidicv_thread/src/kleidicv_thread.cpp +++ b/kleidicv_thread/src/kleidicv_thread.cpp @@ -655,15 +655,14 @@ kleidicv_error_t kleidicv_thread_resize_linear_f32( return parallel_batches(callback, mt, std::max(1, src_height - 1)); } -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP kleidicv_error_t kleidicv_thread_remap_s16_u8( const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, uint8_t *dst, size_t dst_stride, size_t dst_width, size_t dst_height, size_t channels, const int16_t *mapxy, size_t mapxy_stride, kleidicv_border_type_t border_type, const uint8_t *border_value, kleidicv_thread_multithreading mt) { - if (!kleidicv::remap_s16_is_implemented(dst_width, border_type, - channels)) { + if (!kleidicv::remap_s16_is_implemented(src_stride, dst_width, + border_type, channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } auto callback = [=](unsigned begin, unsigned end) { @@ -683,8 +682,8 @@ kleidicv_error_t kleidicv_thread_remap_s16point5_u8( const uint16_t *mapfrac, size_t mapfrac_stride, kleidicv_border_type_t border_type, const uint8_t *border_value, kleidicv_thread_multithreading mt) { - if (!kleidicv::remap_s16point5_is_implemented(dst_width, border_type, - channels)) { + if (!kleidicv::remap_s16point5_is_implemented( + src_stride, dst_width, border_type, channels)) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } auto callback = [=](unsigned begin, unsigned end) { @@ -697,7 +696,6 @@ kleidicv_error_t kleidicv_thread_remap_s16point5_u8( }; return parallel_batches(callback, mt, dst_height); } -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #if KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE kleidicv_error_t kleidicv_thread_warp_perspective_u8( diff --git a/test/api/test_remap.cpp b/test/api/test_remap.cpp index a5a731e71a4f1acd37436408a6610bf845ee1e9f..e386e37fb601670830224acedcd6713dc03855fd 100644 --- a/test/api/test_remap.cpp +++ b/test/api/test_remap.cpp @@ -9,8 +9,6 @@ #include "framework/utils.h" #include "kleidicv/kleidicv.h" -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP - template class RemapS16 : public testing::Test { public: @@ -158,6 +156,14 @@ TYPED_TEST(RemapS16, BlendPadding) { TestFixture::test_blend(src_w, src_h, dst_w, dst_h, 1, 13); } +TYPED_TEST(RemapS16, BlendBigStride) { + size_t src_w = 3 * test::Options::vector_lanes() - 1; + size_t src_h = 16; + size_t dst_w = src_w; + size_t dst_h = src_h; + TestFixture::test_blend(src_w, src_h, dst_w, dst_h, 1, (1 << 16) - src_w - 1); +} + TYPED_TEST(RemapS16, CornerCases) { size_t src_w = 3 * test::Options::vector_lanes() - 1; size_t src_h = 4; @@ -215,6 +221,17 @@ TYPED_TEST(RemapS16, InvalidImageSize) { KLEIDICV_BORDER_TYPE_REPLICATE, nullptr)); } +TYPED_TEST(RemapS16, UnsupportedBigStride) { + const TypeParam src[1] = {}; + TypeParam dst[8]; + int16_t mapxy[16] = {}; + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + kleidicv_remap_s16_u8(src, 2 << 16, 1, 1, dst, 2 << 16, 8, 1, 2, mapxy, 4, + KLEIDICV_BORDER_TYPE_REPLICATE, nullptr)); +} + TYPED_TEST(RemapS16, UnsupportedTwoChannels) { const TypeParam src[1] = {}; TypeParam dst[8]; @@ -334,6 +351,7 @@ class RemapS16Point5 : public testing::Test { *mapfrac.at(row, column) = static_cast((counter * 3) % FRAC_MAX) | (static_cast((counter * 5) % FRAC_MAX) << FRAC_BITS); + ++counter; } } execute_test(mapxy, mapfrac, src_w, src_h, dst_w, dst_h, channels, padding); @@ -445,6 +463,14 @@ TYPED_TEST(RemapS16Point5, OutsideRandomPadding) { TestFixture::test_outside_random(src_w, src_h, dst_w, dst_h, 1, 13); } +TYPED_TEST(RemapS16Point5, BlendBigStride) { + size_t src_w = 3 * test::Options::vector_lanes() - 1; + size_t src_h = 16; + size_t dst_w = src_w; + size_t dst_h = src_h; + TestFixture::test_blend(src_w, src_h, dst_w, dst_h, 1, (1 << 16) - src_w - 1); +} + TYPED_TEST(RemapS16Point5, CornerCases) { size_t src_w = 3 * test::Options::vector_lanes() - 1; size_t src_h = 4; @@ -543,4 +569,3 @@ TYPED_TEST(RemapS16Point5, UnsupportedTooSmallImage) { src, 1, 1, 1, dst, 8, 7, 1, 1, mapxy, 4, mapfrac, 2, KLEIDICV_BORDER_TYPE_REPLICATE, nullptr)); } -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP diff --git a/test/api/test_thread.cpp b/test/api/test_thread.cpp index e8c319ea0cb1c7f5533870823d0e425a0df170b4..e36bfbfe58c3e7027101c281190d514514754854 100644 --- a/test/api/test_thread.cpp +++ b/test/api/test_thread.cpp @@ -594,7 +594,6 @@ TEST(ThreadSeparableFilter2D, NotImplemented) { kleidicv_thread_separable_filter_2d_u16); } -#if KLEIDICV_EXPERIMENTAL_FEATURE_REMAP TEST_P(Thread, remap_s16_u8_border_replicate) { check_remap_s16(kleidicv_remap_s16_u8, kleidicv_thread_remap_s16_u8, 1, KLEIDICV_BORDER_TYPE_REPLICATE, nullptr); @@ -625,7 +624,6 @@ TEST_P(Thread, remap_s16point5_u8_not_implemented) { kleidicv_thread_remap_s16point5_u8, 1, KLEIDICV_BORDER_TYPE_CONSTANT, border_value); } -#endif // KLEIDICV_EXPERIMENTAL_FEATURE_REMAP #if KLEIDICV_EXPERIMENTAL_FEATURE_WARP_PERSPECTIVE TEST_P(Thread, warp_perspective_u8_border_replicate) {