From 5f1b05af0ebc0f6a396feee2b28dc9e94c1f7034 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:50:38 +0300 Subject: [PATCH] Merge pull request #26556 from asmorkalov:FastcvHAL_1stPost Added Fastcv HAL changes in the 3rdparty folder. Code Changes includes HAL code , Fastcv libs and Headers Change-Id: I2f0ddb1f57515c82ae86ba8c2a82965b1a9626ec Requires binaries from https://github.com/opencv/opencv_3rdparty/pull/86. Related patch to opencv_contrib: https://github.com/opencv/opencv_contrib/pull/3811 ### 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/CMakeLists.txt | 34 ++ 3rdparty/fastcv/fastcv.cmake | 43 +++ 3rdparty/fastcv/include/fastcv_hal_core.hpp | 155 ++++++++ .../fastcv/include/fastcv_hal_imgproc.hpp | 151 ++++++++ 3rdparty/fastcv/include/fastcv_hal_utils.hpp | 83 +++++ 3rdparty/fastcv/src/fastcv_hal_core.cpp | 334 ++++++++++++++++++ 3rdparty/fastcv/src/fastcv_hal_imgproc.cpp | 318 +++++++++++++++++ 3rdparty/fastcv/src/fastcv_hal_utils.cpp | 56 +++ CMakeLists.txt | 20 ++ cmake/OpenCVFindLibsPerf.cmake | 20 ++ 10 files changed, 1214 insertions(+) create mode 100644 3rdparty/fastcv/CMakeLists.txt create mode 100644 3rdparty/fastcv/fastcv.cmake create mode 100644 3rdparty/fastcv/include/fastcv_hal_core.hpp create mode 100644 3rdparty/fastcv/include/fastcv_hal_imgproc.hpp create mode 100644 3rdparty/fastcv/include/fastcv_hal_utils.hpp create mode 100644 3rdparty/fastcv/src/fastcv_hal_core.cpp create mode 100644 3rdparty/fastcv/src/fastcv_hal_imgproc.cpp create mode 100644 3rdparty/fastcv/src/fastcv_hal_utils.cpp diff --git a/3rdparty/fastcv/CMakeLists.txt b/3rdparty/fastcv/CMakeLists.txt new file mode 100644 index 0000000000..268d261a98 --- /dev/null +++ b/3rdparty/fastcv/CMakeLists.txt @@ -0,0 +1,34 @@ +if(HAVE_FASTCV) + set(FASTCV_HAL_VERSION 0.0.1 CACHE INTERNAL "") + set(FASTCV_HAL_LIBRARIES "fastcv_hal" CACHE INTERNAL "") + set(FASTCV_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" CACHE INTERNAL "") + set(FASTCV_HAL_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/include/fastcv_hal_core.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/fastcv_hal_imgproc.hpp" + CACHE INTERNAL "") + + file(GLOB FASTCV_HAL_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") + + add_library(fastcv_hal STATIC ${FASTCV_HAL_FILES}) + + target_include_directories(fastcv_hal PRIVATE + ${CMAKE_SOURCE_DIR}/modules/core/include + ${CMAKE_SOURCE_DIR}/modules/imgproc/include + ${FASTCV_HAL_INCLUDE_DIRS} ${FastCV_INCLUDE_PATH}) + + target_link_libraries(fastcv_hal PUBLIC ${FASTCV_LIBRARY}) + + set_target_properties(fastcv_hal PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}) + + if(NOT BUILD_SHARED_LIBS) + ocv_install_target(fastcv_hal EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) + endif() + + ocv_install_3rdparty_licenses(FastCV "${OpenCV_BINARY_DIR}/3rdparty/fastcv/LICENSE") + + if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(fastcv_hal PROPERTIES FOLDER "3rdparty") + endif() +else() + message(STATUS "FastCV is not available, disabling related HAL") +endif(HAVE_FASTCV) diff --git a/3rdparty/fastcv/fastcv.cmake b/3rdparty/fastcv/fastcv.cmake new file mode 100644 index 0000000000..a3c452aa8e --- /dev/null +++ b/3rdparty/fastcv/fastcv.cmake @@ -0,0 +1,43 @@ +function(download_fastcv root_dir) + + # Commit SHA in the opencv_3rdparty repo + set(FASTCV_COMMIT "b8f0d48fa9dbebb0237d3e0abd206f9930c89db6") + + # Define actual FastCV versions + if(ANDROID) + if(AARCH64) + message(STATUS "Download FastCV for Android aarch64") + set(FCV_PACKAGE_NAME "fastcv_android_aarch64_2024_10_24.tgz") + set(FCV_PACKAGE_HASH "14486af00dc0282dac591dc9ccdd957e") + else() + message(STATUS "Download FastCV for Android armv7") + set(FCV_PACKAGE_NAME "fastcv_android_arm32_2024_10_24.tgz") + set(FCV_PACKAGE_HASH "b5afadd5a5b55f8f6c2e7361f225fa21") + endif() + elseif(UNIX AND NOT APPLE AND NOT IOS AND NOT XROS) + if(AARCH64) + set(FCV_PACKAGE_NAME "fastcv_linux_aarch64_2024_10_24.tgz") + set(FCV_PACKAGE_HASH "d15c7b77f2d3577ba46bd94e6cf15230") + else() + message("FastCV: fastcv lib for 32-bit Linux is not supported for now!") + endif() + endif(ANDROID) + + # Download Package + set(OPENCV_FASTCV_URL "https://raw.githubusercontent.com/opencv/opencv_3rdparty/${FASTCV_COMMIT}/fastcv/") + + ocv_download( FILENAME ${FCV_PACKAGE_NAME} + HASH ${FCV_PACKAGE_HASH} + URL ${OPENCV_FASTCV_URL} + DESTINATION_DIR ${root_dir} + ID FASTCV + STATUS res + UNPACK + RELATIVE_URL) + if(res) + set(HAVE_FASTCV TRUE CACHE BOOL "FastCV status") + else() + message(WARNING "FastCV: package download failed!") + endif() + +endfunction() diff --git a/3rdparty/fastcv/include/fastcv_hal_core.hpp b/3rdparty/fastcv/include/fastcv_hal_core.hpp new file mode 100644 index 0000000000..5753ee96bd --- /dev/null +++ b/3rdparty/fastcv/include/fastcv_hal_core.hpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#ifndef OPENCV_FASTCV_HAL_CORE_HPP_INCLUDED +#define OPENCV_FASTCV_HAL_CORE_HPP_INCLUDED + +#include + +#undef cv_hal_lut +#define cv_hal_lut fastcv_hal_lut +#undef cv_hal_normHammingDiff8u +#define cv_hal_normHammingDiff8u fastcv_hal_normHammingDiff8u +#undef cv_hal_mul8u16u +#define cv_hal_mul8u16u fastcv_hal_mul8u16u +#undef cv_hal_sub8u32f +#define cv_hal_sub8u32f fastcv_hal_sub8u32f +#undef cv_hal_transpose2d +#define cv_hal_transpose2d fastcv_hal_transpose2d +#undef cv_hal_meanStdDev +#define cv_hal_meanStdDev fastcv_hal_meanStdDev +#undef cv_hal_flip +#define cv_hal_flip fastcv_hal_flip +#undef cv_hal_rotate90 +#define cv_hal_rotate90 fastcv_hal_rotate + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief look-up table transform of an array. +/// @param src_data Source image data +/// @param src_step Source image step +/// @param src_type Source image type +/// @param lut_data Pointer to lookup table +/// @param lut_channel_size Size of each channel in bytes +/// @param lut_channels Number of channels in lookup table +/// @param dst_data Destination data +/// @param dst_step Destination step +/// @param width Width of images +/// @param height Height of images +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_lut( + const uchar* src_data, + size_t src_step, + size_t src_type, + const uchar* lut_data, + size_t lut_channel_size, + size_t lut_channels, + uchar* dst_data, + size_t dst_step, + int width, + int height); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief Hamming distance between two vectors +/// @param a pointer to first vector data +/// @param b pointer to second vector data +/// @param n length of vectors +/// @param cellSize how many bits of the vectors will be added and treated as a single bit, can be 1 (standard Hamming distance), 2 or 4 +/// @param result pointer to result output +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_normHammingDiff8u(const uchar* a, const uchar* b, int n, int cellSize, int* result); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_mul8u16u( + const uchar * src1_data, + size_t src1_step, + const uchar * src2_data, + size_t src2_step, + ushort * dst_data, + size_t dst_step, + int width, + int height, + double scale); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_sub8u32f( + const uchar *src1_data, + size_t src1_step, + const uchar *src2_data, + size_t src2_step, + float *dst_data, + size_t dst_step, + int width, + int height); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_transpose2d( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int src_width, + int src_height, + int element_size); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_meanStdDev( + const uchar * src_data, + size_t src_step, + int width, + int height, + int src_type, + double * mean_val, + double * stddev_val, + uchar * mask, + size_t mask_step); + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief Flips a 2D array around vertical, horizontal, or both axes +/// @param src_type source and destination image type +/// @param src_data source image data +/// @param src_step source image step +/// @param src_width source and destination image width +/// @param src_height source and destination image height +/// @param dst_data destination image data +/// @param dst_step destination image step +/// @param flip_mode 0 flips around x-axis, 1 around y-axis, -1 both +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_flip( + int src_type, + const uchar* src_data, + size_t src_step, + int src_width, + int src_height, + uchar* dst_data, + size_t dst_step, + int flip_mode); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief Rotates a 2D array in multiples of 90 degrees. +/// @param src_type source and destination image type +/// @param src_data source image data +/// @param src_step source image step +/// @param src_width source image width +/// @If angle has value [180] it is also destination image width +/// If angle has values [90, 270] it is also destination image height +/// @param src_height source and destination image height (destination image width for angles [90, 270]) +/// If angle has value [180] it is also destination image height +/// If angle has values [90, 270] it is also destination image width +/// @param dst_data destination image data +/// @param dst_step destination image step +/// @param angle clockwise angle for rotation in degrees from set [90, 180, 270] +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_rotate( + int src_type, + const uchar* src_data, + size_t src_step, + int src_width, + int src_height, + uchar* dst_data, + size_t dst_step, + int angle); + +#endif diff --git a/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp b/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp new file mode 100644 index 0000000000..dce20f927e --- /dev/null +++ b/3rdparty/fastcv/include/fastcv_hal_imgproc.hpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#ifndef OPENCV_FASTCV_HAL_IMGPROC_HPP_INCLUDED +#define OPENCV_FASTCV_HAL_IMGPROC_HPP_INCLUDED + +#include + +#undef cv_hal_medianBlur +#define cv_hal_medianBlur fastcv_hal_medianBlur +#undef cv_hal_sobel +#define cv_hal_sobel fastcv_hal_sobel +#undef cv_hal_boxFilter +#define cv_hal_boxFilter fastcv_hal_boxFilter +#undef cv_hal_adaptiveThreshold +#define cv_hal_adaptiveThreshold fastcv_hal_adaptiveThreshold + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief Calculate medianBlur filter +/// @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 depth Depths of source and destination image +/// @param cn Number of channels +/// @param ksize Size of kernel +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_medianBlur( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int depth, + int cn, + int ksize); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// @brief Computes Sobel derivatives +/// +/// @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 src_depth Depth of source image +/// @param dst_depth Depths of destination image +/// @param cn Number of channels +/// @param margin_left Left margins for source image +/// @param margin_top Top margins for source image +/// @param margin_right Right margins for source image +/// @param margin_bottom Bottom margins for source image +/// @param dx orders of the derivative x +/// @param dy orders of the derivative y +/// @param ksize Size of kernel +/// @param scale Scale factor for the computed derivative values +/// @param delta Delta value that is added to the results prior to storing them in dst +/// @param border_type Border type +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_sobel( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int src_depth, + int dst_depth, + int cn, + int margin_left, + int margin_top, + int margin_right, + int margin_bottom, + int dx, + int dy, + int ksize, + double scale, + 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( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int src_depth, + int dst_depth, + int cn, + int margin_left, + int margin_top, + int margin_right, + int margin_bottom, + size_t ksize_width, + size_t ksize_height, + int anchor_x, + int anchor_y, + bool normalize, + int border_type); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int fastcv_hal_adaptiveThreshold( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + double maxValue, + int adaptiveMethod, + int thresholdType, + int blockSize, + double C); + +#endif diff --git a/3rdparty/fastcv/include/fastcv_hal_utils.hpp b/3rdparty/fastcv/include/fastcv_hal_utils.hpp new file mode 100644 index 0000000000..781e3cb5f6 --- /dev/null +++ b/3rdparty/fastcv/include/fastcv_hal_utils.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#ifndef OPENCV_FASTCV_HAL_UTILS_HPP_INCLUDED +#define OPENCV_FASTCV_HAL_UTILS_HPP_INCLUDED + +#include "fastcv.h" +#include + +#define INITIALIZATION_CHECK \ +{ \ + if (!FastCvContext::getContext().isInitialized) \ + { \ + return CV_HAL_ERROR_UNKNOWN; \ + } \ +} + +#define CV_HAL_RETURN(status, func) \ +{ \ + if( status == FASTCV_SUCCESS ) \ + { \ + CV_LOG_DEBUG(NULL, "FastCV HAL for "<<#func<<" run successfully!"); \ + return CV_HAL_ERROR_OK; \ + } \ + else if(status == FASTCV_EBADPARAM || status == FASTCV_EUNALIGNPARAM || \ + status == FASTCV_EUNSUPPORTED || status == FASTCV_EHWQDSP || \ + status == FASTCV_EHWGPU) \ + { \ + CV_LOG_DEBUG(NULL, "FastCV status:"< +#include + + +class ParallelTableLookup : public cv::ParallelLoopBody +{ +public: + + ParallelTableLookup(const uchar* src_data_, int width_, size_t src_step_, const uchar* lut_data_, uchar* dst_data_, size_t dst_step_) : + cv::ParallelLoopBody(), src_data(src_data_), width(width_), src_step(src_step_), lut_data(lut_data_), dst_data(dst_data_), dst_step(dst_step_) + { + } + + virtual void operator()(const cv::Range& range) const CV_OVERRIDE + { + fcvStatus status = FASTCV_SUCCESS; + for (int y = range.start; y < range.end; y++) { + status = fcvTableLookupu8((uint8_t*)src_data + y * src_step, width, 1, src_step, (uint8_t*)lut_data, (uint8_t*)dst_data + y * dst_step, dst_step); + if(status != FASTCV_SUCCESS) + CV_LOG_ERROR(NULL,"FastCV error:"< +#include + + +int fastcv_hal_medianBlur( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int depth, + int cn, + int ksize) +{ + // Do not support inplace case + if (src_data == dst_data) + CV_HAL_RETURN_NOT_IMPLEMENTED("Inplace is not supported"); + + // The input image width and height should greater than kernel size + if ((height <= ksize) || (width <= ksize)) + CV_HAL_RETURN_NOT_IMPLEMENTED("Input image size should be larger than kernel size"); + + // The input channel should be 1 + if (cn != 1) + CV_HAL_RETURN_NOT_IMPLEMENTED("Multi-channels is not supported"); + + INITIALIZATION_CHECK; + + fcvStatus status; + int fcvFuncType = FCV_MAKETYPE(ksize,depth); + + switch (fcvFuncType) + { + case FCV_MAKETYPE(3,CV_8U): + { + status = fcvFilterMedian3x3u8_v3(src_data, width, height, src_step, dst_data, dst_step, + fcvBorderType::FASTCV_BORDER_REPLICATE, 0); + break; + } + default: + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Ksize:%d, depth:%s is not supported", ksize, cv::depthToString(depth))); + } + + CV_HAL_RETURN(status, hal_medianBlur); +} + +int fastcv_hal_sobel( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int src_depth, + int dst_depth, + int cn, + int margin_left, + int margin_top, + int margin_right, + int margin_bottom, + int dx, + int dy, + int ksize, + double scale, + double delta, + int border_type) +{ + + if(scale != 1.0f || delta != 0.0f) + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Scale:%f, delta:%f is not supported", scale, delta)); + + // Do not support inplace case + if (src_data == dst_data) + CV_HAL_RETURN_NOT_IMPLEMENTED("Inplace is not supported"); + + // The input image width and height should greater than kernel size + if ((height <= ksize) || (width <= ksize)) + CV_HAL_RETURN_NOT_IMPLEMENTED("Input image size should be larger than kernel size"); + + // The input channel should be 1 + if (cn != 1) + CV_HAL_RETURN_NOT_IMPLEMENTED("Multi-channels is not supported"); + + // Do not support for ROI case + if((margin_left!=0) || (margin_top != 0) || (margin_right != 0) || (margin_bottom !=0)) + CV_HAL_RETURN_NOT_IMPLEMENTED("ROI is not supported"); + + // 1. When ksize <= 0, OpenCV will use Scharr Derivatives + // 2. When ksize == 1, OpenCV will use 3×1 or 1×3 kernel(no Gaussian smoothing is done) + // FastCV doesn't support above two situation + if (ksize <= 1) + CV_HAL_RETURN_NOT_IMPLEMENTED("Scharr derivatives or non square kernel are not supported"); + + // Only support the result type is CV_16S + if (dst_depth != CV_16S) + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Dst depth:%s is not supported", cv::depthToString(dst_depth))); + + INITIALIZATION_CHECK; + + // Only support one direction derivatives and the order is 1.(dx=1 && dy=0)||(dx=0 && dy=1) + int16_t *dxBuffer, *dyBuffer; + + if ((dx == 1) && (dy == 0)) + { + dxBuffer = (int16_t*)dst_data; + dyBuffer = NULL; + } + else if ((dx == 0) && (dy == 1)) + { + dxBuffer = NULL; + dyBuffer = (int16_t*)dst_data; + } + else + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Dx:%d Dy:%d is not supported",dx, dy)); + + fcvStatus status; + fcvBorderType fcvBorder; + + switch (border_type) + { + // For constant border, there are no border value, OpenCV default value is 0 + case cv::BorderTypes::BORDER_CONSTANT: + { + fcvBorder = fcvBorderType::FASTCV_BORDER_CONSTANT; + break; + } + case cv::BorderTypes::BORDER_REPLICATE: + { + fcvBorder = fcvBorderType::FASTCV_BORDER_REPLICATE; + break; + } + default: + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Border type:%s is not supported", borderToString(border_type))); + } + + int fcvFuncType = FCV_MAKETYPE(ksize,src_depth); + + switch (fcvFuncType) + { + case FCV_MAKETYPE(3,CV_8U): + { + status = fcvFilterSobel3x3u8s16(src_data, width, height, src_step, dxBuffer, dyBuffer, dst_step, fcvBorder, 0); + break; + } + case FCV_MAKETYPE(5,CV_8U): + { + status = fcvFilterSobel5x5u8s16(src_data, width, height, src_step, dxBuffer, dyBuffer, dst_step, fcvBorder, 0); + break; + } + case FCV_MAKETYPE(7,CV_8U): + { + status = fcvFilterSobel7x7u8s16(src_data, width, height, src_step, dxBuffer, dyBuffer, dst_step, fcvBorder, 0); + break; + } + default: + CV_HAL_RETURN_NOT_IMPLEMENTED(cv::format("Ksize:%d, src_depth:%s, border type:%s is not supported", + ksize, cv::depthToString(src_depth), borderToString(border_type))); + } + + CV_HAL_RETURN(status, hal_sobel); +} + +int fastcv_hal_boxFilter( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + int src_depth, + int dst_depth, + int cn, + int margin_left, + int margin_top, + int margin_right, + int margin_bottom, + size_t ksize_width, + size_t ksize_height, + int anchor_x, + int anchor_y, + bool normalize, + int border_type) +{ + if((width*height) < (320*240)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("input size not supported"); + } + else if(src_data == dst_data) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("in-place processing not supported"); + } + else if(src_depth != CV_8U || cn != 1) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("src type not supported"); + } + else if(dst_depth != src_depth) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("same src and dst type supported"); + } + else if(ksize_width != ksize_height || + (ksize_width != 3 && ksize_width != 5)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("kernel size not supported"); + } + else if(anchor_x != -1 || anchor_y != -1 || + margin_left != 0 || margin_top != 0 || + margin_right != 0 || margin_bottom != 0) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("ROI not supported"); + } + + INITIALIZATION_CHECK; + + fcvBorderType bdr; + uint8_t bdrVal = 0; + 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"); + } + + fcvStatus status = FASTCV_SUCCESS; + if(ksize_width == 3) + { + status = fcvBoxFilter3x3u8_v3(src_data, width, height, src_step, + dst_data, dst_step, normalize, bdr, bdrVal); + } + else if(ksize_width == 5) + { + status = fcvBoxFilter5x5u8_v2(src_data, width, height, src_step, + dst_data, dst_step, normalize, bdr, bdrVal); + } + + CV_HAL_RETURN(status,hal_boxFilter); +} + +int fastcv_hal_adaptiveThreshold( + const uchar* src_data, + size_t src_step, + uchar* dst_data, + size_t dst_step, + int width, + int height, + double maxValue, + int adaptiveMethod, + int thresholdType, + int blockSize, + double C) +{ + if((width*height) < (320*240)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("input size not supported"); + } + else if (src_data == dst_data) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("In place processing not supported"); + } + + int value = (thresholdType == cv::THRESH_BINARY) ? cvCeil(C) : cvFloor(C); + + if ((maxValue < 1) || (maxValue > 255)) + { + CV_HAL_RETURN_NOT_IMPLEMENTED("max value 1-255 supported"); + } + + INITIALIZATION_CHECK; + + uchar maxVal = cv::saturate_cast(maxValue); + + fcvThreshType threshType = (thresholdType == cv::THRESH_BINARY) ? FCV_THRESH_BINARY : FCV_THRESH_BINARY_INV; + + fcvStatus status = FASTCV_SUCCESS; + if(adaptiveMethod == cv::ADAPTIVE_THRESH_GAUSSIAN_C) + { + if(blockSize == 3) + status = fcvAdaptiveThresholdGaussian3x3u8_v2(src_data, width, height, src_step, maxVal, threshType, value, dst_data, dst_step); + else if(blockSize == 5) + status = fcvAdaptiveThresholdGaussian5x5u8_v2(src_data, width, height, src_step, maxVal, threshType, value, dst_data, dst_step); + else + { + CV_HAL_RETURN_NOT_IMPLEMENTED("block size not supported"); + } + } + else if(adaptiveMethod == cv::ADAPTIVE_THRESH_MEAN_C) + { + if(blockSize == 3) + status = fcvAdaptiveThresholdMean3x3u8_v2(src_data, width, height, src_step, maxVal, threshType, value, dst_data, dst_step); + else if(blockSize == 5) + status = fcvAdaptiveThresholdMean5x5u8_v2(src_data, width, height, src_step, maxVal, threshType, value, dst_data, dst_step); + else + { + CV_HAL_RETURN_NOT_IMPLEMENTED("block size not supported"); + } + } + else + { + CV_HAL_RETURN_NOT_IMPLEMENTED("adaptive method not supported"); + } + + CV_HAL_RETURN(status,hal_adaptiveThreshold); +} diff --git a/3rdparty/fastcv/src/fastcv_hal_utils.cpp b/3rdparty/fastcv/src/fastcv_hal_utils.cpp new file mode 100644 index 0000000000..23fc6e2439 --- /dev/null +++ b/3rdparty/fastcv/src/fastcv_hal_utils.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 +*/ + +#include "fastcv_hal_utils.hpp" + +const char* getFastCVErrorString(int status) +{ + switch(status) + { + case FASTCV_SUCCESS: return "Successful"; + case FASTCV_EFAIL: return "General failure"; + case FASTCV_EUNALIGNPARAM: return "Unaligned pointer parameter"; + case FASTCV_EBADPARAM: return "Bad parameters"; + case FASTCV_EINVALSTATE: return "Called at invalid state"; + case FASTCV_ENORES: return "Insufficient resources, memory, thread, etc"; + case FASTCV_EUNSUPPORTED: return "Unsupported feature"; + case FASTCV_EHWQDSP: return "Hardware QDSP failed to respond"; + case FASTCV_EHWGPU: return "Hardware GPU failed to respond"; + default: return "Unknown FastCV Error"; + } +} + +const char* borderToString(int border) +{ + switch (border) + { + case 0: return "BORDER_CONSTANT"; + case 1: return "BORDER_REPLICATE"; + case 2: return "BORDER_REFLECT"; + case 3: return "BORDER_WRAP"; + case 4: return "BORDER_REFLECT_101"; + case 5: return "BORDER_TRANSPARENT"; + default: return "Unknown border type"; + } +} + +const char* interpolationToString(int interpolation) +{ + switch (interpolation) + { + case 0: return "INTER_NEAREST"; + case 1: return "INTER_LINEAR"; + case 2: return "INTER_CUBIC"; + case 3: return "INTER_AREA"; + case 4: return "INTER_LANCZOS4"; + case 5: return "INTER_LINEAR_EXACT"; + case 6: return "INTER_NEAREST_EXACT"; + case 7: return "INTER_MAX"; + case 8: return "WARP_FILL_OUTLIERS"; + case 16: return "WARP_INVERSE_MAP"; + case 32: return "WARP_RELATIVE_MAP"; + default: return "Unknown interpolation type"; + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3520e92e06..2be9a87a9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,6 +233,8 @@ OCV_OPTION(WITH_NDSRVP "Use Andes RVP extension" (NOT CV_DISABLE_OPTIMIZATION) VISIBLE_IF RISCV) OCV_OPTION(WITH_HAL_RVV "Use HAL RVV optimizations" (NOT CV_DISABLE_OPTIMIZATION) VISIBLE_IF RISCV) +OCV_OPTION(WITH_FASTCV "Use Qualcomm FastCV acceleration library for ARM platform" OFF + VISIBLE_IF ((ARM OR AARCH64) AND (ANDROID OR (UNIX AND NOT APPLE AND NOT IOS AND NOT XROS)))) OCV_OPTION(WITH_CPUFEATURES "Use cpufeatures Android library" ON VISIBLE_IF ANDROID VERIFY HAVE_CPUFEATURES) @@ -935,6 +937,13 @@ if(HAVE_OPENVX) endif() endif() +if(HAVE_FASTCV) + ocv_debug_message(STATUS "Enable FastCV acceleration") + if(NOT ";${OpenCV_HAL};" MATCHES ";fastcv;") + set(OpenCV_HAL "fastcv;${OpenCV_HAL}") + endif() +endif() + if(HAVE_KLEIDICV) ocv_debug_message(STATUS "Enable KleidiCV acceleration") if(NOT ";${OpenCV_HAL};" MATCHES ";kleidicv;") @@ -972,6 +981,14 @@ foreach(hal ${OpenCV_HAL}) else() message(STATUS "Carotene: NEON is not available, disabling carotene...") endif() + elseif(hal STREQUAL "fastcv") + if((ARM OR AARCH64) AND (ANDROID OR (UNIX AND NOT APPLE AND NOT IOS AND NOT XROS))) + add_subdirectory(3rdparty/fastcv) + ocv_hal_register(FASTCV_HAL_LIBRARIES FASTCV_HAL_HEADERS FASTCV_HAL_INCLUDE_DIRS) + list(APPEND OpenCV_USED_HAL "fastcv (ver ${FASTCV_HAL_VERSION})") + else() + message(STATUS "FastCV: fastcv is not available, disabling fastcv...") + endif() elseif(hal STREQUAL "kleidicv") add_subdirectory(3rdparty/kleidicv) ocv_hal_register(KLEIDICV_HAL_LIBRARIES KLEIDICV_HAL_HEADERS KLEIDICV_HAL_INCLUDE_DIRS) @@ -1793,6 +1810,9 @@ endif() if(WITH_OPENVX OR HAVE_OPENVX) status(" OpenVX:" HAVE_OPENVX THEN "YES (${OPENVX_LIBRARIES})" ELSE "NO") endif() +if(WITH_FASTCV OR HAVE_FASTCV) + status(" FastCV:" HAVE_FASTCV THEN "YES (${FASTCV_LIBRARY})" ELSE "NO") +endif() status(" Custom HAL:" OpenCV_USED_HAL THEN "YES (${OpenCV_USED_HAL})" ELSE "NO") diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index c2bff4fb1c..4459e2e2e5 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -176,3 +176,23 @@ if(WITH_KLEIDICV) endif() endif() endif(WITH_KLEIDICV) + +# --- FastCV --- +if(WITH_FASTCV) + if((EXISTS ${FastCV_INCLUDE_PATH}) AND (EXISTS ${FastCV_LIB_PATH})) + set(HAVE_FASTCV TRUE CACHE BOOL "FastCV status") + else() + include("${OpenCV_SOURCE_DIR}/3rdparty/fastcv/fastcv.cmake") + set(FCV_ROOT_DIR "${OpenCV_BINARY_DIR}/3rdparty/fastcv") + download_fastcv(${FCV_ROOT_DIR}) + if (HAVE_FASTCV) + set(FastCV_INCLUDE_PATH "${FCV_ROOT_DIR}/inc" CACHE PATH "FastCV includes directory") + set(FastCV_LIB_PATH "${FCV_ROOT_DIR}/libs" CACHE PATH "FastCV library directory") + else() + set(HAVE_FASTCV FALSE CACHE BOOL "FastCV status") + endif() + if (HAVE_FASTCV) + set(FASTCV_LIBRARY "${FastCV_LIB_PATH}/libfastcvopt.so" CACHE PATH "FastCV library") + endif() +endif() +endif(WITH_FASTCV)