From f1a775825ff4b1d0ef23cf4cc1aa5235e9cc3e02 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Wed, 18 Dec 2024 04:47:28 +0800 Subject: [PATCH 1/6] Use universal intrinsics in bayer2Gray --- modules/imgproc/src/demosaicing.cpp | 105 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 24baf16362..1a06727e4d 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -123,12 +123,12 @@ public: } }; -#if CV_SIMD128 +#if CV_SIMD || CV_SIMD_SCALABLE class SIMDBayerInterpolator_8u { public: - int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst, - int width, int bcoeff, int gcoeff, int rcoeff) const + static int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst, + int width, int bcoeff, int gcoeff, int rcoeff) { #if CV_NEON uint16x8_t masklo = vdupq_n_u16(255); @@ -177,96 +177,97 @@ public: vst1_u8(dst + 8, p.val[1]); } #else - v_uint16x8 v255 = v_setall_u16(255); - v_int16x8 v_descale = v_setall_s16(static_cast(1 << 14)); - v_int16x8 dummy; - v_int16x8 cxrb; - v_int16x8 cxg2; - v_zip(v_setall_s16(static_cast(rcoeff)), - v_setall_s16(static_cast(bcoeff)), + v_uint16 v255 = vx_setall_u16(255); + v_int16 v_descale = vx_setall_s16(static_cast(1 << 14)); + v_int16 dummy; + v_int16 cxrb; + v_int16 cxg2; + v_zip(vx_setall_s16(static_cast(rcoeff)), + vx_setall_s16(static_cast(bcoeff)), cxrb, dummy); - v_zip(v_setall_s16(static_cast(gcoeff)), - v_setall_s16(static_cast(2)), + v_zip(vx_setall_s16(static_cast(gcoeff)), + vx_setall_s16(static_cast(2)), cxg2, dummy); const uchar* bayer_end = bayer + width; - for (; bayer < bayer_end - 14; bayer += 14, dst += 14) + const int step = VTraits::vlanes() - 2; + for (; bayer < bayer_end - step; bayer += step, dst += step) { - v_uint16x8 first_line = v_reinterpret_as_u16(v_load(bayer)); - v_uint16x8 second_line = v_reinterpret_as_u16(v_load(bayer + bayer_step)); - v_uint16x8 third_line = v_reinterpret_as_u16(v_load(bayer + bayer_step * 2)); + v_uint16 first_line = v_reinterpret_as_u16(vx_load(bayer)); + v_uint16 second_line = v_reinterpret_as_u16(vx_load(bayer + bayer_step)); + v_uint16 third_line = v_reinterpret_as_u16(vx_load(bayer + bayer_step * 2)); // bayer[0] - v_uint16x8 first_line0 = v_and(first_line, v255); + v_uint16 first_line0 = v_and(first_line, v255); // bayer[bayer_step*2] - v_uint16x8 third_line0 = v_and(third_line, v255); + v_uint16 third_line0 = v_and(third_line, v255); // bayer[0] + bayer[bayer_step*2] - v_uint16x8 first_third_line0 = v_add(first_line0, third_line0); + v_uint16 first_third_line0 = v_add(first_line0, third_line0); // bayer[2] + bayer[bayer_step*2+2] - v_uint16x8 first_third_line2 = v_rotate_right<1>(first_third_line0); + v_uint16 first_third_line2 = v_rotate_right<1>(first_third_line0); // bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2] - v_int16x8 r0 = v_reinterpret_as_s16(v_add(first_third_line0, first_third_line2)); + v_int16 r0 = v_reinterpret_as_s16(v_add(first_third_line0, first_third_line2)); // (bayer[2] + bayer[bayer_step*2+2]) * 2 - v_int16x8 r1 = v_reinterpret_as_s16(v_shl<1>(first_third_line2)); + v_int16 r1 = v_reinterpret_as_s16(v_shl<1>(first_third_line2)); // bayer[bayer_step+1] - v_uint16x8 second_line1 = v_shr<8>(second_line); + v_uint16 second_line1 = v_shr<8>(second_line); // bayer[bayer_step+1] * 4 - v_int16x8 b0 = v_reinterpret_as_s16(v_shl<2>(second_line1)); + v_int16 b0 = v_reinterpret_as_s16(v_shl<2>(second_line1)); // bayer[bayer_step+3] - v_uint16x8 second_line3 = v_rotate_right<1>(second_line1); + v_uint16 second_line3 = v_rotate_right<1>(second_line1); // bayer[bayer_step+1] + bayer[bayer_step+3] - v_uint16x8 second_line13 = v_add(second_line1, second_line3); + v_uint16 second_line13 = v_add(second_line1, second_line3); // (bayer[bayer_step+1] + bayer[bayer_step+3]) * 2 - v_int16x8 b1 = v_reinterpret_as_s16(v_shl(second_line13, 1)); + v_int16 b1 = v_reinterpret_as_s16(v_shl(second_line13, 1)); // bayer[1] - v_uint16x8 first_line1 = v_shr<8>(first_line); + v_uint16 first_line1 = v_shr<8>(first_line); // bayer[bayer_step] - v_uint16x8 second_line0 = v_and(second_line, v255); + v_uint16 second_line0 = v_and(second_line, v255); // bayer[bayer_step+2] - v_uint16x8 second_line2 = v_rotate_right<1>(second_line0); + v_uint16 second_line2 = v_rotate_right<1>(second_line0); // bayer[bayer_step] + bayer[bayer_step+2] - v_uint16x8 second_line02 = v_add(second_line0, second_line2); + v_uint16 second_line02 = v_add(second_line0, second_line2); // bayer[bayer_step*2+1] - v_uint16x8 third_line1 = v_shr<8>(third_line); + v_uint16 third_line1 = v_shr<8>(third_line); // bayer[1] + bayer[bayer_step*2+1] - v_uint16x8 first_third_line1 = v_add(first_line1, third_line1); + v_uint16 first_third_line1 = v_add(first_line1, third_line1); // bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1] - v_int16x8 g0 = v_reinterpret_as_s16(v_add(first_third_line1, second_line02)); + v_int16 g0 = v_reinterpret_as_s16(v_add(first_third_line1, second_line02)); // bayer[bayer_step+2] * 4 - v_int16x8 g1 = v_reinterpret_as_s16(v_shl<2>(second_line2)); + v_int16 g1 = v_reinterpret_as_s16(v_shl<2>(second_line2)); - v_int16x8 rb0; - v_int16x8 rb1; - v_int16x8 rb2; - v_int16x8 rb3; + v_int16 rb0; + v_int16 rb1; + v_int16 rb2; + v_int16 rb3; v_zip(r0, b0, rb0, rb1); v_zip(r1, b1, rb2, rb3); - v_int16x8 gd0; - v_int16x8 gd1; - v_int16x8 gd2; - v_int16x8 gd3; + v_int16 gd0; + v_int16 gd1; + v_int16 gd2; + v_int16 gd3; v_zip(g0, v_descale, gd0, gd1); v_zip(g1, v_descale, gd2, gd3); - v_int32x4 gray_even0 = v_shr<16>(v_add(v_dotprod(rb0, cxrb), v_dotprod(gd0, cxg2))); - v_int32x4 gray_even1 = v_shr<16>(v_add(v_dotprod(rb1, cxrb), v_dotprod(gd1, cxg2))); - v_int32x4 gray_odd0 = v_shr<16>(v_add(v_dotprod(rb2, cxrb), v_dotprod(gd2, cxg2))); - v_int32x4 gray_odd1 = v_shr<16>(v_add(v_dotprod(rb3, cxrb), v_dotprod(gd3, cxg2))); + v_int32 gray_even0 = v_shr<16>(v_add(v_dotprod(rb0, cxrb), v_dotprod(gd0, cxg2))); + v_int32 gray_even1 = v_shr<16>(v_add(v_dotprod(rb1, cxrb), v_dotprod(gd1, cxg2))); + v_int32 gray_odd0 = v_shr<16>(v_add(v_dotprod(rb2, cxrb), v_dotprod(gd2, cxg2))); + v_int32 gray_odd1 = v_shr<16>(v_add(v_dotprod(rb3, cxrb), v_dotprod(gd3, cxg2))); - v_int16x8 gray_even = v_pack(gray_even0, gray_even1); - v_int16x8 gray_odd = v_pack(gray_odd0, gray_odd1); + v_int16 gray_even = v_pack(gray_even0, gray_even1); + v_int16 gray_odd = v_pack(gray_odd0, gray_odd1); - v_int16x8 gray_d0; - v_int16x8 gray_d1; + v_int16 gray_d0; + v_int16 gray_d1; v_zip(gray_even, gray_odd, gray_d0, gray_d1); - v_uint8x16 gray = v_pack(v_reinterpret_as_u16(gray_d0), v_reinterpret_as_u16(gray_d1)); + v_uint8 gray = v_pack(v_reinterpret_as_u16(gray_d0), v_reinterpret_as_u16(gray_d1)); v_store(dst, gray); } From d6dc22d03c1d173f1d5867853b691e9c9dc86709 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Mon, 3 Feb 2025 00:09:36 +0800 Subject: [PATCH 2/6] Fix build on RISC-V --- modules/imgproc/src/demosaicing.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 1a06727e4d..5512ac36b0 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -123,13 +123,13 @@ public: } }; -#if CV_SIMD || CV_SIMD_SCALABLE class SIMDBayerInterpolator_8u { public: static int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst, int width, int bcoeff, int gcoeff, int rcoeff) { +#if CV_SIMD || CV_SIMD_SCALABLE #if CV_NEON uint16x8_t masklo = vdupq_n_u16(255); const uchar* bayer_end = bayer + width; @@ -274,6 +274,9 @@ public: #endif return static_cast(bayer - (bayer_end - width)); +#else + return 0; +#endif } int bayer2RGB(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const @@ -283,7 +286,7 @@ public: G R G R | G R G R | G R G R | G R G R B G B G | B G B G | B G B G | B G B G */ - +#if CV_SIMD128 #if CV_NEON uint16x8_t masklo = vdupq_n_u16(255); uint8x16x3_t pix; @@ -406,6 +409,9 @@ public: #endif return (int)(bayer - (bayer_end - width)); +#else + return 0; +#endif } int bayer2RGBA(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue, const uchar alpha) const @@ -416,6 +422,7 @@ public: B G B G | B G B G | B G B G | B G B G */ +#if CV_SIMD128 #if CV_NEON uint16x8_t masklo = vdupq_n_u16(255); uint8x16x4_t pix; @@ -537,6 +544,9 @@ public: #endif return (int)(bayer - (bayer_end - width)); +#else + return 0; +#endif } int bayer2RGB_EA(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const @@ -556,6 +566,7 @@ public: B G B G | B G B G | B G B G | B G B G */ +#if CV_SIMD128 v_uint16x8 r0 = v_reinterpret_as_u16(v_load(bayer)); v_uint16x8 r1 = v_reinterpret_as_u16(v_load(bayer+bayer_step)); v_uint16x8 r2 = v_reinterpret_as_u16(v_load(bayer+bayer_step*2)); @@ -643,12 +654,11 @@ public: } return int(bayer - (bayer_end - width)); +#else + return 0; +#endif } }; -#else -typedef SIMDBayerStubInterpolator_ SIMDBayerInterpolator_8u; -#endif - template class Bayer2Gray_Invoker : From 0fa61de22ad6c06414f712ac3e4efe31ea08e162 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Mon, 3 Feb 2025 14:19:52 +0800 Subject: [PATCH 3/6] Fix bayer2RGB_EA macro --- modules/imgproc/src/demosaicing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 5512ac36b0..4cb338c095 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -551,6 +551,7 @@ public: int bayer2RGB_EA(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const { +#if CV_SIMD128 const uchar* bayer_end = bayer + width; v_uint16x8 masklow = v_setall_u16(0x00ff); v_uint16x8 delta1 = v_setall_u16(1), delta2 = v_setall_u16(2); @@ -566,7 +567,6 @@ public: B G B G | B G B G | B G B G | B G B G */ -#if CV_SIMD128 v_uint16x8 r0 = v_reinterpret_as_u16(v_load(bayer)); v_uint16x8 r1 = v_reinterpret_as_u16(v_load(bayer+bayer_step)); v_uint16x8 r2 = v_reinterpret_as_u16(v_load(bayer+bayer_step*2)); From fbffaa5276091b043e97aed912bf75dcaca25196 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 7 Mar 2025 11:56:26 +0300 Subject: [PATCH 4/6] Warning fix. --- modules/imgproc/src/demosaicing.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 4cb338c095..84ac903fe0 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -275,6 +275,8 @@ public: return static_cast(bayer - (bayer_end - width)); #else + CV_UNUSED(bayer); CV_UNUSED(bayer_step); CV_UNUSED(dst); + CV_UNUSED(width); CV_UNUSED(bcoeff); CV_UNUSED(gcoeff); CV_UNUSED(rcoeff); return 0; #endif } From 648424eaf213cc3da4b14ee309d961012ffca080 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 7 Mar 2025 15:33:54 +0300 Subject: [PATCH 5/6] Code review fixes. --- modules/imgproc/src/demosaicing.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 84ac903fe0..68816a6fd6 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -412,6 +412,7 @@ public: return (int)(bayer - (bayer_end - width)); #else + CV_UNUSED(bayer); CV_UNUSED(bayer_step); CV_UNUSED(dst); CV_UNUSED(width); CV_UNUSED(blue); return 0; #endif } @@ -547,6 +548,8 @@ public: return (int)(bayer - (bayer_end - width)); #else + CV_UNUSED(bayer); CV_UNUSED(bayer_step); CV_UNUSED(dst); + CV_UNUSED(width); CV_UNUSED(blue); CV_UNUSED(alpha); return 0; #endif } @@ -657,6 +660,7 @@ public: return int(bayer - (bayer_end - width)); #else + CV_UNUSED(bayer); CV_UNUSED(bayer_step); CV_UNUSED(dst); CV_UNUSED(width); CV_UNUSED(blue); return 0; #endif } From 40843d06aba0fa16fdeb75b1262d6a901048854a Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 7 Mar 2025 16:24:20 +0300 Subject: [PATCH 6/6] Disable CV_SIMD_SCALABLE for demosaicing as the implementation is not efficient on RISC-V RVV. --- modules/imgproc/src/demosaicing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/demosaicing.cpp b/modules/imgproc/src/demosaicing.cpp index 68816a6fd6..7916d5a319 100644 --- a/modules/imgproc/src/demosaicing.cpp +++ b/modules/imgproc/src/demosaicing.cpp @@ -129,7 +129,7 @@ public: static int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst, int width, int bcoeff, int gcoeff, int rcoeff) { -#if CV_SIMD || CV_SIMD_SCALABLE +#if CV_SIMD #if CV_NEON uint16x8_t masklo = vdupq_n_u16(255); const uchar* bayer_end = bayer + width;