From 59f762b2f0baedfbc77a2a30820b82495dd30b48 Mon Sep 17 00:00:00 2001 From: adsha-quic Date: Thu, 19 Dec 2024 10:58:24 +0530 Subject: [PATCH] Merge pull request #26619 from CodeLinaro:adsha_2ndPost FastCV-based HAL for OpenCV acceleration 2ndpost-2 #26619 ### Detailed description: - Add support for multiply 8u, 16s and 32f - Add support for cv_hal_pyrdown 8u - Add support for cv_hal_cvtBGRtoHSV and cv_hal_cvtBGRtoYUVApprox 8u Requires binary from [opencv/opencv_3rdparty#90](https://github.com/opencv/opencv_3rdparty/pull/90) Depends on: [opencv/opencv#26617](https://github.com/opencv/opencv/pull/26617) ### 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 - [ ] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- 3rdparty/fastcv/include/fastcv_hal_core.hpp | 42 +++ .../fastcv/include/fastcv_hal_imgproc.hpp | 74 ++++-- 3rdparty/fastcv/src/fastcv_hal_core.cpp | 188 +++++++++++++ 3rdparty/fastcv/src/fastcv_hal_imgproc.cpp | 249 ++++++++++++++++++ 4 files changed, 525 insertions(+), 28 deletions(-) diff --git a/3rdparty/fastcv/include/fastcv_hal_core.hpp b/3rdparty/fastcv/include/fastcv_hal_core.hpp index 47025856f7..03c17dc6b5 100644 --- a/3rdparty/fastcv/include/fastcv_hal_core.hpp +++ b/3rdparty/fastcv/include/fastcv_hal_core.hpp @@ -26,6 +26,12 @@ #define cv_hal_rotate90 fastcv_hal_rotate #undef cv_hal_addWeighted8u #define cv_hal_addWeighted8u fastcv_hal_addWeighted8u +#undef cv_hal_mul8u +#define cv_hal_mul8u fastcv_hal_mul8u +#undef cv_hal_mul16s +#define cv_hal_mul16s fastcv_hal_mul16s +#undef cv_hal_mul32f +#define cv_hal_mul32f fastcv_hal_mul32f //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// @brief look-up table transform of an array. @@ -177,4 +183,40 @@ int fastcv_hal_addWeighted8u( int height, const double scalars[3]); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_mul8u( + const uchar *src1_data, + size_t src1_step, + const uchar *src2_data, + size_t src2_step, + uchar *dst_data, + size_t dst_step, + int width, + int height, + double scale); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_mul16s( + const short *src1_data, + size_t src1_step, + const short *src2_data, + size_t src2_step, + short *dst_data, + size_t dst_step, + int width, + int height, + double scale); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_mul32f( + const float *src1_data, + size_t src1_step, + const float *src2_data, + size_t src2_step, + float *dst_data, + size_t dst_step, + int width, + int height, + double scale); + #endif diff --git a/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp b/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp index 7fd49bc62c..8b9a2ca4da 100644 --- a/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp +++ b/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp @@ -20,7 +20,12 @@ #define cv_hal_gaussianBlurBinomial fastcv_hal_gaussianBlurBinomial #undef cv_hal_warpPerspective #define cv_hal_warpPerspective fastcv_hal_warpPerspective - +#undef cv_hal_pyrdown +#define cv_hal_pyrdown fastcv_hal_pyrdown +#undef cv_hal_cvtBGRtoHSV +#define cv_hal_cvtBGRtoHSV fastcv_hal_cvtBGRtoHSV +#undef cv_hal_cvtBGRtoYUVApprox +#define cv_hal_cvtBGRtoYUVApprox fastcv_hal_cvtBGRtoYUVApprox //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// @brief Calculate medianBlur filter /// @param src_data Source image data @@ -88,33 +93,6 @@ int fastcv_hal_sobel( double delta, int border_type); -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// @brief Canny edge detector -/// @param src_data Source image data -/// @param src_step Source image step -/// @param dst_data Destination image data -/// @param dst_step Destination image step -/// @param width Source image width -/// @param height Source image height -/// @param cn Number of channels -/// @param lowThreshold low thresholds value -/// @param highThreshold high thresholds value -/// @param ksize Kernel size for Sobel operator. -/// @param L2gradient Flag, indicating use L2 or L1 norma. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -int fastcv_hal_canny( - const uchar* src_data, - size_t src_step, - uchar* dst_data, - size_t dst_step, - int width, - int height, - int cn, - double lowThreshold, - double highThreshold, - int ksize, - bool L2gradient); - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int fastcv_hal_boxFilter( @@ -217,4 +195,44 @@ int fastcv_hal_warpPerspective( int border_type, const double border_value[4]); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_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); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_cvtBGRtoHSV( + const uchar * src_data, + size_t src_step, + uchar * dst_data, + size_t dst_step, + int width, + int height, + int depth, + int scn, + bool swapBlue, + bool isFullRange, + bool isHSV); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_cvtBGRtoYUVApprox( + const uchar * src_data, + size_t src_step, + uchar * dst_data, + size_t dst_step, + int width, + int height, + int depth, + int scn, + bool swapBlue, + bool isCbCr); #endif diff --git a/3rdparty/fastcv/src/fastcv_hal_core.cpp b/3rdparty/fastcv/src/fastcv_hal_core.cpp index a219eddc8c..d46bf9a172 100644 --- a/3rdparty/fastcv/src/fastcv_hal_core.cpp +++ b/3rdparty/fastcv/src/fastcv_hal_core.cpp @@ -383,4 +383,192 @@ int fastcv_hal_addWeighted8u( } CV_HAL_RETURN(status, hal_addWeighted8u_v2); +} + +int fastcv_hal_mul8u( + const uchar *src1_data, + size_t src1_step, + const uchar *src2_data, + size_t src2_step, + uchar *dst_data, + size_t dst_step, + int width, + int height, + double scale) +{ + int8_t sF; + + if(FCV_CMP_EQ(scale,1.0)) { sF = 0; } + else if(scale > 1.0) + { + if(FCV_CMP_EQ(scale,2.0)) { sF = -1; } + else if(FCV_CMP_EQ(scale,4.0)) { sF = -2; } + else if(FCV_CMP_EQ(scale,8.0)) { sF = -3; } + else if(FCV_CMP_EQ(scale,16.0)) { sF = -4; } + else if(FCV_CMP_EQ(scale,32.0)) { sF = -5; } + else if(FCV_CMP_EQ(scale,64.0)) { sF = -6; } + else if(FCV_CMP_EQ(scale,128.0)) { sF = -7; } + else if(FCV_CMP_EQ(scale,256.0)) { sF = -8; } + else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + } + else if(scale > 0 && scale < 1.0) + { + if(FCV_CMP_EQ(scale,1/2.0)) { sF = 1; } + else if(FCV_CMP_EQ(scale,1/4.0)) { sF = 2; } + else if(FCV_CMP_EQ(scale,1/8.0)) { sF = 3; } + else if(FCV_CMP_EQ(scale,1/16.0)) { sF = 4; } + else if(FCV_CMP_EQ(scale,1/32.0)) { sF = 5; } + else if(FCV_CMP_EQ(scale,1/64.0)) { sF = 6; } + else if(FCV_CMP_EQ(scale,1/128.0)) { sF = 7; } + else if(FCV_CMP_EQ(scale,1/256.0)) { sF = 8; } + else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + } + else + CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + + INITIALIZATION_CHECK; + + int nStripes = cv::getNumThreads(); + + if(height == 1) + { + cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){ + int rangeWidth = range.end - range.start; + const uchar* yS1 = src1_data + static_cast(range.start); + const uchar* yS2 = src2_data + static_cast(range.start); + uchar* yD = dst_data + static_cast(range.start); + fcvElementMultiplyu8(yS1, rangeWidth, 1, 0, yS2, 0, sF, + FASTCV_CONVERT_POLICY_SATURATE, yD, 0); + }, nStripes); + } + else + { + cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){ + int rangeHeight = range.end - range.start; + const uchar* yS1 = src1_data + static_cast(range.start)*src1_step; + const uchar* yS2 = src2_data + static_cast(range.start)*src2_step; + uchar* yD = dst_data + static_cast(range.start)*dst_step; + fcvElementMultiplyu8(yS1, width, rangeHeight, src1_step, yS2, src2_step, + sF, FASTCV_CONVERT_POLICY_SATURATE, yD, dst_step); + }, nStripes); + } + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_mul8u); +} + +int fastcv_hal_mul16s( + const short *src1_data, + size_t src1_step, + const short *src2_data, + size_t src2_step, + short *dst_data, + size_t dst_step, + int width, + int height, + double scale) +{ + int8_t sF; + + if(FCV_CMP_EQ(scale,1.0)) { sF = 0; } + else if(scale > 1.0) + { + if(FCV_CMP_EQ(scale,2.0)) { sF = -1; } + else if(FCV_CMP_EQ(scale,4.0)) { sF = -2; } + else if(FCV_CMP_EQ(scale,8.0)) { sF = -3; } + else if(FCV_CMP_EQ(scale,16.0)) { sF = -4; } + else if(FCV_CMP_EQ(scale,32.0)) { sF = -5; } + else if(FCV_CMP_EQ(scale,64.0)) { sF = -6; } + else if(FCV_CMP_EQ(scale,128.0)) { sF = -7; } + else if(FCV_CMP_EQ(scale,256.0)) { sF = -8; } + else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + } + else if(scale > 0 && scale < 1.0) + { + if(FCV_CMP_EQ(scale,1/2.0)) { sF = 1; } + else if(FCV_CMP_EQ(scale,1/4.0)) { sF = 2; } + else if(FCV_CMP_EQ(scale,1/8.0)) { sF = 3; } + else if(FCV_CMP_EQ(scale,1/16.0)) { sF = 4; } + else if(FCV_CMP_EQ(scale,1/32.0)) { sF = 5; } + else if(FCV_CMP_EQ(scale,1/64.0)) { sF = 6; } + else if(FCV_CMP_EQ(scale,1/128.0)) { sF = 7; } + else if(FCV_CMP_EQ(scale,1/256.0)) { sF = 8; } + else CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + } + else + CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + + INITIALIZATION_CHECK; + + int nStripes = cv::getNumThreads(); + + if(height == 1) + { + cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){ + int rangeWidth = range.end - range.start; + const short* yS1 = src1_data + static_cast(range.start); + const short* yS2 = src2_data + static_cast(range.start); + short* yD = dst_data + static_cast(range.start); + fcvElementMultiplys16(yS1, rangeWidth, 1, 0, yS2, 0, sF, + FASTCV_CONVERT_POLICY_SATURATE, yD, 0); + }, nStripes); + } + else + { + cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){ + int rangeHeight = range.end - range.start; + const short* yS1 = src1_data + static_cast(range.start) * (src1_step/sizeof(short)); + const short* yS2 = src2_data + static_cast(range.start) * (src2_step/sizeof(short)); + short* yD = dst_data + static_cast(range.start) * (dst_step/sizeof(short)); + fcvElementMultiplys16(yS1, width, rangeHeight, src1_step, yS2, src2_step, + sF, FASTCV_CONVERT_POLICY_SATURATE, yD, dst_step); + }, nStripes); + } + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_mul16s); +} + +int fastcv_hal_mul32f( + const float *src1_data, + size_t src1_step, + const float *src2_data, + size_t src2_step, + float *dst_data, + size_t dst_step, + int width, + int height, + double scale) +{ + if(!FCV_CMP_EQ(scale,1.0)) + CV_HAL_RETURN_NOT_IMPLEMENTED("scale factor not supported"); + + INITIALIZATION_CHECK; + + int nStripes = cv::getNumThreads(); + + if(height == 1) + { + cv::parallel_for_(cv::Range(0, width), [&](const cv::Range &range){ + int rangeWidth = range.end - range.start; + const float* yS1 = src1_data + static_cast(range.start); + const float* yS2 = src2_data + static_cast(range.start); + float* yD = dst_data + static_cast(range.start); + fcvElementMultiplyf32(yS1, rangeWidth, 1, 0, yS2, 0, yD, 0); + }, nStripes); + } + else + { + cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){ + int rangeHeight = range.end - range.start; + const float* yS1 = src1_data + static_cast(range.start) * (src1_step/sizeof(float)); + const float* yS2 = src2_data + static_cast(range.start) * (src2_step/sizeof(float)); + float* yD = dst_data + static_cast(range.start) * (dst_step/sizeof(float)); + fcvElementMultiplyf32(yS1, width, rangeHeight, src1_step, + yS2, src2_step, yD, dst_step); + }, nStripes); + } + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_mul32f); } \ No newline at end of file diff --git a/3rdparty/fastcv/src/fastcv_hal_imgproc.cpp b/3rdparty/fastcv/src/fastcv_hal_imgproc.cpp index 7f128e7d1c..58872d8f57 100644 --- a/3rdparty/fastcv/src/fastcv_hal_imgproc.cpp +++ b/3rdparty/fastcv/src/fastcv_hal_imgproc.cpp @@ -743,4 +743,253 @@ int fastcv_hal_warpPerspective( CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Src type:%s is not supported", cv::typeToString(src_type).c_str())); CV_HAL_RETURN(status, hal_warpPerspective); +} + +class FcvPyrLoop_Invoker : public cv::ParallelLoopBody +{ +public: + + FcvPyrLoop_Invoker(cv::Mat src_, int width_, int height_, cv::Mat dst_, int bdr_, int knl_, int stripeHeight_, int nStripes_) : + cv::ParallelLoopBody(), src(src_), width(width_), height(height_), dst(dst_), bdr(bdr_), knl(knl_), stripeHeight(stripeHeight_), nStripes(nStripes_) + { + } + + virtual void operator()(const cv::Range& range) const CV_OVERRIDE + { + int height_ = stripeHeight * (range.end - range.start); + int width_ = width; + cv::Mat src_; + int n = knl/2; + + if(range.end == nStripes) + height_ += (height - range.end * stripeHeight); + + src_ = cv::Mat(height_ + 2*n, width_ + 2*n, CV_8U); + + if(range.start == 0 && range.end == nStripes) + cv::copyMakeBorder(src(cv::Rect(0, 0, width, height)), src_, n, n, n, n, bdr); + else if(range.start == 0) + cv::copyMakeBorder(src(cv::Rect(0, 0, width_, height_ + n)), src_, n, 0, n, n, bdr); + else if(range.end == nStripes) + cv::copyMakeBorder(src(cv::Rect(0, range.start * stripeHeight - n, width_, height_ + n)), src_, 0, n, n, n, bdr); + else + cv::copyMakeBorder(src(cv::Rect(0, range.start * stripeHeight - n, width_, height_ + 2*n)), src_, 0, 0, n, n, bdr); + + int dstHeight_, dstWidth_, origDstHeight_, origDstWidth_; + dstHeight_ = (height_ + 2*n + 1)/2; + dstWidth_ = (width_ + 2*n + 1)/2; + origDstHeight_ = (height_ + 1)/2; + origDstWidth_ = (width_ + 1)/2; + + cv::Mat dst_padded = cv::Mat(dstHeight_, dstWidth_, CV_8U); + + fcvPyramidLevel_v2 framePyr[2]; + framePyr[0].ptr = NULL; + framePyr[1].ptr = dst_padded.data; + framePyr[1].stride = dstWidth_; + + fcvPyramidCreateu8_v4(src_.data, width_ + 2*n, height_ + 2*n, + width_ + 2*n, 2, FASTCV_PYRAMID_SCALE_HALF, + framePyr, FASTCV_BORDER_UNDEFINED, 0); + + int start_val = stripeHeight * range.start; + cv::Mat dst_temp1 = dst_padded(cv::Rect(n/2, n/2, origDstWidth_, origDstHeight_)); + cv::Mat dst_temp2 = dst(cv::Rect(0, start_val/2, origDstWidth_, origDstHeight_)); + dst_temp1.copyTo(dst_temp2); + } + +private: + cv::Mat src; + const int width; + const int height; + cv::Mat dst; + const int bdr; + const int knl; + const int stripeHeight; + const int nStripes; + + FcvPyrLoop_Invoker(const FcvPyrLoop_Invoker &); // = delete; + const FcvPyrLoop_Invoker& operator= (const FcvPyrLoop_Invoker &); // = delete; +}; + +int fastcv_hal_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) +{ + if(depth != CV_8U || cn!= 1) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("src type not supported"); + } + + int dstW = (src_width & 1) == 1 ? ((src_width + 1) >> 1) : ((src_width) >> 1); + int dstH = (src_height & 1) == 1 ? ((src_height + 1) >> 1) : ((src_height) >> 1); + + if((dstW > dst_width) || (dstH > dst_height)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("dst size needs to be atleast half of the src size"); + } + + INITIALIZATION_CHECK; + + fcvBorderType bdr; + uint8_t bVal = 0; + int nThreads = cv::getNumThreads(); + if(nThreads <= 1) + { + switch(border_type) + { + case cv::BORDER_REPLICATE: + bdr = FASTCV_BORDER_REPLICATE; + break; + case cv::BORDER_REFLECT: + bdr = FASTCV_BORDER_REFLECT; + break; + case cv::BORDER_REFLECT101: // cv::BORDER_REFLECT_101, BORDER_DEFAULT + bdr = FASTCV_BORDER_REFLECT_V2; + break; + default: + CV_HAL_RETURN_NOT_IMPLEMENTED("border type not supported"); + } + + fcvPyramidLevel_v2 frame1Pyr[2]; + frame1Pyr[0].ptr = NULL; + frame1Pyr[1].ptr = dst_data; + frame1Pyr[1].stride = dst_step; + + fcvStatus status = fcvPyramidCreateu8_v4(src_data, src_width, src_height, + src_step, 2, FASTCV_PYRAMID_SCALE_HALF, + frame1Pyr, bdr, bVal); + + CV_HAL_RETURN(status,hal_pyrdown); + } + else + { + cv::Mat src = cv::Mat(src_height, src_width, CV_8UC1, (void*)src_data, src_step); + cv::Mat dst = cv::Mat(dst_height, dst_width, CV_8UC1, (void*)dst_data, dst_step); + + int nStripes, stripeHeight = nThreads * 10; + + if(src.rows/stripeHeight == 0) + nStripes = 1; + else + nStripes = (src.rows/stripeHeight); + + cv::parallel_for_(cv::Range(0, nStripes), + FcvPyrLoop_Invoker(src, src_width, src_height, dst, border_type, 5, stripeHeight, nStripes), nStripes); + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_pyrdown); + } +} + +int fastcv_hal_cvtBGRtoHSV( + const uchar * src_data, + size_t src_step, + uchar * dst_data, + size_t dst_step, + int width, + int height, + int depth, + int scn, + bool swapBlue, + bool isFullRange, + bool isHSV) +{ + if(width * height > 640 * 480) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("input size not supported"); + } + if(scn != 3 || depth != CV_8U) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("src type not supported"); + } + else if(!isHSV || !isFullRange) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("Full range HSV supported"); + } + else if(!swapBlue) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("current color code not supported, expected swapped blue channel"); + } + else if (src_data == dst_data) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("In-place not supported"); + } + else if((src_step < (size_t)width*3) || + (dst_step < (size_t)width*3)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("unexpected stride values"); + } + + INITIALIZATION_CHECK; + + int nStripes = cv::getNumThreads(); + + cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){ + int sHeight = range.end - range.start; + const uchar* yS = src_data + static_cast(range.start) * src_step; + uchar* yD = dst_data + static_cast(range.start) * dst_step; + fcvColorRGB888ToHSV888u8(yS, width, sHeight, src_step, yD, dst_step); + }, nStripes); + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_BGRtoHSV); +} + +int fastcv_hal_cvtBGRtoYUVApprox( + const uchar * src_data, + size_t src_step, + uchar * dst_data, + size_t dst_step, + int width, + int height, + int depth, + int scn, + bool swapBlue, + bool isCbCr) +{ + if(scn != 3 || depth != CV_8U) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("src type not supported"); + } + else if(!isCbCr) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("CbCr supported"); + } + else if(!swapBlue) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("expected swapped blue channel"); + } + else if (src_data == dst_data) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("In-place not supported"); + } + else if((src_step < (size_t)width*3) || + (dst_step < (size_t)width*3)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("unexpected stride values"); + } + + INITIALIZATION_CHECK; + + int nStripes = cv::getNumThreads(); + + cv::parallel_for_(cv::Range(0, height), [&](const cv::Range &range){ + int sHeight = range.end - range.start; + const uchar* yS = src_data + static_cast(range.start) * src_step; + uchar* yD = dst_data + static_cast(range.start) * dst_step; + fcvColorRGB888toYCrCbu8_v3(yS, width, sHeight, src_step, yD, dst_step); + }, nStripes); + + fcvStatus status = FASTCV_SUCCESS; + CV_HAL_RETURN(status, hal_BGRtoYUVApprox); } \ No newline at end of file