diff --git a/hal/riscv-rvv/src/core/flip.cpp b/hal/riscv-rvv/src/core/flip.cpp index 0af8458ccf..8a39e98bd1 100644 --- a/hal/riscv-rvv/src/core/flip.cpp +++ b/hal/riscv-rvv/src/core/flip.cpp @@ -46,10 +46,25 @@ CV_HAL_RVV_FLIP_C1(64UC1, uint64_t, RVV_U64M8) #define CV_HAL_RVV_FLIP_INPLACE_C1(name, _Tps, RVV) \ inline void flip_inplace_##name(uchar* data, size_t step, int width, int height, int flip_mode) { \ auto new_height = (flip_mode < 0 ? height / 2 : height); \ - auto new_width = width / 2; \ - for (int h = 0; h < new_height; h++) { \ + auto new_width = (flip_mode < 0 ? width : width / 2); \ + int h; \ + for (h = 0; h < new_height; h++) { \ _Tps* row_begin = (_Tps*)(data + step * h); \ - _Tps* row_end = (_Tps*)(data + step * (flip_mode < 0 ? (new_height - h) : (h + 1))); \ + _Tps* row_end = (_Tps*)(data + step * (flip_mode < 0 ? (height - h) : (h + 1))); \ + int vl; \ + for (int w = 0; w < new_width; w += vl) { \ + vl = RVV::setvl(new_width - w); \ + RVV::VecType indices = __riscv_vrsub(RVV::vid(vl), vl - 1, vl); \ + auto v_left = RVV::vload(row_begin + w, vl); \ + auto v_right = RVV::vload(row_end - w - vl, vl); \ + RVV::vstore(row_begin + w, __riscv_vrgather(v_right, indices, vl), vl); \ + RVV::vstore(row_end - w - vl, __riscv_vrgather(v_left, indices, vl), vl); \ + } \ + } \ + if (flip_mode == -1 && new_height * 2 != height) { \ + _Tps* row_begin = (_Tps*)(data + step * h); \ + _Tps* row_end = (_Tps*)(data + step * (h + 1)); \ + new_width /= 2; \ int vl; \ for (int w = 0; w < new_width; w += vl) { \ vl = RVV::setvl(new_width - w); \ @@ -117,10 +132,27 @@ CV_HAL_RVV_FLIP_C3(64UC3, uint64_t, RVV_C3_U64M2) #define CV_HAL_RVV_FLIP_INPLACE_C3(name, _Tps, RVV) \ inline void flip_inplace_##name(uchar* data, size_t step, int width, int height, int flip_mode) { \ auto new_height = (flip_mode < 0 ? height / 2 : height); \ - auto new_width = width / 2; \ - for (int h = 0; h < new_height; h++) { \ + auto new_width = (flip_mode < 0 ? width : width / 2); \ + int h; \ + for (h = 0; h < new_height; h++) { \ _Tps* row_begin = (_Tps*)(data + step * h); \ - _Tps* row_end = (_Tps*)(data + step * (flip_mode < 0 ? (new_height - h) : (h + 1))); \ + _Tps* row_end = (_Tps*)(data + step * (flip_mode < 0 ? (height - h) : (h + 1))); \ + int vl; \ + for (int w = 0; w < new_width; w += vl) { \ + vl = RVV::setvl(new_width - w); \ + RVV::VecType indices = __riscv_vrsub(RVV::vid(vl), vl - 1, vl); \ + auto v_left = RVV::vload3(row_begin + 3 * w, vl); \ + auto flipped_left = RVV::vflip3(v_left, indices, vl); \ + auto v_right = RVV::vload3(row_end - 3 * (w + vl), vl); \ + auto flipped_right = RVV::vflip3(v_right, indices, vl); \ + RVV::vstore3(row_begin + 3 * w, flipped_right, vl); \ + RVV::vstore3(row_end - 3 * (w + vl), flipped_left, vl); \ + } \ + } \ + if (flip_mode == -1 && new_height * 2 != height) { \ + _Tps* row_begin = (_Tps*)(data + step * h); \ + _Tps* row_end = (_Tps*)(data + step * (h + 1)); \ + new_width /= 2; \ int vl; \ for (int w = 0; w < new_width; w += vl) { \ vl = RVV::setvl(new_width - w); \ @@ -322,10 +354,8 @@ int flip(int src_type, const uchar* src_data, size_t src_step, int src_width, in if (src_width < 0 || src_height < 0 || esz > 32) return CV_HAL_ERROR_NOT_IMPLEMENTED; - // BUG: https://github.com/opencv/opencv/issues/28124 if (src_data == dst_data) { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - //return flip_inplace(esz, dst_data, dst_step, src_width, src_height, flip_mode); + return flip_inplace(esz, dst_data, dst_step, src_width, src_height, flip_mode); } if (flip_mode == 0) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index d2ce1f03fd..3a7a54a050 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -878,6 +878,14 @@ static void flip(const Mat& src, Mat& dst, int flipcode) } } +static void flip_inplace(Mat& dst, int flipcode) +{ + Mat m; + m.create(dst.size(), dst.type()); + reference::flip(dst, m, flipcode); + memcpy(dst.ptr(), m.ptr(), dst.total() * dst.elemSize()); +} + static void rotate(const Mat& src, Mat& dst, int rotateMode) { Mat tmp; @@ -944,6 +952,36 @@ struct FlipOp : public BaseElemWiseOp int flipcode; }; +struct FlipInplaceOp : public BaseElemWiseOp +{ + FlipInplaceOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { flipcode = 0; } + void getRandomSize(RNG& rng, vector& size) + { + cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size); + } + void op(const vector& src, Mat& dst, const Mat&) + { + dst.create(src[0].size(), src[0].type()); + memcpy(dst.ptr(), src[0].ptr(), src[0].total() * src[0].elemSize()); + cv::flip(dst, dst, flipcode); + } + void refop(const vector& src, Mat& dst, const Mat&) + { + dst.create(src[0].size(), src[0].type()); + memcpy(dst.ptr(), src[0].ptr(), src[0].total() * src[0].elemSize()); + reference::flip_inplace(dst, flipcode); + } + void generateScalars(int, RNG& rng) + { + flipcode = rng.uniform(0, 3) - 1; + } + double getMaxErr(int) + { + return 0; + } + int flipcode; +}; + struct RotateOp : public BaseElemWiseOp { RotateOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) { rotatecode = 0; } @@ -1622,6 +1660,7 @@ INSTANTIATE_TEST_CASE_P(Core_InRangeS, ElemWiseTest, ::testing::Values(ElemWiseO INSTANTIATE_TEST_CASE_P(Core_InRange, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new InRangeOp))); INSTANTIATE_TEST_CASE_P(Core_Flip, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new FlipOp))); +INSTANTIATE_TEST_CASE_P(Core_FlipInplace, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new FlipInplaceOp))); INSTANTIATE_TEST_CASE_P(Core_Rotate, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new RotateOp))); INSTANTIATE_TEST_CASE_P(Core_Transpose, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new TransposeOp))); INSTANTIATE_TEST_CASE_P(Core_SetIdentity, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new SetIdentityOp)));