1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #28180 from fengyuentau:rvv_hal/flip

rvv_hal: fix flip inplace #28180

Fixes https://github.com/opencv/opencv/issues/28124

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Yuantao Feng
2025-12-15 15:51:48 +08:00
committed by GitHub
parent f5d6fe5392
commit 912d27a7b7
2 changed files with 78 additions and 9 deletions
+39 -9
View File
@@ -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)
+39
View File
@@ -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<uchar>(), m.ptr<uchar>(), 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<int>& size)
{
cvtest::randomSize(rng, 2, 2, ARITHM_MAX_SIZE_LOG, size);
}
void op(const vector<Mat>& src, Mat& dst, const Mat&)
{
dst.create(src[0].size(), src[0].type());
memcpy(dst.ptr<uchar>(), src[0].ptr<uchar>(), src[0].total() * src[0].elemSize());
cv::flip(dst, dst, flipcode);
}
void refop(const vector<Mat>& src, Mat& dst, const Mat&)
{
dst.create(src[0].size(), src[0].type());
memcpy(dst.ptr<uchar>(), src[0].ptr<uchar>(), 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)));