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

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
This commit is contained in:
adsha-quic
2024-12-19 10:58:24 +05:30
committed by GitHub
parent 537a2566cf
commit 59f762b2f0
4 changed files with 525 additions and 28 deletions
+42
View File
@@ -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
+46 -28
View File
@@ -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
+188
View File
@@ -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<size_t>(range.start);
const uchar* yS2 = src2_data + static_cast<size_t>(range.start);
uchar* yD = dst_data + static_cast<size_t>(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<size_t>(range.start)*src1_step;
const uchar* yS2 = src2_data + static_cast<size_t>(range.start)*src2_step;
uchar* yD = dst_data + static_cast<size_t>(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<size_t>(range.start);
const short* yS2 = src2_data + static_cast<size_t>(range.start);
short* yD = dst_data + static_cast<size_t>(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<size_t>(range.start) * (src1_step/sizeof(short));
const short* yS2 = src2_data + static_cast<size_t>(range.start) * (src2_step/sizeof(short));
short* yD = dst_data + static_cast<size_t>(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<size_t>(range.start);
const float* yS2 = src2_data + static_cast<size_t>(range.start);
float* yD = dst_data + static_cast<size_t>(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<size_t>(range.start) * (src1_step/sizeof(float));
const float* yS2 = src2_data + static_cast<size_t>(range.start) * (src2_step/sizeof(float));
float* yD = dst_data + static_cast<size_t>(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);
}
+249
View File
@@ -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<size_t>(range.start) * src_step;
uchar* yD = dst_data + static_cast<size_t>(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<size_t>(range.start) * src_step;
uchar* yD = dst_data + static_cast<size_t>(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);
}