From a858fb7cff0f50b469fc9da42a1e2b7104abcc3f Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 17 Dec 2025 12:57:50 +0300 Subject: [PATCH 1/2] Stateless HAL for filters and morphology. --- modules/imgproc/src/filter.dispatch.cpp | 35 +++++++- modules/imgproc/src/hal_replacement.hpp | 111 ++++++++++++++++++++++++ modules/imgproc/src/morph.dispatch.cpp | 16 +++- 3 files changed, 159 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/src/filter.dispatch.cpp b/modules/imgproc/src/filter.dispatch.cpp index a1568d249c..172ec34d8e 100644 --- a/modules/imgproc/src/filter.dispatch.cpp +++ b/modules/imgproc/src/filter.dispatch.cpp @@ -1171,8 +1171,24 @@ static bool replacementFilter2D(int stype, int dtype, int kernel_type, int anchor_x, int anchor_y, double delta, int borderType, bool isSubmatrix) { + // Prioritize stateless implementation + int res = cv_hal_filter_stateless(src_data, src_step, stype, + dst_data, dst_step, dtype, width, height, + full_width, full_height, offset_x, offset_y, + kernel_data, kernel_step, kernel_type, + kernel_width, kernel_height, anchor_x, anchor_y, + delta, borderType, isSubmatrix, src_data == dst_data); + if (res == CV_HAL_ERROR_OK) + { + return true; + } else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) + { + CV_Error_(cv::Error::StsInternal, + ("HAL implementation filter_stateless ==> " CVAUX_STR(cv_hal_filter_stateless) " returned %d (0x%08x)", res, res)); + } + cvhalFilter2D* ctx; - int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height, + res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, src_data == dst_data); if (res == CV_HAL_ERROR_NOT_IMPLEMENTED) { @@ -1385,8 +1401,23 @@ static bool replacementSepFilter(int stype, int dtype, int ktype, uchar * kernely_data, int kernely_len, int anchor_x, int anchor_y, double delta, int borderType) { + // Prioritize stateless implementation + int res = cv_hal_sepFilter_stateless(src_data, src_step, stype, + dst_data, dst_step, dtype, + width, height, full_width, full_height, offset_x, offset_y, + kernelx_data, kernelx_len, kernely_data, kernely_len, ktype, + anchor_x, anchor_y, delta, borderType); + if (res == CV_HAL_ERROR_OK) + { + return true; + } else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) + { + CV_Error_(cv::Error::StsInternal, + ("HAL implementation sepFilter_stateless ==> " CVAUX_STR(cv_hal_sepFilter_stateless) " returned %d (0x%08x)", res, res)); + } + cvhalFilter2D *ctx; - int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, + res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, kernelx_data, kernelx_len, kernely_data, kernely_len, anchor_x, anchor_y, delta, borderType); diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 8bc20fbefd..f73094c494 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -86,6 +86,40 @@ int my_hal_filterFree(cvhalFilter2D *context) { */ struct cvhalFilter2D {}; +/** + @brief 2D filtering in a stateless manner + @param src_data source image data + @param src_step source image step + @param src_type source image type + @param dst_data destination image data + @param dst_step destination image step + @param dst_type destination image type + @param width images width + @param height images height + @param full_width full width of source image (outside the ROI) + @param full_height full height of source image (outside the ROI) + @param offset_x source image ROI offset X + @param offset_y source image ROI offset Y + @param kernel_data pointer to kernel data + @param kernel_step kernel step + @param kernel_type kernel type (CV_8U, ...) + @param kernel_width kernel width + @param kernel_height kernel height + @param anchor_x relative X position of center point within the kernel + @param anchor_y relative Y position of center point within the kernel + @param delta added to pixel values + @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) + @param isSubmatrix indicates whether the submatrices will be allowed as source image + @param allowInplace indicates whether the inplace operation will be possible + @sa cv::filter2D, cv::hal::Filter2D + */ +inline int hal_ni_filter_stateless(uchar * src_data, size_t src_step, int src_type, + uchar * dst_data, size_t dst_step, int dst_type, + int width, int height, int full_width, int full_height, int offset_x, int offset_y, + uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int anchor_x, int anchor_y, double delta, int borderType, bool isSubmatrix, bool allowInplace) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + /** @brief hal_filterInit @param context double pointer to user-defined context @@ -131,11 +165,44 @@ inline int hal_ni_filter(cvhalFilter2D *context, uchar *src_data, size_t src_ste inline int hal_ni_filterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @cond IGNORED +#define cv_hal_filter_stateless hal_ni_filter_stateless #define cv_hal_filterInit hal_ni_filterInit #define cv_hal_filter hal_ni_filter #define cv_hal_filterFree hal_ni_filterFree //! @endcond +/** + @brief separable filtering in a stateless manner + @param src_data source image data + @param src_step source image step + @param src_type source image type + @param dst_data destination image data + @param dst_step destination image step + @param dst_type destination image type + @param width images width + @param height images height + @param full_width full width of source image (outside the ROI) + @param full_height full height of source image (outside the ROI) + @param offset_x source image ROI offset X + @param offset_y source image ROI offset Y + @param kernelx_data pointer to x-kernel data + @param kernelx_len x-kernel vector length + @param kernely_data pointer to y-kernel data + @param kernely_len y-kernel vector length + @param kernel_type kernel type (CV_8U, ...) + @param anchor_x relative X position of center point within the kernel + @param anchor_y relative Y position of center point within the kernel + @param delta added to pixel values + @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) + @sa cv::sepFilter2D, cv::hal::SepFilter2D + */ +inline int hal_ni_sepFilter_stateless(uchar * src_data, size_t src_step, int src_type, + uchar * dst_data, size_t dst_step, int dst_type, + int width, int height, int full_width, int full_height, int offset_x, int offset_y, + uchar * kernelx_data, int kernelx_len, uchar * kernely_data, int kernely_len, int kernel_type, + int anchor_x, int anchor_y, double delta, int borderType) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + /** @brief hal_sepFilterInit @param context double pointer to user-defined context @@ -177,11 +244,54 @@ inline int hal_ni_sepFilter(cvhalFilter2D *context, uchar *src_data, size_t src_ inline int hal_ni_sepFilterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @cond IGNORED +#define cv_hal_sepFilter_stateless hal_ni_sepFilter_stateless #define cv_hal_sepFilterInit hal_ni_sepFilterInit #define cv_hal_sepFilter hal_ni_sepFilter #define cv_hal_sepFilterFree hal_ni_sepFilterFree //! @endcond +/** + @brief morphology in a stateless manner + @param operation morphology operation CV_HAL_MORPH_ERODE or CV_HAL_MORPH_DILATE + @param dst_type destination image type + @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 src_type source image type + @param width images width + @param height images height + @param src_full_width full width of source image (outside the ROI) + @param src_full_height full height of source image (outside the ROI) + @param src_roi_x source image ROI X offset + @param src_roi_y source image ROI Y offset + @param dst_full_width full width of destination image + @param dst_full_height full height of destination image + @param dst_roi_x destination image ROI X offset + @param dst_roi_y destination image ROI Y offset + @param kernel_data pointer to kernel data + @param kernel_step kernel step + @param kernel_type kernel type (CV_8U, ...) + @param kernel_width kernel width + @param kernel_height kernel height + @param anchor_x relative X position of center point within the kernel + @param anchor_y relative Y position of center point within the kernel + @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) + @param borderValue values to use for CV_HAL_BORDER_CONSTANT mode + @param iterations number of iterations + @param allowSubmatrix indicates whether the submatrices will be allowed as source image + @param allowInplace indicates whether the inplace operation will be possible + @sa cv::erode, cv::dilate, cv::morphologyEx, cv::hal::Morph + */ +inline int hal_ni_morph_stateless(int operation, uchar * src_data, size_t src_step, int src_type, + uchar * dst_data, size_t dst_step, int dst_type, + int width, int height, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, + int dst_full_width, int dst_full_height, int dst_roi_x, int dst_roi_y, + uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int anchor_x, int anchor_y, int borderType, const double borderValue[4], + int iterations, bool allowSubmatrix, bool allowInplace) +{ return CV_HAL_ERROR_NOT_IMPLEMENTED; } + /** @brief hal_morphInit @param context double pointer to user-defined context @@ -233,6 +343,7 @@ inline int hal_ni_morph(cvhalFilter2D *context, uchar *src_data, size_t src_step inline int hal_ni_morphFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } //! @cond IGNORED +#define cv_hal_morph_stateless hal_ni_morph_stateless #define cv_hal_morphInit hal_ni_morphInit #define cv_hal_morph hal_ni_morph #define cv_hal_morphFree hal_ni_morphFree diff --git a/modules/imgproc/src/morph.dispatch.cpp b/modules/imgproc/src/morph.dispatch.cpp index 98adbf10c1..ee473886ad 100644 --- a/modules/imgproc/src/morph.dispatch.cpp +++ b/modules/imgproc/src/morph.dispatch.cpp @@ -212,8 +212,22 @@ static bool halMorph(int op, int src_type, int dst_type, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool isSubmatrix) { + // Prioritize stateless implementation + int res = cv_hal_morph_stateless(op, src_data, src_step, src_type, dst_data, dst_step, dst_type, width, height, + roi_width, roi_height, roi_x, roi_y, roi_width2, roi_height2, roi_x2, roi_y2, + kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, anchor_x, anchor_y, + borderType, borderValue, iterations, isSubmatrix, src_data == dst_data); + if (res == CV_HAL_ERROR_OK) + { + return true; + } else if (res != CV_HAL_ERROR_NOT_IMPLEMENTED) + { + CV_Error_(cv::Error::StsInternal, + ("HAL implementation morph_stateless ==> " CVAUX_STR(cv_hal_morph_stateless) " returned %d (0x%08x)", res, res)); + } + cvhalFilter2D * ctx; - int res = cv_hal_morphInit(&ctx, op, src_type, dst_type, width, height, + res = cv_hal_morphInit(&ctx, op, src_type, dst_type, width, height, kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, anchor_x, anchor_y, borderType, borderValue, From a3380cc128d8c8d880d20f88cb3a8d6ec6971831 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 19 Dec 2025 14:59:45 +0300 Subject: [PATCH 2/2] Code review fixes. --- modules/imgproc/src/hal_replacement.hpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index f73094c494..6df3b77c9b 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -113,10 +113,10 @@ struct cvhalFilter2D {}; @param allowInplace indicates whether the inplace operation will be possible @sa cv::filter2D, cv::hal::Filter2D */ -inline int hal_ni_filter_stateless(uchar * src_data, size_t src_step, int src_type, +inline int hal_ni_filter_stateless(const uchar * src_data, size_t src_step, int src_type, uchar * dst_data, size_t dst_step, int dst_type, int width, int height, int full_width, int full_height, int offset_x, int offset_y, - uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + const uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, int anchor_x, int anchor_y, double delta, int borderType, bool isSubmatrix, bool allowInplace) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -196,11 +196,12 @@ inline int hal_ni_filterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NOT_I @param borderType border processing mode (CV_HAL_BORDER_REFLECT, ...) @sa cv::sepFilter2D, cv::hal::SepFilter2D */ -inline int hal_ni_sepFilter_stateless(uchar * src_data, size_t src_step, int src_type, +inline int hal_ni_sepFilter_stateless(const uchar * src_data, size_t src_step, int src_type, uchar * dst_data, size_t dst_step, int dst_type, int width, int height, int full_width, int full_height, int offset_x, int offset_y, - uchar * kernelx_data, int kernelx_len, uchar * kernely_data, int kernely_len, int kernel_type, - int anchor_x, int anchor_y, double delta, int borderType) + const uchar * kernelx_data, int kernelx_len, + const uchar * kernely_data, int kernely_len, + int kernel_type, int anchor_x, int anchor_y, double delta, int borderType) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } /** @@ -253,12 +254,12 @@ inline int hal_ni_sepFilterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NO /** @brief morphology in a stateless manner @param operation morphology operation CV_HAL_MORPH_ERODE or CV_HAL_MORPH_DILATE - @param dst_type destination image type @param src_data source image data @param src_step source image step + @param src_type source image type @param dst_data destination image data @param dst_step destination image step - @param src_type source image type + @param dst_type destination image type @param width images width @param height images height @param src_full_width full width of source image (outside the ROI) @@ -283,11 +284,11 @@ inline int hal_ni_sepFilterFree(cvhalFilter2D *context) { return CV_HAL_ERROR_NO @param allowInplace indicates whether the inplace operation will be possible @sa cv::erode, cv::dilate, cv::morphologyEx, cv::hal::Morph */ -inline int hal_ni_morph_stateless(int operation, uchar * src_data, size_t src_step, int src_type, +inline int hal_ni_morph_stateless(int operation, const uchar * src_data, size_t src_step, int src_type, uchar * dst_data, size_t dst_step, int dst_type, int width, int height, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, int dst_full_width, int dst_full_height, int dst_roi_x, int dst_roi_y, - uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + const uchar * kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }