vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
message(STATUS "HAVE_FASTCV status ${HAVE_FASTCV}")
|
||||
if(HAVE_FASTCV)
|
||||
set(the_description "Qualcomm FastCV accelerated functions")
|
||||
ocv_define_module(fastcv opencv_core opencv_geometry opencv_imgproc opencv_features opencv_video WRAP python java)
|
||||
ocv_module_include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
${FastCV_INCLUDE_PATH})
|
||||
|
||||
ocv_target_link_libraries(${the_module} ${FASTCV_LIBRARY})
|
||||
ocv_target_compile_definitions(${the_module} PRIVATE -DHAVE_FASTCV=1)
|
||||
ocv_install_3rdparty_licenses(FastCV "${OpenCV_BINARY_DIR}/3rdparty/fastcv/LICENSE")
|
||||
else()
|
||||
ocv_module_disable(fastcv)
|
||||
endif()
|
||||
@@ -0,0 +1,6 @@
|
||||
FastCV extension for OpenCV
|
||||
===========================
|
||||
|
||||
This module provides wrappers for several FastCV functions not covered by the corresponding HAL in OpenCV or have implementation incompatible with OpenCV.
|
||||
Please note that:
|
||||
1. This module supports ARM architecture only. This means that CMake script will not configure or build under x86 platform.
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HPP
|
||||
#define OPENCV_FASTCV_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "opencv2/fastcv/arithm.hpp"
|
||||
#include "opencv2/fastcv/bilateralFilter.hpp"
|
||||
#include "opencv2/fastcv/blur.hpp"
|
||||
#include "opencv2/fastcv/channel.hpp"
|
||||
#include "opencv2/fastcv/cluster.hpp"
|
||||
#include "opencv2/fastcv/draw.hpp"
|
||||
#include "opencv2/fastcv/edges.hpp"
|
||||
#include "opencv2/fastcv/fast10.hpp"
|
||||
#include "opencv2/fastcv/fft.hpp"
|
||||
#include "opencv2/fastcv/histogram.hpp"
|
||||
#include "opencv2/fastcv/hough.hpp"
|
||||
#include "opencv2/fastcv/ipptransform.hpp"
|
||||
#include "opencv2/fastcv/moments.hpp"
|
||||
#include "opencv2/fastcv/mser.hpp"
|
||||
#include "opencv2/fastcv/pyramid.hpp"
|
||||
#include "opencv2/fastcv/remap.hpp"
|
||||
#include "opencv2/fastcv/scale.hpp"
|
||||
#include "opencv2/fastcv/shift.hpp"
|
||||
#include "opencv2/fastcv/smooth.hpp"
|
||||
#include "opencv2/fastcv/thresh.hpp"
|
||||
#include "opencv2/fastcv/tracking.hpp"
|
||||
#include "opencv2/fastcv/warp.hpp"
|
||||
#include "opencv2/fastcv/allocator.hpp"
|
||||
#include "opencv2/fastcv/dsp_init.hpp"
|
||||
#include "opencv2/fastcv/sad_dsp.hpp"
|
||||
#include "opencv2/fastcv/thresh_dsp.hpp"
|
||||
#include "opencv2/fastcv/fft_dsp.hpp"
|
||||
#include "opencv2/fastcv/edges_dsp.hpp"
|
||||
#include "opencv2/fastcv/blur_dsp.hpp"
|
||||
#include "opencv2/fastcv/color.hpp"
|
||||
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
* @{
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // OPENCV_FASTCV_HPP
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_ALLOCATOR_HPP
|
||||
#define OPENCV_FASTCV_ALLOCATOR_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Resource manager for FastCV allocations.
|
||||
* This class manages active allocations.
|
||||
*/
|
||||
class QcResourceManager {
|
||||
public:
|
||||
static QcResourceManager& getInstance();
|
||||
|
||||
void addAllocation(void* ptr);
|
||||
void removeAllocation(void* ptr);
|
||||
|
||||
private:
|
||||
QcResourceManager() = default;
|
||||
std::set<void*> activeAllocations;
|
||||
std::mutex resourceMutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Qualcomm's custom allocator.
|
||||
* This allocator uses Qualcomm's memory management functions.
|
||||
*
|
||||
* Note: The userdata field of cv::UMatData is used to store the file descriptor (fd) of the allocated memory.
|
||||
*
|
||||
*/
|
||||
class QcAllocator : public cv::MatAllocator {
|
||||
public:
|
||||
QcAllocator();
|
||||
~QcAllocator();
|
||||
|
||||
cv::UMatData* allocate(int dims, const int* sizes, int type, void* data0, size_t* step, cv::AccessFlag flags, cv::UMatUsageFlags usageFlags) const CV_OVERRIDE;
|
||||
bool allocate(cv::UMatData* u, cv::AccessFlag accessFlags, cv::UMatUsageFlags usageFlags) const CV_OVERRIDE;
|
||||
void deallocate(cv::UMatData* u) const CV_OVERRIDE;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Gets the default Qualcomm's allocator.
|
||||
* This function returns a pointer to the default Qualcomm's allocator, which is optimized
|
||||
* for use with DSP.
|
||||
*
|
||||
* @return Pointer to the default FastCV allocator.
|
||||
*/
|
||||
CV_EXPORTS cv::MatAllocator* getQcAllocator();
|
||||
|
||||
//! @}
|
||||
|
||||
} // namespace fastcv
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_FASTCV_ALLOCATOR_HPP
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_ARITHM_HPP
|
||||
#define OPENCV_FASTCV_ARITHM_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#define FCV_CMP_EQ(val1,val2) (fabs(val1 - val2) < FLT_EPSILON)
|
||||
|
||||
#define FCV_OPTYPE(depth,op) ((depth<<3) + op)
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Matrix multiplication of two int8_t type matrices
|
||||
* uses signed integer input/output whereas cv::gemm uses floating point input/output
|
||||
* matmuls8s32 provides enhanced speed on Qualcomm's processors
|
||||
* @param src1 First source matrix of type CV_8S
|
||||
* @param src2 Second source matrix of type CV_8S
|
||||
* @param dst Resulting matrix of type CV_32S
|
||||
*/
|
||||
CV_EXPORTS_W void matmuls8s32(InputArray src1, InputArray src2, OutputArray dst);
|
||||
|
||||
//! @}
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Arithmetic add and subtract operations for two matrices
|
||||
* It is optimized for Qualcomm's processors
|
||||
* @param src1 First source matrix, can be of type CV_8U, CV_16S, CV_32F.
|
||||
* Note: CV_32F not supported for subtract
|
||||
* @param src2 Second source matrix of same type and size as src1
|
||||
* @param dst Resulting matrix of type as src mats
|
||||
* @param op type of operation - 0 for add and 1 for subtract
|
||||
*/
|
||||
CV_EXPORTS_W void arithmetic_op(InputArray src1, InputArray src2, OutputArray dst, int op);
|
||||
|
||||
//! @}
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Matrix multiplication of two float type matrices
|
||||
* R = a*A*B + b*C where A,B,C,R are matrices and a,b are constants
|
||||
* It is optimized for Qualcomm's processors
|
||||
* @param src1 First source matrix of type CV_32F
|
||||
* @param src2 Second source matrix of type CV_32F with same rows as src1 cols
|
||||
* @param dst Resulting matrix of type CV_32F
|
||||
* @param alpha multiplying factor for src1 and src2
|
||||
* @param src3 Optional third matrix of type CV_32F to be added to matrix product
|
||||
* @param beta multiplying factor for src3
|
||||
*/
|
||||
CV_EXPORTS_W void gemm(InputArray src1, InputArray src2, OutputArray dst, float alpha = 1.0,
|
||||
InputArray src3 = noArray(), float beta = 0.0);
|
||||
|
||||
//! @}
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Integral of a YCbCr420 image.
|
||||
* Note: Input height should be multiple of 2. Input width and stride should be multiple of 16.
|
||||
* Output stride should be multiple of 8.
|
||||
* It is optimized for Qualcomm's processors
|
||||
* @param Y Input Y component of 8UC1 YCbCr420 image.
|
||||
* @param CbCr Input CbCr component(interleaved) of 8UC1 YCbCr420 image.
|
||||
* @param IY Output Y integral of CV_32S one channel, size (Y height + 1)*(Y width + 1)
|
||||
* @param ICb Output Cb integral of CV_32S one channel, size (Y height/2 + 1)*(Y width/2 + 1)
|
||||
* @param ICr Output Cr integral of CV_32S one channel, size (Y height/2 + 1)*(Y width/2 + 1)
|
||||
*/
|
||||
CV_EXPORTS_W void integrateYUV(InputArray Y, InputArray CbCr, OutputArray IY, OutputArray ICb, OutputArray ICr);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_ARITHM_HPP
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_BILATERALFILTER_HPP
|
||||
#define OPENCV_FASTCV_BILATERALFILTER_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Applies Bilateral filter to an image considering d-pixel diameter of each pixel's neighborhood.
|
||||
This filter does not work inplace.
|
||||
|
||||
* @param _src Intput image with type CV_8UC1
|
||||
* @param _dst Destination image with same type as _src
|
||||
* @param d kernel size (can be 5, 7 or 9)
|
||||
* @param sigmaColor Filter sigma in the color space.
|
||||
Typical value is 50.0f.
|
||||
Increasing this value means increasing the influence of the neighboring pixels of more different color to the smoothing result.
|
||||
* @param sigmaSpace Filter sigma in the coordinate space.
|
||||
Typical value is 1.0f.
|
||||
Increasing this value means increasing the influence of farther neighboring pixels within the kernel size distance to the smoothing result.
|
||||
* @param borderType border mode used to extrapolate pixels outside of the image
|
||||
*/
|
||||
CV_EXPORTS_W void bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
float sigmaColor, float sigmaSpace,
|
||||
int borderType = BORDER_DEFAULT );
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_BILATERALFILTER_HPP
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_BLUR_HPP
|
||||
#define OPENCV_FASTCV_BLUR_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
*/
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Gaussian blur with sigma = 0 and square kernel size. The way of handling borders is different with cv::GaussianBlur,
|
||||
* leading to slight variations in the output.
|
||||
* @param _src Intput image with type CV_8UC1
|
||||
* @param _dst Output image with type CV_8UC1
|
||||
* @param kernel_size Filer kernel size. One of 3, 5, 11
|
||||
* @param blur_border If set to true, border is blurred by 0-padding adjacent values.(A variant of the constant border)
|
||||
* If set to false, borders up to half-kernel width are ignored (e.g. 1 pixel in the 3x3 case).
|
||||
*
|
||||
* @sa GaussianBlur
|
||||
*/
|
||||
CV_EXPORTS_W void gaussianBlur(InputArray _src, OutputArray _dst, int kernel_size = 3, bool blur_border = true);
|
||||
|
||||
/**
|
||||
* @brief NxN correlation with non-separable kernel. Borders up to half-kernel width are ignored
|
||||
* @param _src Intput image with type CV_8UC1
|
||||
* @param _dst Output image with type CV_8UC1, CV_16SC1 or CV_32FC1
|
||||
* @param ddepth The depth of output image
|
||||
* @param _kernel Filer kernel data
|
||||
*
|
||||
* @sa Filter2D
|
||||
*/
|
||||
CV_EXPORTS_W void filter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel);
|
||||
|
||||
/**
|
||||
* @brief NxN correlation with separable kernel. If srcImg and dstImg point to the same address and srcStride equals to dstStride,
|
||||
* it will do in-place. Borders up to half-kernel width are ignored.
|
||||
* The way of handling overflow is different with OpenCV, this function will do right shift for
|
||||
* the intermediate results and final result.
|
||||
* @param _src Intput image with type CV_8UC1
|
||||
* @param _dst Output image with type CV_8UC1, CV_16SC1
|
||||
* @param ddepth The depth of output image
|
||||
* @param _kernelX Filer kernel data in x direction
|
||||
* @param _kernelY Filer kernel data in Y direction (For CV_16SC1, the kernelX and kernelY should be same)
|
||||
*
|
||||
* @sa sepFilter2D
|
||||
*/
|
||||
CV_EXPORTS_W void sepFilter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY);
|
||||
//! @}
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Calculates the local subtractive and contrastive normalization of the image.
|
||||
* Each pixel of the image is normalized by the mean and standard deviation of the patch centred at the pixel.
|
||||
* It is optimized for Qualcomm's processors.
|
||||
* @param _src Input image, should have one channel CV_8U or CV_32F
|
||||
* @param _dst Output array, should be one channel, CV_8S if src of type CV_8U, or CV_32F if src of CV_32F
|
||||
* @param pSize Patch size for mean and std dev calculation
|
||||
* @param useStdDev If 1, bot mean and std dev will be used for normalization, if 0, only mean used
|
||||
*/
|
||||
CV_EXPORTS_W void normalizeLocalBox(InputArray _src, OutputArray _dst, Size pSize, bool useStdDev);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_BLUR_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_BLUR_DSP_HPP
|
||||
#define OPENCV_FASTCV_BLUR_DSP_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Filter an image with non-separable kernel
|
||||
* @param _src Intput image with type CV_8UC1, src size should be greater than 176*144
|
||||
* @param _dst Output image with type CV_8UC1, CV_16SC1 or CV_32FC1
|
||||
* @param ddepth The depth of output image
|
||||
* @param _kernel Filer kernel data
|
||||
*/
|
||||
CV_EXPORTS void filter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel);
|
||||
|
||||
//! @}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_BLUR_DSP_HPP
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_CHANNEL_HPP
|
||||
#define OPENCV_FASTCV_CHANNEL_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Creates one multi-channel mat out of several single-channel CV_8U mats.
|
||||
* Optimized for Qualcomm's processors
|
||||
* @param mv input vector of matrices to be merged; all the matrices in mv must be of CV_8UC1 and have the same size
|
||||
* Note: numbers of mats can be 2,3 or 4.
|
||||
* @param dst output array of depth CV_8U and same size as mv[0]; The number of channels
|
||||
* will be the total number of matrices in the matrix array
|
||||
*/
|
||||
CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst);
|
||||
|
||||
//! @}
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Splits an CV_8U multi-channel mat into several CV_8UC1 mats
|
||||
* Optimized for Qualcomm's processors
|
||||
* @param src input 2,3 or 4 channel mat of depth CV_8U
|
||||
* @param mv output vector of size src.channels() of CV_8UC1 mats
|
||||
*/
|
||||
CV_EXPORTS_W void split(InputArray src, OutputArrayOfArrays mv);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_CHANNEL_HPP
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_CLUSTER_HPP
|
||||
#define OPENCV_FASTCV_CLUSTER_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Clusterizes N input points in D-dimensional space into K clusters
|
||||
* Accepts 8-bit unsigned integer points
|
||||
* Provides faster execution time than cv::kmeans on Qualcomm's processors
|
||||
* @param points Points array of type 8u, each row represets a point.
|
||||
* Size is N rows by D columns, can be non-continuous.
|
||||
* @param clusterCenters Initial cluster centers array of type 32f, each row represents a center.
|
||||
* Size is K rows by D columns, can be non-continuous.
|
||||
* @param newClusterCenters Resulting cluster centers array of type 32f, each row represents found center.
|
||||
* Size is set to be K rows by D columns.
|
||||
* @param clusterSizes Resulting cluster member counts array of type uint32, size is set to be 1 row by K columns.
|
||||
* @param clusterBindings Resulting points indices array of type uint32, each index tells to which cluster the corresponding point belongs to.
|
||||
* Size is set to be 1 row by numPointsUsed columns.
|
||||
* @param clusterSumDists Resulting distance sums array of type 32f, each number is a sum of distances between each cluster center to its belonging points.
|
||||
* Size is set to be 1 row by K columns
|
||||
* @param numPointsUsed Number of points to clusterize starting from 0 to numPointsUsed-1 inclusively. Sets to N if negative.
|
||||
*/
|
||||
CV_EXPORTS_W void clusterEuclidean(InputArray points, InputArray clusterCenters, OutputArray newClusterCenters,
|
||||
OutputArray clusterSizes, OutputArray clusterBindings, OutputArray clusterSumDists,
|
||||
int numPointsUsed = -1);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_CLUSTER_HPP
|
||||
@@ -0,0 +1,43 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
|
||||
#ifndef OPENCV_FASTCV_COLOR_HPP
|
||||
#define OPENCV_FASTCV_COLOR_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace fastcv
|
||||
{
|
||||
|
||||
enum ColorConversionCodes {
|
||||
// FastCV-specific color conversion codes (avoid collision with OpenCV core)
|
||||
COLOR_YUV2YUV444sp_NV12 = 156, //!< FastCV: YCbCr420PseudoPlanar to YCbCr444PseudoPlanar
|
||||
COLOR_YUV2YUV422sp_NV12 = 157, //!< FastCV: YCbCr420PseudoPlanar to YCbCr422PseudoPlanar
|
||||
COLOR_YUV422sp2YUV444sp = 158, //!< FastCV: YCbCr422PseudoPlanar to YCbCr444PseudoPlanar
|
||||
COLOR_YUV422sp2YUV_NV12 = 159, //!< FastCV: YCbCr422PseudoPlanar to YCbCr420PseudoPlanar
|
||||
COLOR_YUV444sp2YUV422sp = 160, //!< FastCV: YCbCr444PseudoPlanar to YCbCr422PseudoPlanar
|
||||
COLOR_YUV444sp2YUV_NV12 = 161, //!< FastCV: YCbCr444PseudoPlanar to YCbCr420PseudoPlanar
|
||||
COLOR_YUV2RGB565_NV12 = 162, //!< FastCV: YCbCr420PseudoPlanar to RGB565
|
||||
COLOR_YUV422sp2RGB565 = 163, //!< FastCV: YCbCr422PseudoPlanar to RGB565
|
||||
COLOR_YUV422sp2RGB = 164, //!< FastCV: YCbCr422PseudoPlanar to RGB888
|
||||
COLOR_YUV422sp2RGBA = 165, //!< FastCV: YCbCr422PseudoPlanar to RGBA8888
|
||||
COLOR_YUV444sp2RGB565 = 166, //!< FastCV: YCbCr444PseudoPlanar to RGB565
|
||||
COLOR_YUV444sp2RGB = 167, //!< FastCV: YCbCr444PseudoPlanar to RGB888
|
||||
COLOR_YUV444sp2RGBA = 168, //!< FastCV: YCbCr444PseudoPlanar to RGBA8888
|
||||
COLOR_RGB2YUV_NV12 = 169, //!< FastCV: RGB888 to YCbCr420PseudoPlanar
|
||||
COLOR_RGB5652YUV444sp = 170, //!< FastCV: RGB565 to YCbCr444PseudoPlanar
|
||||
COLOR_RGB5652YUV422sp = 171, //!< FastCV: RGB565 to YCbCr422PseudoPlanar
|
||||
COLOR_RGB5652YUV_NV12 = 172, //!< FastCV: RGB565 to YCbCr420PseudoPlanar
|
||||
COLOR_RGB2YUV444sp = 173, //!< FastCV: RGB888 to YCbCr444PseudoPlanar
|
||||
COLOR_RGB2YUV422sp = 174, //!< FastCV: RGB888 to YCbCr422PseudoPlanar
|
||||
};
|
||||
|
||||
CV_EXPORTS_W void cvtColor(InputArray src, OutputArray dst, int code);
|
||||
|
||||
}}; //cv::fastcv namespace end
|
||||
|
||||
#endif // OPENCV_FASTCV_COLOR_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_DRAW_HPP
|
||||
#define OPENCV_FASTCV_DRAW_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Draw convex polygon
|
||||
This function fills the interior of a convex polygon with the specified color.
|
||||
Requires the width and stride to be multple of 8.
|
||||
* @param img Image to draw on. Should have up to 4 8-bit channels
|
||||
* @param pts Array of polygon points coordinates. Should contain N two-channel or 2*N one-channel 32-bit integer elements
|
||||
* @param color Color of drawn polygon stored as B,G,R and A(if supported)
|
||||
*/
|
||||
CV_EXPORTS_W void fillConvexPoly(InputOutputArray img, InputArray pts, Scalar color);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_DRAW_HPP
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_DSP_INIT_HPP
|
||||
#define OPENCV_FASTCV_DSP_INIT_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Initializes the FastCV DSP environment.
|
||||
*
|
||||
* This function sets up the necessary environment and resources for the DSP to operate.
|
||||
* It must be called once at the very beginning of the use case or program to ensure that
|
||||
* the DSP is properly initialized before any DSP-related operations are performed.
|
||||
*
|
||||
* @note This function must be called at the start of the use case or program, before any
|
||||
* DSP-related operations.
|
||||
*
|
||||
* @return int Returns 0 on success, and a non-zero value on failure.
|
||||
*/
|
||||
CV_EXPORTS int fcvdspinit();
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the FastCV DSP environment.
|
||||
*
|
||||
* This function releases the resources and environment set up by the 'fcvdspinit' function.
|
||||
* It should be called before the use case or program exits to ensure that all DSP resources
|
||||
* are properly cleaned up and no memory leaks occur.
|
||||
*
|
||||
* @note This function must be called at the end of the use case or program, after all DSP-related
|
||||
* operations are complete.
|
||||
*/
|
||||
CV_EXPORTS void fcvdspdeinit();
|
||||
//! @}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_DSP_INIT_HPP
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_EDGES_HPP
|
||||
#define OPENCV_EDGES_HPP
|
||||
|
||||
#include "opencv2/core/mat.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
*/
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Creates a 2D gradient image from source luminance data without normalization.
|
||||
* Calculate X direction 1 order derivative or Y direction 1 order derivative or both at the same time, .
|
||||
* @param _src Input image with type CV_8UC1
|
||||
* @param _dx Buffer to store horizontal gradient. Must be (dxyStride)*(height) bytes in size.
|
||||
* If NULL, the horizontal gradient will not be calculated.
|
||||
* @param _dy Buffer to store vertical gradient. Must be (dxyStride)*(height) bytes in size.
|
||||
* If NULL, the vertical gradient will not be calculated
|
||||
* @param kernel_size Sobel kernel size, support 3x3, 5x5, 7x7
|
||||
* @param borderType Border type, support BORDER_CONSTANT, BORDER_REPLICATE
|
||||
* @param borderValue Border value for constant border
|
||||
*/
|
||||
CV_EXPORTS_W void sobel(InputArray _src, OutputArray _dx, OutputArray _dy, int kernel_size, int borderType, int borderValue);
|
||||
|
||||
/**
|
||||
* @brief Creates a 2D gradient image from source luminance data without normalization.
|
||||
* This function computes central differences on 3x3 neighborhood and then convolves the result with Sobel kernel,
|
||||
* borders up to half-kernel width are ignored.
|
||||
* @param _src Input image with type CV_8UC1
|
||||
* @param _dst If _dsty is given, buffer to store horizontal gradient, otherwise, output 8-bit image of |dx|+|dy|.
|
||||
* Size of buffer is (srcwidth)*(srcheight) bytes
|
||||
* @param _dsty (Optional)Buffer to store vertical gradient. Must be (srcwidth)*(srcheight) in size.
|
||||
* @param ddepth The depth of output image CV_8SC1,CV_16SC1,CV_32FC1,
|
||||
* @param normalization If do normalization for the result
|
||||
*/
|
||||
CV_EXPORTS_W void sobel3x3u8(InputArray _src, OutputArray _dst, OutputArray _dsty = noArray(), int ddepth = CV_8U,
|
||||
bool normalization = false);
|
||||
|
||||
//! @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_EDGES_DSP_HPP
|
||||
#define OPENCV_FASTCV_EDGES_DSP_HPP
|
||||
|
||||
#include "opencv2/core/mat.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
*/
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Canny edge detector applied to a 8 bit grayscale image
|
||||
* @param _src Input image with type CV_8UC1
|
||||
* @param _dst Output 8-bit image containing the edge detection results
|
||||
* @param lowThreshold First threshold
|
||||
* @param highThreshold Second threshold
|
||||
* @param apertureSize The Sobel kernel size for calculating gradient. Supported sizes are 3, 5 and 7.
|
||||
* @param L2gradient L2 Gradient or L1 Gradient
|
||||
*/
|
||||
CV_EXPORTS void Canny(InputArray _src, OutputArray _dst, int lowThreshold, int highThreshold, int apertureSize = 3, bool L2gradient = false);
|
||||
//! @}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif //OPENCV_FASTCV_EDGES_DSP_HPP
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_FAST10_HPP
|
||||
#define OPENCV_FASTCV_FAST10_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Extracts FAST10 corners and scores from the image based on the mask.
|
||||
* The mask specifies pixels to be ignored by the detector
|
||||
* designed for corner detection on Qualcomm's processors, provides enhanced speed.
|
||||
*
|
||||
* @param src 8-bit grayscale image
|
||||
* @param mask Optional mask indicating which pixels should be omited from corner dection.
|
||||
Its size should be k times image width and height, where k = 1/2, 1/4 , 1/8 , 1, 2, 4 and 8
|
||||
For more details see documentation to `fcvCornerFast9InMaskScoreu8` function in FastCV
|
||||
* @param coords Output array of CV_32S containing interleave x, y positions of detected corners
|
||||
* @param scores Optional output array containing the scores of the detected corners.
|
||||
The score is the highest threshold that can still validate the detected corner.
|
||||
A higher score value indicates a stronger corner feature.
|
||||
For example, a corner of score 108 is stronger than a corner of score 50
|
||||
* @param barrier FAST threshold. The threshold is used to compare difference between intensity value
|
||||
of the central pixel and pixels on a circle surrounding this pixel
|
||||
* @param border Number for pixels to ignore from top,bottom,right,left of the image. Defaults to 4 if it's below 4
|
||||
* @param nmsEnabled Enable non-maximum suppresion to prune weak key points
|
||||
*/
|
||||
CV_EXPORTS_W void FAST10(InputArray src, InputArray mask, OutputArray coords, OutputArray scores, int barrier, int border, bool nmsEnabled);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_FAST10_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_FFT_HPP
|
||||
#define OPENCV_FASTCV_FFT_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Computes the 1D or 2D Fast Fourier Transform of a real valued matrix.
|
||||
For the 2D case, the width and height of the input and output matrix must be powers of 2.
|
||||
For the 1D case, the height of the matrices must be 1, while the width must be a power of 2.
|
||||
Accepts 8-bit unsigned integer array, whereas cv::dft accepts floating-point or complex array.
|
||||
* @param src Input array of CV_8UC1. The dimensions of the matrix must be powers of 2 for the 2D case,
|
||||
and in the 1D case, the height must be 1, while the width must be a power of 2.
|
||||
* @param dst The computed FFT matrix of type CV_32FC2. The FFT Re and Im coefficients are stored in different channels.
|
||||
Hence the dimensions of the dst are (srcWidth, srcHeight)
|
||||
*/
|
||||
CV_EXPORTS_W void FFT(InputArray src, OutputArray dst);
|
||||
|
||||
/**
|
||||
* @brief Computes the 1D or 2D Inverse Fast Fourier Transform of a complex valued matrix.
|
||||
For the 2D case, The width and height of the input and output matrix must be powers of 2.
|
||||
For the 1D case, the height of the matrices must be 1, while the width must be a power of 2.
|
||||
|
||||
* @param src Input array of type CV_32FC2 containing FFT Re and Im coefficients stored in separate channels.
|
||||
The dimensions of the matrix must be powers of 2 for the 2D case, and in the 1D case, the height must be 1,
|
||||
while the width must be a power of 2.
|
||||
* @param dst The computed IFFT matrix of type CV_8U. The matrix is real valued and has no imaginary components.
|
||||
Hence the dimensions of the dst are (srcWidth , srcHeight)
|
||||
*/
|
||||
CV_EXPORTS_W void IFFT(InputArray src, OutputArray dst);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_FFT_HPP
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_FFT_DSP_HPP
|
||||
#define OPENCV_FASTCV_FFT_DSP_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Computes the 1D or 2D Fast Fourier Transform of a real valued matrix.
|
||||
For the 2D case, the width and height of the input and output matrix must be powers of 2.
|
||||
For the 1D case, the height of the matrices must be 1, while the width must be a power of 2.
|
||||
|
||||
* @param src Input array of CV_8UC1. The dimensions of the matrix must be powers of 2 for the 2D case,
|
||||
and in the 1D case, the height must be 1, while the width must be a power of 2.
|
||||
* @param dst The computed FFT matrix of type CV_32FC2. The FFT Re and Im coefficients are stored in different channels.
|
||||
Hence the dimensions of the dst are (srcWidth, srcHeight)
|
||||
*/
|
||||
CV_EXPORTS void FFT(InputArray src, OutputArray dst);
|
||||
|
||||
/**
|
||||
* @brief Computes the 1D or 2D Inverse Fast Fourier Transform of a complex valued matrix.
|
||||
For the 2D case, The width and height of the input and output matrix must be powers of 2.
|
||||
For the 1D case, the height of the matrices must be 1, while the width must be a power of 2.
|
||||
|
||||
* @param src Input array of type CV_32FC2 containing FFT Re and Im coefficients stored in separate channels.
|
||||
The dimensions of the matrix must be powers of 2 for the 2D case, and in the 1D case, the height must be 1,
|
||||
while the width must be a power of 2.
|
||||
* @param dst The computed IFFT matrix of type CV_8U. The matrix is real valued and has no imaginary components.
|
||||
Hence the dimensions of the dst are (srcWidth , srcHeight)
|
||||
*/
|
||||
CV_EXPORTS void IFFT(InputArray src, OutputArray dst);
|
||||
|
||||
//! @}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_FFT_DSP_HPP
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HISTOGRAM_HPP
|
||||
#define OPENCV_FASTCV_HISTOGRAM_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Calculates histogram of input image. This function implements specific use case of
|
||||
* 256-bin histogram calculation for 8u single channel images in an optimized way.
|
||||
* @param _src Intput image with type CV_8UC1
|
||||
* @param _hist Output histogram of type int of 256 bins
|
||||
*/
|
||||
CV_EXPORTS_W void calcHist( InputArray _src, OutputArray _hist );
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_HISTOGRAM_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_HOUGH_HPP
|
||||
#define OPENCV_FASTCV_HOUGH_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Performs Hough Line detection
|
||||
*
|
||||
* @param src Input 8-bit image containing binary contour. Width and step should be divisible by 8
|
||||
* @param lines Output array containing detected lines in a form of (x1, y1, x2, y2) where all numbers are 32-bit floats
|
||||
* @param threshold Controls the minimal length of a detected line. Value must be between 0.0 and 1.0
|
||||
* Values close to 1.0 reduces the number of detected lines. Values close to 0.0
|
||||
* detect more lines, but may be noisy. Recommended value is 0.25.
|
||||
*/
|
||||
CV_EXPORTS_W void houghLines(InputArray src, OutputArray lines, double threshold = 0.25);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_HOUGH_HPP
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_IPPTRANSFORM_HPP
|
||||
#define OPENCV_FASTCV_IPPTRANSFORM_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief This function performs 8x8 forward discrete Cosine transform on input image
|
||||
* accepts input of type 8-bit unsigned integer and produces output of type 16-bit signed integer
|
||||
* provides faster execution time than cv::dct on Qualcomm's processor
|
||||
* @param src Input image of type CV_8UC1
|
||||
* @param dst Output image of type CV_16SC1
|
||||
*/
|
||||
CV_EXPORTS_W void DCT(InputArray src, OutputArray dst);
|
||||
|
||||
/**
|
||||
* @brief This function performs 8x8 inverse discrete Cosine transform on input image
|
||||
* provides faster execution time than cv::dct in inverse case on Qualcomm's processor
|
||||
* @param src Input image of type CV_16SC1
|
||||
* @param dst Output image of type CV_8UC1
|
||||
*/
|
||||
CV_EXPORTS_W void IDCT(InputArray src, OutputArray dst);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_IPPTRANSFORM_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_MOMENTS_HPP
|
||||
#define OPENCV_FASTCV_MOMENTS_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Calculates all of the moments up to the third order of the image pixels' intensities
|
||||
* The results are returned in the structure cv::Moments. This function cv::fastcv::moments()
|
||||
* calculate the moments using floating point calculations whereas cv::moments() calculate moments using double.
|
||||
* @param _src Input image with type CV_8UC1, CV_32SC1, CV_32FC1
|
||||
* @param binary If true, assumes the image to be binary (0x00 for black, 0xff for white), otherwise assumes the image to be
|
||||
* grayscale.
|
||||
*/
|
||||
CV_EXPORTS cv::Moments moments(InputArray _src, bool binary);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_MOMENTS_HPP
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_MSER_HPP
|
||||
#define OPENCV_FASTCV_MSER_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief MSER blob detector for grayscale images
|
||||
*
|
||||
*/
|
||||
class CV_EXPORTS_W FCVMSER
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Structure containing additional information about found contour
|
||||
*
|
||||
*/
|
||||
struct ContourData
|
||||
{
|
||||
uint32_t variation; //!< Variation of a contour from previous grey level
|
||||
int32_t polarity; //!< Polarity for a contour. This value is 1 if this is a MSER+ region, -1 if this is a MSER- region.
|
||||
uint32_t nodeId; //!< Node ID for a contour
|
||||
uint32_t nodeCounter; //!< Node counter for a contour
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates MSER detector
|
||||
*
|
||||
* @param imgSize Image size. Image width has to be greater than 50, and image height has to be greater than 5.
|
||||
* @param numNeighbors Number of neighbors in contours, can be 4 or 8
|
||||
* @param delta Delta to be used in MSER algorithm (the difference in grayscale values
|
||||
within which the region is stable ).
|
||||
Typical value range [0.8 8], typical value 2
|
||||
* @param minArea Minimum area (number of pixels) of a mser contour.
|
||||
Typical value range [10 50], typical value 30
|
||||
* @param maxArea Maximum area (number of pixels) of a mser contour.
|
||||
Typical value 14400 or 0.25*width*height
|
||||
* @param maxVariation Maximum variation in grayscale between 2 levels allowed.
|
||||
Typical value range [0.1 1.0], typical value 0.15
|
||||
* @param minDiversity Minimum diversity in grayscale between 2 levels allowed.
|
||||
Typical value range [0.1 1.0], typical value 0.2
|
||||
* @return Feature detector object ready for detection
|
||||
*/
|
||||
CV_WRAP static Ptr<FCVMSER> create( const cv::Size& imgSize,
|
||||
int numNeighbors = 4,
|
||||
int delta = 2,
|
||||
int minArea = 30,
|
||||
int maxArea = 14400,
|
||||
float maxVariation = 0.15f,
|
||||
float minDiversity = 0.2f);
|
||||
|
||||
/**
|
||||
* @brief This is an overload for detect() function
|
||||
*
|
||||
* @param src Source image of type CV_8UC1. Image width has to be greater than 50, and image height has to be greater than 5.
|
||||
Pixels at the image boundary are not processed. If boundary pixels are important
|
||||
for a particular application, please consider padding the input image with dummy
|
||||
pixels of one pixel wide.
|
||||
* @param contours Array containing found contours
|
||||
*/
|
||||
CV_WRAP virtual void detect(InputArray src, std::vector<std::vector<Point>>& contours) = 0;
|
||||
|
||||
/**
|
||||
* @brief This is an overload for detect() function
|
||||
*
|
||||
* @param src Source image of type CV_8UC1. Image width has to be greater than 50, and image height has to be greater than 5.
|
||||
Pixels at the image boundary are not processed. If boundary pixels are important
|
||||
for a particular application, please consider padding the input image with dummy
|
||||
pixels of one pixel wide.
|
||||
* @param contours Array containing found contours
|
||||
* @param boundingBoxes Array containing bounding boxes of found contours
|
||||
*/
|
||||
CV_WRAP virtual void detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes) = 0;
|
||||
|
||||
/**
|
||||
* @brief Runs MSER blob detector on the grayscale image
|
||||
*
|
||||
* @param src Source image of type CV_8UC1. Image width has to be greater than 50, and image height has to be greater than 5.
|
||||
Pixels at the image boundary are not processed. If boundary pixels are important
|
||||
for a particular application, please consider padding the input image with dummy
|
||||
pixels of one pixel wide.
|
||||
* @param contours Array containing found contours
|
||||
* @param boundingBoxes Array containing bounding boxes of found contours
|
||||
* @param contourData Array containing additional information about found contours
|
||||
*/
|
||||
virtual void detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes,
|
||||
std::vector<ContourData>& contourData) = 0;
|
||||
|
||||
CV_WRAP virtual cv::Size getImgSize() = 0;
|
||||
CV_WRAP virtual int getNumNeighbors() = 0;
|
||||
CV_WRAP virtual int getDelta() = 0;
|
||||
CV_WRAP virtual int getMinArea() = 0;
|
||||
CV_WRAP virtual int getMaxArea() = 0;
|
||||
CV_WRAP virtual float getMaxVariation() = 0;
|
||||
CV_WRAP virtual float getMinDiversity() = 0;
|
||||
|
||||
virtual ~FCVMSER() {}
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_MSER_HPP
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_PYRAMID_HPP
|
||||
#define OPENCV_FASTCV_PYRAMID_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Creates a gradient pyramid from an image pyramid
|
||||
* Note: The borders are ignored during gradient calculation.
|
||||
* @param pyr Input pyramid of 1-channel 8-bit images. Only continuous images are supported.
|
||||
* @param dx Horizontal Sobel gradient pyramid of the same size as pyr
|
||||
* @param dy Verical Sobel gradient pyramid of the same size as pyr
|
||||
* @param outType Type of output data, can be CV_8S, CV_16S or CV_32F
|
||||
*/
|
||||
CV_EXPORTS_W void sobelPyramid(InputArrayOfArrays pyr, OutputArrayOfArrays dx, OutputArrayOfArrays dy, int outType = CV_8S);
|
||||
|
||||
/**
|
||||
* @brief Builds an image pyramid of float32 arising from a single
|
||||
original image - that are successively downscaled w.r.t. the
|
||||
pre-set levels. This API supports both ORB scaling and scale down by half.
|
||||
*
|
||||
* @param src Input single-channel image of type 8U or 32F
|
||||
* @param pyr Output array containing nLevels downscaled image copies
|
||||
* @param nLevels Number of pyramid levels to produce
|
||||
* @param scaleBy2 to scale images 2x down or by a factor of 1/(2)^(1/4) which is approximated as 0.8408964 (ORB downscaling),
|
||||
* ORB scaling is not supported for float point images
|
||||
* @param borderType how to process border, the options are BORDER_REFLECT (maps to FASTCV_BORDER_REFLECT),
|
||||
* BORDER_REFLECT_101 (maps to FASTCV_BORDER_REFLECT_V2) and BORDER_REPLICATE (maps to FASTCV_BORDER_REPLICATE).
|
||||
* Other border types are mapped to FASTCV_BORDER_UNDEFINED(border pixels are ignored). Currently, borders only
|
||||
* supported for downscaling by half, ignored for ORB scaling. Also ignored for float point images
|
||||
* @param borderValue what value should be used to fill border, ignored for float point images
|
||||
*/
|
||||
CV_EXPORTS_W void buildPyramid(InputArray src, OutputArrayOfArrays pyr, int nLevels, bool scaleBy2 = true,
|
||||
int borderType = cv::BORDER_REFLECT, uint8_t borderValue = 0);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_PYRAMID_HPP
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_REMAP_HPP
|
||||
#define OPENCV_FASTCV_REMAP_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Applies a generic geometrical transformation to a greyscale CV_8UC1 image.
|
||||
* @param src The first input image data, type CV_8UC1
|
||||
* @param dst The output image data, type CV_8UC1
|
||||
* @param map1 Floating-point CV_32FC1 matrix with each element as the column coordinate of the mapped location in the source image
|
||||
* @param map2 Floating-point CV_32FC1 matrix with each element as the row coordinate of the mapped location in the source image.
|
||||
* @param interpolation Only INTER_NEAREST and INTER_LINEAR interpolation is supported
|
||||
* @param borderValue constant pixel value
|
||||
*/
|
||||
CV_EXPORTS_W void remap( InputArray src, OutputArray dst,
|
||||
InputArray map1, InputArray map2,
|
||||
int interpolation, int borderValue=0);
|
||||
|
||||
/**
|
||||
* @brief Applies a generic geometrical transformation to a 4-channel CV_8UC4 image with bilinear or nearest neighbor interpolation
|
||||
* @param src The first input image data, type CV_8UC4
|
||||
* @param dst The output image data, type CV_8UC4
|
||||
* @param map1 Floating-point CV_32FC1 matrix with each element as the column coordinate of the mapped location in the source image
|
||||
* @param map2 Floating-point CV_32FC1 matrix with each element as the row coordinate of the mapped location in the source image.
|
||||
* @param interpolation Only INTER_NEAREST and INTER_LINEAR interpolation is supported
|
||||
*/
|
||||
CV_EXPORTS_W void remapRGBA( InputArray src, OutputArray dst,
|
||||
InputArray map1, InputArray map2, int interpolation);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_REMAP_HPP
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_SAD_HPP
|
||||
#define OPENCV_FASTCV_SAD_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
*/
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
/**
|
||||
* @brief Sum of absolute differences of an image against an 8x8 template.
|
||||
* @param _patch The first input image data, type CV_8UC1
|
||||
* @param _src The input image data, type CV_8UC1
|
||||
* @param _dst The output image data, type CV_16UC1
|
||||
*/
|
||||
CV_EXPORTS void sumOfAbsoluteDiffs(cv::InputArray _patch, cv::InputArray _src, cv::OutputArray _dst);
|
||||
//! @}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_SAD_HPP
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_SCALE_HPP
|
||||
#define OPENCV_FASTCV_SCALE_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Down-scales the image using specified scaling factors or dimensions.
|
||||
* This function supports both single-channel (CV_8UC1) and two-channel (CV_8UC2) images.
|
||||
*
|
||||
* @param _src The input image data, type CV_8UC1 or CV_8UC2.
|
||||
* @param _dst The output image data, type CV_8UC1 or CV_8UC2.
|
||||
* @param dsize The desired size of the output image. If empty, it is calculated using inv_scale_x and inv_scale_y.
|
||||
* @param inv_scale_x The inverse scaling factor for the width. If dsize is provided, this parameter is ignored.
|
||||
* @param inv_scale_y The inverse scaling factor for the height. If dsize is provided, this parameter is ignored.
|
||||
*
|
||||
* @note If dsize is not specified, inv_scale_x and inv_scale_y must be strictly positive.
|
||||
*/
|
||||
CV_EXPORTS_W void resizeDown(cv::InputArray _src, cv::OutputArray _dst, Size dsize, double inv_scale_x, double inv_scale_y);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_SCALE_HPP
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_SHIFT_HPP
|
||||
#define OPENCV_FASTCV_SHIFT_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Applies the meanshift procedure and obtains the final converged position.
|
||||
This function applies the meanshift procedure to an original image (usually a probability image)
|
||||
and obtains the final converged position. The converged position search will stop either it has reached
|
||||
the required accuracy or the maximum number of iterations. Moments used in the algorithm are calculated
|
||||
in floating point.
|
||||
This function isn't bit-exact with cv::meanShift but provides improved latency on Snapdragon processors.
|
||||
|
||||
* @param src 8-bit, 32-bit int or 32-bit float grayscale image which is usually a probability image
|
||||
* computed based on object histogram
|
||||
* @param rect Initial search window position which also returns the final converged window position
|
||||
* @param termCrit The criteria used to finish the MeanShift which consists of two termination criteria:
|
||||
* 1) epsilon: required accuracy; 2) max_iter: maximum number of iterations
|
||||
* @return Iteration number at which the loop stopped
|
||||
*/
|
||||
CV_EXPORTS_W int meanShift(InputArray src, Rect& rect, TermCriteria termCrit);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_SHIFT_HPP
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_SMOOTH_HPP
|
||||
#define OPENCV_FASTCV_SMOOTH_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Recursive Bilateral Filtering
|
||||
|
||||
Different from traditional bilateral filtering, here the smoothing is actually performed in gradient domain.
|
||||
The algorithm claims that it's more efficient than the original bilateral filtering in both image quality and computation.
|
||||
See algorithm description in the paper Recursive Bilateral Filtering, ECCV2012 by Prof Yang Qingxiong
|
||||
This function isn't bit-exact with cv::bilateralFilter but provides improved latency on Snapdragon processors.
|
||||
* @param src Input image, should have one CV_8U channel
|
||||
* @param dst Output array having one CV_8U channel
|
||||
* @param sigmaColor Sigma in the color space, the bigger the value the more color difference is smoothed by the algorithm
|
||||
* @param sigmaSpace Sigma in the coordinate space, the bigger the value the more distant pixels are smoothed
|
||||
*/
|
||||
CV_EXPORTS_W void bilateralRecursive(cv::InputArray src, cv::OutputArray dst, float sigmaColor = 0.03f, float sigmaSpace = 0.1f);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_SMOOTH_HPP
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_THRESH_HPP
|
||||
#define OPENCV_FASTCV_THRESH_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Binarizes a grayscale image based on a pair of threshold values. The binarized image will be in the two values
|
||||
* selected by user
|
||||
* this function provides improved latency on Snapdragon processor.
|
||||
* @param src 8-bit grayscale image
|
||||
* @param dst Output image of the same size and type as input image, can be the same as input image
|
||||
* @param lowThresh The lower threshold value for binarization
|
||||
* @param highThresh The higher threshold value for binarization
|
||||
* @param trueValue The value assigned to the destination pixel if the source is within the range inclusively defined by the
|
||||
* pair of threshold values
|
||||
* @param falseValue The value assigned to the destination pixel if the source is out of the range inclusively defined by the
|
||||
* pair of threshold values
|
||||
*/
|
||||
CV_EXPORTS_W void thresholdRange(InputArray src, OutputArray dst, int lowThresh, int highThresh, int trueValue, int falseValue);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_THRESH_HPP
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_THRESH_DSP_HPP
|
||||
#define OPENCV_FASTCV_THRESH_DSP_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Binarizes a grayscale image using Otsu's method.
|
||||
* Sets the pixel to max(255) if it's value is greater than the threshold;
|
||||
* else, set the pixel to min(0). The threshold is searched that minimizes
|
||||
* the intra-class variance (the variance within the class).
|
||||
*
|
||||
* @param _src Input 8-bit grayscale image. Size of buffer is srcStride*srcHeight bytes.
|
||||
* @param _dst Output 8-bit binarized image. Size of buffer is dstStride*srcHeight bytes.
|
||||
* @param type Threshold type that can be either 0 or 1.
|
||||
* NOTE: For threshold type=0, the pixel is set as
|
||||
* maxValue if it's value is greater than the threshold; else, it is set as zero.
|
||||
* For threshold type=1, the pixel is set as zero if it's
|
||||
* value is greater than the threshold; else, it is set as maxValue.
|
||||
*/
|
||||
CV_EXPORTS void thresholdOtsu(InputArray _src, OutputArray _dst, bool type);
|
||||
|
||||
//! @}
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_THRESH_DSP_HPP
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_TRACKING_HPP
|
||||
#define OPENCV_FASTCV_TRACKING_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Calculates sparse optical flow using Lucas-Kanade algorithm
|
||||
* accepts 8-bit unsigned integer image
|
||||
* Provides faster execution time on Qualcomm's processor
|
||||
* @param src Input single-channel image of type 8U, initial motion frame
|
||||
* @param dst Input single-channel image of type 8U, final motion frame, should have the same size and stride as initial frame
|
||||
* @param srcPyr Pyramid built from intial motion frame
|
||||
* @param dstPyr Pyramid built from final motion frame
|
||||
* @param ptsIn Array of initial subpixel coordinates of starting points, should contain 32F 2D elements
|
||||
* @param ptsOut Output array of calculated final points, should contain 32F 2D elements
|
||||
* @param ptsEst Input array of estimations for final points, should contain 32F 2D elements, can be empty
|
||||
* @param statusVec Output array of int32 values indicating status of each feature, can be empty
|
||||
* @param winSize Size of window for optical flow searching. Width and height ust be odd numbers. Suggested values are 5, 7 or 9
|
||||
* @param termCriteria Termination criteria containing max number of iterations, max epsilon and stop condition
|
||||
*/
|
||||
CV_EXPORTS_W void trackOpticalFlowLK(InputArray src, InputArray dst,
|
||||
InputArrayOfArrays srcPyr, InputArrayOfArrays dstPyr,
|
||||
InputArray ptsIn, OutputArray ptsOut, InputArray ptsEst,
|
||||
OutputArray statusVec, cv::Size winSize = cv::Size(7, 7),
|
||||
cv::TermCriteria termCriteria = cv::TermCriteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,
|
||||
/* maxIterations */ 7, /* maxEpsilon */ 0.03f * 0.03f));
|
||||
|
||||
/**
|
||||
* @brief Overload for v1 of the LK tracking function
|
||||
*
|
||||
* @param src Input single-channel image of type 8U, initial motion frame
|
||||
* @param dst Input single-channel image of type 8U, final motion frame, should have the same size and stride as initial frame
|
||||
* @param srcPyr Pyramid built from intial motion frame
|
||||
* @param dstPyr Pyramid built from final motion frame
|
||||
* @param srcDxPyr Pyramid of Sobel derivative by X of srcPyr
|
||||
* @param srcDyPyr Pyramid of Sobel derivative by Y of srcPyr
|
||||
* @param ptsIn Array of initial subpixel coordinates of starting points, should contain 32F 2D elements
|
||||
* @param ptsOut Output array of calculated final points, should contain 32F 2D elements
|
||||
* @param statusVec Output array of int32 values indicating status of each feature, can be empty
|
||||
* @param winSize Size of window for optical flow searching. Width and height ust be odd numbers. Suggested values are 5, 7 or 9
|
||||
* @param maxIterations Maximum number of iterations to try
|
||||
*/
|
||||
CV_EXPORTS_W void trackOpticalFlowLK(InputArray src, InputArray dst,
|
||||
InputArrayOfArrays srcPyr, InputArrayOfArrays dstPyr,
|
||||
InputArrayOfArrays srcDxPyr, InputArrayOfArrays srcDyPyr,
|
||||
InputArray ptsIn, OutputArray ptsOut,
|
||||
OutputArray statusVec, cv::Size winSize = cv::Size(7, 7), int maxIterations = 7);
|
||||
|
||||
//! @}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
|
||||
#endif // OPENCV_FASTCV_TRACKING_HPP
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_WARP_HPP
|
||||
#define OPENCV_WARP_HPP
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
/**
|
||||
* @defgroup fastcv Module-wrapper for FastCV hardware accelerated functions
|
||||
*/
|
||||
|
||||
//! @addtogroup fastcv
|
||||
//! @{
|
||||
|
||||
/**
|
||||
* @brief Transform an image using perspective transformation, same as cv::warpPerspective but not bit-exact.
|
||||
* @param _src Input 8-bit image.
|
||||
* @param _dst Output 8-bit image.
|
||||
* @param _M0 3x3 perspective transformation matrix.
|
||||
* @param dsize Size of the output image.
|
||||
* @param interpolation Interpolation method. Only cv::INTER_NEAREST, cv::INTER_LINEAR and cv::INTER_AREA are supported.
|
||||
* @param borderType Pixel extrapolation method. Only cv::BORDER_CONSTANT, cv::BORDER_REPLICATE and cv::BORDER_TRANSPARENT
|
||||
* are supported.
|
||||
* @param borderValue Value used in case of a constant border.
|
||||
*/
|
||||
CV_EXPORTS_W void warpPerspective(InputArray _src, OutputArray _dst, InputArray _M0, Size dsize, int interpolation, int borderType,
|
||||
const Scalar& borderValue);
|
||||
|
||||
/**
|
||||
* @brief Perspective warp two images using the same transformation. Bi-linear interpolation is used where applicable.
|
||||
* For example, to warp a grayscale image and an alpha image at the same time, or warp two color channels.
|
||||
* @param _src1 First input 8-bit image. Size of buffer is src1Stride*srcHeight bytes.
|
||||
* @param _src2 Second input 8-bit image. Size of buffer is src2Stride*srcHeight bytes.
|
||||
* @param _dst1 First warped output image (correspond to src1). Size of buffer is dst1Stride*dstHeight bytes, type CV_8UC1
|
||||
* @param _dst2 Second warped output image (correspond to src2). Size of buffer is dst2Stride*dstHeight bytes, type CV_8UC1
|
||||
* @param _M0 The 3x3 perspective transformation matrix (inversed map)
|
||||
* @param dsize The output image size
|
||||
*/
|
||||
CV_EXPORTS_W void warpPerspective2Plane(InputArray _src1, InputArray _src2, OutputArray _dst1, OutputArray _dst2,
|
||||
InputArray _M0, Size dsize);
|
||||
|
||||
/**
|
||||
* @brief Performs an affine transformation on an input image using a provided transformation matrix.
|
||||
*
|
||||
* This function performs two types of operations based on the transformation matrix:
|
||||
*
|
||||
* 1. Standard Affine Transformation (2x3 matrix):
|
||||
* - Transforms the entire input image using the affine matrix
|
||||
* - Supports both CV_8UC1 and CV_8UC3 types
|
||||
*
|
||||
* 2. Patch Extraction with Transformation (2x2 matrix):
|
||||
* - Extracts and transforms a patch from the input image
|
||||
* - Only supports CV_8UC1 type
|
||||
* - If input is a ROI: patch is extracted from ROI center in the original image
|
||||
* - If input is full image: patch is extracted from image center
|
||||
*
|
||||
* @param _src Input image. Supported formats:
|
||||
* - CV_8UC1: 8-bit single-channel
|
||||
* - CV_8UC3: 8-bit three-channel - only for 2x3 matrix
|
||||
* @param _dst Output image. Will have the same type as src and size specified by dsize
|
||||
* @param _M 2x2/2x3 affine transformation matrix (inversed map)
|
||||
* @param dsize Output size:
|
||||
* - For 2x3 matrix: Size of the output image
|
||||
* - For 2x2 matrix: Size of the extracted patch
|
||||
* @param interpolation Interpolation method. Only applicable for 2x3 transformation with CV_8UC1 input.
|
||||
* Options:
|
||||
* - INTER_NEAREST: Nearest-neighbor interpolation
|
||||
* - INTER_LINEAR: Bilinear interpolation (default)
|
||||
* - INTER_AREA: Area-based interpolation
|
||||
* - INTER_CUBIC: Bicubic interpolation
|
||||
* Note: CV_8UC3 input always use bicubic interpolation internally
|
||||
* @param borderValue Constant pixel value for border pixels. Only applicable for 2x3 transformations
|
||||
* with single-channel input.
|
||||
*
|
||||
* @note The affine matrix follows the inverse mapping convention, applied to destination coordinates
|
||||
* to produce corresponding source coordinates.
|
||||
* @note The function uses 'FASTCV_BORDER_CONSTANT' for border handling, with the specified 'borderValue'.
|
||||
*/
|
||||
CV_EXPORTS_W void warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size dsize, int interpolation = INTER_LINEAR,
|
||||
int borderValue = 0);
|
||||
|
||||
//! @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int>> IntegrateYUVPerfTest;
|
||||
|
||||
PERF_TEST_P(IntegrateYUVPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8U) // image depth
|
||||
)
|
||||
)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
|
||||
cv::Mat Y(srcSize, depth), CbCr(srcSize.height/2, srcSize.width, depth);
|
||||
cv::Mat IY, ICb, ICr;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, Y, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, CbCr, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
TEST_CYCLE() cv::fastcv::integrateYUV(Y, CbCr, IY, ICb, ICr);
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<float /*sigmaColor*/, float /*sigmaSpace*/> BilateralRecursivePerfParams;
|
||||
typedef perf::TestBaseWithParam<BilateralRecursivePerfParams> BilateralRecursivePerfTest;
|
||||
|
||||
PERF_TEST_P(BilateralRecursivePerfTest, run,
|
||||
::testing::Combine(::testing::Values(0.01f, 0.03f, 0.1f, 1.f, 5.f),
|
||||
::testing::Values(0.01f, 0.05f, 0.1f, 1.f, 5.f))
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
float sigmaColor = std::get<0>(p);
|
||||
float sigmaSpace = std::get<1>(p);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
Mat dst;
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::bilateralRecursive(src, dst, sigmaColor, sigmaSpace);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
typedef std::tuple<float /*sigmaColor*/, float /*sigmaSpace*/, cv::Size, int > BilateralPerfParams;
|
||||
typedef perf::TestBaseWithParam<BilateralPerfParams> BilateralPerfTest;
|
||||
|
||||
|
||||
PERF_TEST_P(BilateralPerfTest, run,
|
||||
::testing::Combine(::testing::Values(0.01f, 0.03f, 0.1f, 1.f, 5.f),
|
||||
::testing::Values(0.01f, 0.05f, 0.1f, 1.f, 5.f),
|
||||
::testing::Values(Size(8, 8), Size(640, 480), Size(800, 600)),
|
||||
::testing::Values(5, 7, 9))
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
float sigmaColor = std::get<0>(p);
|
||||
float sigmaSpace = std::get<1>(p);
|
||||
cv::Size size = std::get<2>(p);
|
||||
int d = get<3>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
Mat dst;
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::bilateralFilter(src, dst, d, sigmaColor, sigmaSpace);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int, bool>> GaussianBlurPerfTest;
|
||||
|
||||
PERF_TEST_P(GaussianBlurPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8U,CV_16S,CV_32S), // image depth
|
||||
::testing::Values(3, 5), // kernel size
|
||||
::testing::Values(true,false) // blur border
|
||||
)
|
||||
)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
bool border = get<3>(GetParam());
|
||||
|
||||
// For some cases FastCV not support, so skip them
|
||||
if((ksize!=5) && (depth!=CV_8U))
|
||||
throw ::perf::TestBase::PerfSkipTestException();
|
||||
|
||||
cv::Mat src(srcSize, depth);
|
||||
cv::Mat dst;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::gaussianBlur(src, dst, ksize, border);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int>> Filter2DPerfTest;
|
||||
|
||||
PERF_TEST_P(Filter2DPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8U,CV_16S,CV_32F), // dst image depth
|
||||
::testing::Values(3, 5, 7, 9, 11) // kernel size
|
||||
)
|
||||
)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
|
||||
cv::Mat src(srcSize, CV_8U);
|
||||
cv::Mat kernel;
|
||||
cv::Mat dst;
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
case CV_16S:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_8S);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_32F);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cv::randu(src, 0, 256);
|
||||
cv::randu(kernel, INT8_MIN, INT8_MAX);
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::filter2D(src, dst, ddepth, kernel);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int>> SepFilter2DPerfTest;
|
||||
|
||||
PERF_TEST_P(SepFilter2DPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8U,CV_16S), // dst image depth
|
||||
::testing::Values(3, 5, 7, 9, 11, 13, 15, 17) // kernel size
|
||||
)
|
||||
)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
|
||||
cv::Mat src(srcSize, ddepth);
|
||||
cv::Mat kernel(1, ksize, ddepth);
|
||||
cv::Mat dst;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, kernel, Scalar::all(INT8_MIN), Scalar::all(INT8_MAX));
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::sepFilter2D(src, dst, ddepth, kernel, kernel);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, Size, int>> NormalizeLocalBoxPerfTest;
|
||||
|
||||
PERF_TEST_P(NormalizeLocalBoxPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8U,CV_32F), // src image depth
|
||||
::testing::Values(Size(3,3),Size(5,5)), // patch size
|
||||
::testing::Values(0,1) // use std dev or not
|
||||
)
|
||||
)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
Size sz = get<2>(GetParam());
|
||||
bool useStdDev = get<3>(GetParam());
|
||||
|
||||
cv::Mat src(srcSize, depth);
|
||||
cv::Mat dst;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
TEST_CYCLE() cv::fastcv::normalizeLocalBox(src, dst, sz, useStdDev);
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int>> Filter2DPerfTest_DSP;
|
||||
|
||||
PERF_TEST_P(Filter2DPerfTest_DSP, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p), // image size
|
||||
::testing::Values(CV_8U,CV_16S,CV_32F), // dst image depth
|
||||
::testing::Values(3, 5, 7) // kernel size
|
||||
)
|
||||
)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
|
||||
cv::Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(srcSize, CV_8U);
|
||||
|
||||
cv::Mat kernel;
|
||||
cv::Mat dst;
|
||||
kernel.allocator = cv::fastcv::getQcAllocator();
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
case CV_16S:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_8S);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_32F);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cv::randu(src, 0, 256);
|
||||
cv::randu(kernel, INT8_MIN, INT8_MAX);
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::filter2D(src, dst, ddepth, kernel);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<int /* nPts */, int /*nDims*/, int /*nClusters*/> ClusterEuclideanPerfParams;
|
||||
typedef perf::TestBaseWithParam<ClusterEuclideanPerfParams> ClusterEuclideanPerfTest;
|
||||
|
||||
PERF_TEST_P(ClusterEuclideanPerfTest, run,
|
||||
::testing::Combine(::testing::Values(100, 1000, 10000), // nPts
|
||||
::testing::Values(2, 10, 32), // nDims
|
||||
::testing::Values(5, 10, 16)) // nClusters
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
int nPts = std::get<0>(p);
|
||||
int nDims = std::get<1>(p);
|
||||
int nClusters = std::get<2>(p);
|
||||
|
||||
Mat points(nPts, nDims, CV_8U);
|
||||
Mat clusterCenters(nClusters, nDims, CV_32F);
|
||||
|
||||
Mat trueMeans(nClusters, nDims, CV_32F);
|
||||
Mat stddevs(nClusters, nDims, CV_32F);
|
||||
std::vector<int> trueClusterSizes(nClusters, 0);
|
||||
std::vector<int> trueClusterBindings(nPts, 0);
|
||||
std::vector<float> trueSumDists(nClusters, 0);
|
||||
|
||||
cv::RNG& rng = cv::theRNG();
|
||||
for (int i = 0; i < nClusters; i++)
|
||||
{
|
||||
Mat mean(1, nDims, CV_64F), stdev(1, nDims, CV_64F);
|
||||
rng.fill(mean, cv::RNG::UNIFORM, 0, 256);
|
||||
rng.fill(stdev, cv::RNG::UNIFORM, 5.f, 16);
|
||||
int lo = i * nPts / nClusters;
|
||||
int hi = (i + 1) * nPts / nClusters;
|
||||
|
||||
for (int d = 0; d < nDims; d++)
|
||||
{
|
||||
rng.fill(points.col(d).rowRange(lo, hi), cv::RNG::NORMAL,
|
||||
mean.at<double>(d), stdev.at<double>(d));
|
||||
}
|
||||
|
||||
float sd = 0;
|
||||
for (int j = lo; j < hi; j++)
|
||||
{
|
||||
Mat pts64f;
|
||||
points.row(j).convertTo(pts64f, CV_64F);
|
||||
sd += cv::norm(mean, pts64f, NORM_L2);
|
||||
trueClusterBindings.at(j) = i;
|
||||
trueClusterSizes.at(i)++;
|
||||
}
|
||||
trueSumDists.at(i) = sd;
|
||||
|
||||
// let's shift initial cluster center a bit
|
||||
Mat(mean + stdev * 0.5).copyTo(clusterCenters.row(i));
|
||||
|
||||
mean.copyTo(trueMeans.row(i));
|
||||
stdev.copyTo(stddevs.row(i));
|
||||
}
|
||||
|
||||
while(next())
|
||||
{
|
||||
Mat newClusterCenters;
|
||||
std::vector<int> clusterSizes, clusterBindings;
|
||||
std::vector<float> clusterSumDists;
|
||||
startTimer();
|
||||
cv::fastcv::clusterEuclidean(points, clusterCenters, newClusterCenters, clusterSizes, clusterBindings, clusterSumDists);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int, int>> SobelPerfTest;
|
||||
|
||||
PERF_TEST_P(SobelPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(3,5,7), // kernel size
|
||||
::testing::Values(BORDER_CONSTANT, BORDER_REPLICATE), // border type
|
||||
::testing::Values(0) // border value
|
||||
)
|
||||
)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ksize = get<1>(GetParam());
|
||||
int border = get<2>(GetParam());
|
||||
int borderValue = get<3>(GetParam());
|
||||
|
||||
cv::Mat dx, dy, src(srcSize, CV_8U);
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::sobel(src,dx,dy,ksize,border,borderValue);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int>> Sobel3x3u8PerfTest;
|
||||
|
||||
PERF_TEST_P(Sobel3x3u8PerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(CV_8S, CV_16S, CV_32F), // image depth
|
||||
::testing::Values(0, 1) // normalization
|
||||
)
|
||||
)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int normalization = get<2>(GetParam());
|
||||
|
||||
cv::Mat dx, dy, src(srcSize, CV_8U);
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
if((normalization ==0) && (ddepth == CV_8S))
|
||||
throw ::perf::TestBase::PerfSkipTestException();
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::sobel3x3u8(src, dx, dy, ddepth, normalization);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
} //namespace
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, pair<int, int>, bool>> CannyPerfTest;
|
||||
|
||||
PERF_TEST_P(CannyPerfTest, run,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(3, 5, 7), // aperture size
|
||||
::testing::Values(make_pair(0, 50), make_pair(100, 150), make_pair(50, 150)), // low and high thresholds
|
||||
::testing::Values(false, true) // L2gradient
|
||||
)
|
||||
)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int apertureSize = get<1>(GetParam());
|
||||
auto thresholds = get<2>(GetParam());
|
||||
bool L2gradient = get<3>(GetParam());
|
||||
|
||||
cv::Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(srcSize, CV_8UC1);
|
||||
|
||||
cv::Mat dst;
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
cv::randu(src, 0, 256);
|
||||
|
||||
int lowThreshold = thresholds.first;
|
||||
int highThreshold = thresholds.second;
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::Canny(src, dst, lowThreshold, highThreshold, apertureSize, L2gradient);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} //namespace
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<bool /*useScores*/, int /*barrier*/, int /*border*/, bool /*nmsEnabled*/> FAST10PerfParams;
|
||||
typedef perf::TestBaseWithParam<FAST10PerfParams> FAST10PerfTest;
|
||||
|
||||
PERF_TEST_P(FAST10PerfTest, run,
|
||||
::testing::Combine(::testing::Bool(), // useScores
|
||||
::testing::Values(10, 30, 50), // barrier
|
||||
::testing::Values( 4, 10, 32), // border
|
||||
::testing::Bool() // nonmax suppression
|
||||
)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
bool useScores = std::get<0>(p);
|
||||
int barrier = std::get<1>(p);
|
||||
int border = std::get<2>(p);
|
||||
bool nmsEnabled = std::get<3>(p);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
std::vector<int> coords, scores;
|
||||
while(next())
|
||||
{
|
||||
coords.clear();
|
||||
scores.clear();
|
||||
startTimer();
|
||||
cv::fastcv::FAST10(src, noArray(), coords, useScores ? scores : noArray(), barrier, border, nmsEnabled);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<cv::Size> FFTExtPerfTest;
|
||||
|
||||
PERF_TEST_P_(FFTExtPerfTest, forward)
|
||||
{
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat dst;
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::FFT(src, dst);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(FFTExtPerfTest, inverse)
|
||||
{
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat fwd, back;
|
||||
cv::fastcv::FFT(src, fwd);
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::IFFT(fwd, back);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, FFTExtPerfTest,
|
||||
::testing::Values(Size(8, 8), Size(128, 128), Size(32, 256), Size(512, 512),
|
||||
Size(32, 1), Size(512, 1)));
|
||||
|
||||
/// DCT ///
|
||||
|
||||
typedef perf::TestBaseWithParam<cv::Size> DCTExtPerfTest;
|
||||
|
||||
PERF_TEST_P_(DCTExtPerfTest, forward)
|
||||
{
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat dst, ref;
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::DCT(src, dst);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(DCTExtPerfTest, inverse)
|
||||
{
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat fwd, back;
|
||||
cv::fastcv::DCT(src, fwd);
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::IDCT(fwd, back);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, DCTExtPerfTest,
|
||||
::testing::Values(Size(8, 8), Size(128, 128), Size(32, 256), Size(512, 512)));
|
||||
} // namespace
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<cv::Size> FFT_DSPExtPerfTest;
|
||||
|
||||
PERF_TEST_P_(FFT_DSPExtPerfTest, forward)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
|
||||
Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat dst;
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::FFT(src, dst);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(FFT_DSPExtPerfTest, inverse)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
Size size = GetParam();
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
|
||||
Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(size, CV_8UC1);
|
||||
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat fwd, back;
|
||||
fwd.allocator = cv::fastcv::getQcAllocator();
|
||||
back.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
cv::fastcv::dsp::FFT(src, fwd);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::IFFT(fwd, back);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, FFT_DSPExtPerfTest,
|
||||
::testing::Values(Size(256, 256), Size(512, 512)));
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef tuple<cv::Size /*imgSize*/, int /*nPts*/, int /*channels*/> FillConvexPerfParams;
|
||||
typedef perf::TestBaseWithParam<FillConvexPerfParams> FillConvexPerfTest;
|
||||
|
||||
PERF_TEST_P(FillConvexPerfTest, randomDraw, Combine(
|
||||
testing::Values(Size(640, 480), Size(512, 512), Size(1920, 1080)),
|
||||
testing::Values(4, 64, 1024),
|
||||
testing::Values(1, 2, 3, 4)
|
||||
))
|
||||
{
|
||||
auto p = GetParam();
|
||||
|
||||
Size imgSize = std::get<0>(p);
|
||||
int nPts = std::get<1>(p);
|
||||
int channels = std::get<2>(p);
|
||||
|
||||
cv::RNG rng = cv::theRNG();
|
||||
|
||||
std::vector<Point> allPts, contour;
|
||||
for (int i = 0; i < nPts; i++)
|
||||
{
|
||||
allPts.push_back(Point(rng() % imgSize.width, rng() % imgSize.height));
|
||||
}
|
||||
cv::convexHull(allPts, contour);
|
||||
|
||||
Scalar color(rng() % 256, rng() % 256, rng() % 256);
|
||||
|
||||
Mat img(imgSize, CV_MAKE_TYPE(CV_8U, channels), Scalar(0));
|
||||
|
||||
while(next())
|
||||
{
|
||||
img = 0;
|
||||
startTimer();
|
||||
cv::fastcv::fillConvexPoly(img, contour, color);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P(FillConvexPerfTest, circle, Combine(
|
||||
testing::Values(Size(640, 480), Size(512, 512), Size(1920, 1080)),
|
||||
testing::Values(4, 64, 1024),
|
||||
testing::Values(1, 2, 3, 4)
|
||||
))
|
||||
{
|
||||
auto p = GetParam();
|
||||
|
||||
Size imgSize = std::get<0>(p);
|
||||
int nPts = std::get<1>(p);
|
||||
int channels = std::get<2>(p);
|
||||
|
||||
cv::RNG rng = cv::theRNG();
|
||||
|
||||
float r = std::min(imgSize.width, imgSize.height) / 2 * 0.9f;
|
||||
float angle = CV_PI * 2.0f / (float)nPts;
|
||||
std::vector<Point2i> contour;
|
||||
for (int i = 0; i < nPts; i++)
|
||||
{
|
||||
Point2f pt(r * cos((float)i * angle),
|
||||
r * sin((float)i * angle));
|
||||
contour.push_back({ imgSize.width / 2 + int(pt.x),
|
||||
imgSize.height / 2 + int(pt.y)});
|
||||
}
|
||||
Scalar color(rng() % 256, rng() % 256, rng() % 256);
|
||||
|
||||
Mat img(imgSize, CV_MAKE_TYPE(CV_8U, channels), Scalar(0));
|
||||
|
||||
while(next())
|
||||
{
|
||||
img = 0;
|
||||
startTimer();
|
||||
cv::fastcv::fillConvexPoly(img, contour, color);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<cv::Size> HistogramPerfParams;
|
||||
typedef perf::TestBaseWithParam<HistogramPerfParams> HistogramPerfTest;
|
||||
|
||||
|
||||
PERF_TEST_P(HistogramPerfTest, run,
|
||||
testing::Values(perf::szQVGA, perf::szVGA, perf::sz720p, perf::sz1080p)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
cv::Size size = std::get<0>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
Mat hist(1, 256, CV_32SC1);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::calcHist(src, hist);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<std::string /* file name */, double /* threshold */ > HoughLinesPerfParams;
|
||||
typedef perf::TestBaseWithParam<HoughLinesPerfParams> HoughLinesPerfTest;
|
||||
|
||||
PERF_TEST_P(HoughLinesPerfTest, run,
|
||||
::testing::Combine(::testing::Values("cv/shared/pic5.png",
|
||||
"stitching/a1.png",
|
||||
"cv/shared/pic5.png",
|
||||
"cv/shared/pic1.png"), // images
|
||||
::testing::Values(0.05, 0.25, 0.5, 0.75, 5) // threshold
|
||||
)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
std::string fname = std::get<0>(p);
|
||||
double thrld = std::get<1>(p);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile(fname), cv::IMREAD_GRAYSCALE);
|
||||
// make it aligned by 8
|
||||
cv::Mat withBorder;
|
||||
int bpix = ((src.cols & 0xfffffff8) + 8) - src.cols;
|
||||
cv::copyMakeBorder(src, withBorder, 0, 0, 0, bpix, BORDER_REFLECT101);
|
||||
src = withBorder;
|
||||
|
||||
while(next())
|
||||
{
|
||||
std::vector<cv::Vec4f> lines;
|
||||
startTimer();
|
||||
cv::fastcv::houghLines(src, lines, thrld);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
static void initFastCVTests()
|
||||
{
|
||||
cvtest::registerGlobalSkipTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
}
|
||||
|
||||
CV_PERF_TEST_MAIN(imgproc, initFastCVTests())
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<int /*rows1*/, int /*cols1*/, int /*cols2*/> MatMulPerfParams;
|
||||
typedef perf::TestBaseWithParam<MatMulPerfParams> MatMulPerfTest;
|
||||
|
||||
typedef std::tuple<int /*rows1*/, int /*cols1*/, int /*cols2*/, float> MatMulGemmPerfParams;
|
||||
typedef perf::TestBaseWithParam<MatMulGemmPerfParams> MatMulGemmPerfTest;
|
||||
|
||||
PERF_TEST_P(MatMulPerfTest, run,
|
||||
::testing::Combine(::testing::Values(8, 16, 128, 256), // rows1
|
||||
::testing::Values(8, 16, 128, 256), // cols1
|
||||
::testing::Values(8, 16, 128, 256)) // cols2
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
int rows1 = std::get<0>(p);
|
||||
int cols1 = std::get<1>(p);
|
||||
int cols2 = std::get<2>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src1(rows1, cols1, CV_8SC1), src2(cols1, cols2, CV_8SC1);
|
||||
cvtest::randUni(rng, src1, Scalar::all(-128), Scalar::all(128));
|
||||
cvtest::randUni(rng, src2, Scalar::all(-128), Scalar::all(128));
|
||||
|
||||
Mat dst;
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::matmuls8s32(src1, src2, dst);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P(MatMulGemmPerfTest, run,
|
||||
::testing::Combine(::testing::Values(8, 16, 128, 256), // rows1
|
||||
::testing::Values(8, 16, 128, 256), // cols1
|
||||
::testing::Values(8, 16, 128, 256), // cols2
|
||||
::testing::Values(2.5, 5.8)) // alpha
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
int rows1 = std::get<0>(p);
|
||||
int cols1 = std::get<1>(p);
|
||||
int cols2 = std::get<2>(p);
|
||||
float alpha = std::get<3>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src1(rows1, cols1, CV_32FC1), src2(cols1, cols2, CV_32FC1);
|
||||
cvtest::randUni(rng, src1, Scalar::all(-128.0), Scalar::all(128.0));
|
||||
cvtest::randUni(rng, src2, Scalar::all(-128.0), Scalar::all(128.0));
|
||||
|
||||
Mat dst;
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::gemm(src1, src2, dst, alpha, noArray(), 0);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<cv::Size, MatType, int /*iterations*/, float /*epsilon*/, Size /*winSize*/> MeanShiftPerfParams;
|
||||
typedef perf::TestBaseWithParam<MeanShiftPerfParams> MeanShiftPerfTest;
|
||||
|
||||
PERF_TEST_P(MeanShiftPerfTest, run,
|
||||
::testing::Combine(::testing::Values(Size(128, 128), Size(640, 480), Size(800, 600)),
|
||||
::testing::Values(CV_8U, CV_32S, CV_32F), // type
|
||||
::testing::Values(2, 10, 100), // nIterations
|
||||
::testing::Values(0.01f, 0.1f, 1.f, 10.f), // epsilon
|
||||
::testing::Values(Size(8, 8), Size(13, 48), Size(64, 64)) // window size
|
||||
)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
cv::Size size = std::get<0>(p);
|
||||
MatType type = std::get<1>(p);
|
||||
int iters = std::get<2>(p);
|
||||
float eps = std::get<3>(p);
|
||||
Size winSize = std::get<4>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
|
||||
const int nPts = 20;
|
||||
Mat ptsMap(size, CV_8UC1, Scalar(255));
|
||||
for(size_t i = 0; i < nPts; ++i)
|
||||
{
|
||||
ptsMap.at<uchar>(rng() % size.height, rng() % size.width) = 0;
|
||||
}
|
||||
Mat distTrans(size, CV_8UC1);
|
||||
cv::distanceTransform(ptsMap, distTrans, DIST_L2, DIST_MASK_PRECISE);
|
||||
Mat vsrc = 255 - distTrans;
|
||||
Mat src;
|
||||
vsrc.convertTo(src, type);
|
||||
|
||||
Point startPt(rng() % (size.width - winSize.width),
|
||||
rng() % (size.height - winSize.height));
|
||||
Rect startRect(startPt, winSize);
|
||||
|
||||
cv::TermCriteria termCrit( TermCriteria::EPS + TermCriteria::MAX_ITER, iters, eps);
|
||||
|
||||
Rect window = startRect;
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::meanShift(src, window, termCrit);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
// we use such nested structure to combine test values
|
||||
typedef std::tuple< std::tuple<bool /* useBboxes */, bool /* useContourData */>,
|
||||
int /* numNeighbors */, std::string /*file path*/> MSERPerfParams;
|
||||
typedef perf::TestBaseWithParam<MSERPerfParams> MSERPerfTest;
|
||||
|
||||
PERF_TEST_P(MSERPerfTest, run,
|
||||
::testing::Combine(::testing::Values(std::tuple<bool, bool> { true, false},
|
||||
std::tuple<bool, bool> {false, false},
|
||||
std::tuple<bool, bool> { true, true}
|
||||
), // useBboxes, useContourData
|
||||
::testing::Values(4, 8), // numNeighbors
|
||||
::testing::Values("cv/shared/baboon.png", "cv/mser/puzzle.png")
|
||||
)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
bool useBboxes = std::get<0>(std::get<0>(p));
|
||||
bool useContourData = std::get<1>(std::get<0>(p));
|
||||
int numNeighbors = std::get<1>(p); // 4 or 8
|
||||
std::string imgPath = std::get<2>(p);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile(imgPath), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
uint32_t delta = 2;
|
||||
uint32_t minArea = 256;
|
||||
uint32_t maxArea = (int)src.total()/4;
|
||||
float maxVariation = 0.15f;
|
||||
float minDiversity = 0.2f;
|
||||
|
||||
cv::Ptr<cv::fastcv::FCVMSER> mser;
|
||||
mser = cv::fastcv::FCVMSER::create(src.size(), numNeighbors, delta, minArea, maxArea,
|
||||
maxVariation, minDiversity);
|
||||
|
||||
while(next())
|
||||
{
|
||||
std::vector<std::vector<Point>> contours;
|
||||
std::vector<cv::Rect> bboxes;
|
||||
std::vector<cv::fastcv::FCVMSER::ContourData> contourData;
|
||||
|
||||
startTimer();
|
||||
if (useBboxes)
|
||||
{
|
||||
if (useContourData)
|
||||
{
|
||||
mser->detect(src, contours, bboxes, contourData);
|
||||
}
|
||||
else
|
||||
{
|
||||
mser->detect(src, contours, bboxes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mser->detect(src, contours);
|
||||
}
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __FASTCV_EXT_PERF_PRECOMP_HPP__
|
||||
#define __FASTCV_EXT_PERF_PRECOMP_HPP__
|
||||
|
||||
#include <opencv2/ts.hpp>
|
||||
#include <opencv2/geometry.hpp>
|
||||
#include <opencv2/features.hpp>
|
||||
#include <opencv2/fastcv.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
using namespace perf;
|
||||
} // namespace
|
||||
|
||||
#define CV_TEST_TAG_FASTCV_SKIP_DSP "fastcv_skip_dsp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<bool /*useFloat*/, int /*nLevels*/, bool /*scaleBy2*/> PyramidTestParams;
|
||||
class PyramidTest : public ::perf::TestBaseWithParam<PyramidTestParams> { };
|
||||
|
||||
PERF_TEST_P(PyramidTest, checkAllVersions, // version, useFloat, nLevels
|
||||
::testing::Values(
|
||||
PyramidTestParams { true, 2, true}, PyramidTestParams { true, 3, true}, PyramidTestParams { true, 4, true},
|
||||
PyramidTestParams {false, 2, true}, PyramidTestParams {false, 3, true}, PyramidTestParams {false, 4, true},
|
||||
PyramidTestParams {false, 2, false}, PyramidTestParams {false, 3, false}, PyramidTestParams {false, 4, false}
|
||||
))
|
||||
{
|
||||
auto par = GetParam();
|
||||
|
||||
bool useFloat = std::get<0>(par);
|
||||
int nLevels = std::get<1>(par);
|
||||
bool scaleBy2 = std::get<2>(par);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
if (useFloat)
|
||||
{
|
||||
cv::Mat f;
|
||||
src.convertTo(f, CV_32F);
|
||||
src = f;
|
||||
}
|
||||
|
||||
while(next())
|
||||
{
|
||||
std::vector<cv::Mat> pyr;
|
||||
startTimer();
|
||||
cv::fastcv::buildPyramid(src, pyr, nLevels, scaleBy2);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
typedef std::tuple<MatType, size_t> SobelPyramidTestParams;
|
||||
class SobelPyramidTest : public ::perf::TestBaseWithParam<SobelPyramidTestParams> {};
|
||||
|
||||
PERF_TEST_P(SobelPyramidTest, checkAllTypes,
|
||||
::testing::Combine(::testing::Values(CV_8S, CV_16S, CV_32F),
|
||||
::testing::Values(3, 6)))
|
||||
{
|
||||
auto p = GetParam();
|
||||
int type = std::get<0>(p);
|
||||
size_t nLevels = std::get<1>(p);
|
||||
|
||||
// NOTE: test files should be manually loaded to folder on a device, for example like this:
|
||||
// adb push fastcv/misc/bilateral_recursive/ /sdcard/testdata/fastcv/bilateral/
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
std::vector<cv::Mat> pyr;
|
||||
cv::fastcv::buildPyramid(src, pyr, nLevels);
|
||||
|
||||
while(next())
|
||||
{
|
||||
std::vector<cv::Mat> pyrDx, pyrDy;
|
||||
startTimer();
|
||||
cv::fastcv::sobelPyramid(pyr, pyrDx, pyrDy, type);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<cv::Size /*srcSize*/> SumOfAbsDiffsPerfParams;
|
||||
typedef perf::TestBaseWithParam<SumOfAbsDiffsPerfParams> SumOfAbsDiffsPerfTest;
|
||||
|
||||
PERF_TEST_P(SumOfAbsDiffsPerfTest, run,
|
||||
::testing::Values(cv::Size(640, 480), // VGA
|
||||
cv::Size(1280, 720), // 720p
|
||||
cv::Size(1920, 1080)) // 1080p
|
||||
)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
// Initialize FastCV DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
auto p = GetParam();
|
||||
cv::Size srcSize = std::get<0>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
cv::Mat patch, src;
|
||||
|
||||
patch.allocator = cv::fastcv::getQcAllocator(); // Use FastCV allocator for patch
|
||||
src.allocator = cv::fastcv::getQcAllocator(); // Use FastCV allocator for src
|
||||
|
||||
patch.create(8, 8, CV_8UC1);
|
||||
src.create(srcSize, CV_8UC1);
|
||||
|
||||
cvtest::randUni(rng, patch, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
cvtest::randUni(rng, src, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
cv::Mat dst;
|
||||
dst.allocator = cv::fastcv::getQcAllocator(); // Use FastCV allocator for dst
|
||||
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::sumOfAbsoluteDiffs(patch, src, dst);
|
||||
stopTimer();
|
||||
}
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef perf::TestBaseWithParam<std::tuple<Size, int>> ResizePerfTest;
|
||||
|
||||
PERF_TEST_P(ResizePerfTest, run, ::testing::Combine(
|
||||
::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(2, 4) // resize factor
|
||||
))
|
||||
{
|
||||
Size size = std::get<0>(GetParam());
|
||||
int factor = std::get<1>(GetParam());
|
||||
|
||||
cv::Mat inputImage(size, CV_8UC1);
|
||||
cv::randu(inputImage, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
cv::Mat resized_image;
|
||||
Size dsize(inputImage.cols / factor, inputImage.rows / factor);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::resizeDown(inputImage, resized_image, dsize, 0, 0);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<std::tuple<Size, double, double, int>> ResizeByMnPerfTest;
|
||||
|
||||
PERF_TEST_P(ResizeByMnPerfTest, run, ::testing::Combine(
|
||||
::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // image size
|
||||
::testing::Values(0.35, 0.65), // inv_scale_x
|
||||
::testing::Values(0.35, 0.65), // inv_scale_y
|
||||
::testing::Values(CV_8UC1, CV_8UC2) // data type
|
||||
))
|
||||
{
|
||||
Size size = std::get<0>(GetParam());
|
||||
double inv_scale_x = std::get<1>(GetParam());
|
||||
double inv_scale_y = std::get<2>(GetParam());
|
||||
int type = std::get<3>(GetParam());
|
||||
|
||||
cv::Mat inputImage(size, type);
|
||||
cv::randu(inputImage, cv::Scalar::all(0), cv::Scalar::all(255));
|
||||
|
||||
Size dsize;
|
||||
cv::Mat resized_image;
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::resizeDown(inputImage, resized_image, dsize, inv_scale_x, inv_scale_y);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<cv::Size, bool /*type*/> ThresholdOtsuPerfParams;
|
||||
typedef perf::TestBaseWithParam<ThresholdOtsuPerfParams> ThresholdOtsuPerfTest;
|
||||
|
||||
PERF_TEST_P(ThresholdOtsuPerfTest, run,
|
||||
::testing::Combine(::testing::Values(Size(320, 240), Size(640, 480), Size(1280, 720), Size(1920, 1080)),
|
||||
::testing::Values(false, true) // type
|
||||
)
|
||||
)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
auto p = GetParam();
|
||||
cv::Size size = std::get<0>(p);
|
||||
bool type = std::get<1>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
|
||||
cv::Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(size, CV_8UC1);
|
||||
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
cv::Mat dst;
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::dsp::thresholdOtsu(src, dst, type);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<cv::Size, int /*lowThresh*/, int /*highThresh*/, int /*trueValue*/, int /*falseValue*/> ThresholdRangePerfParams;
|
||||
typedef perf::TestBaseWithParam<ThresholdRangePerfParams> ThresholdRangePerfTest;
|
||||
|
||||
PERF_TEST_P(ThresholdRangePerfTest, run,
|
||||
::testing::Combine(::testing::Values(Size(8, 8), Size(640, 480), Size(800, 600)),
|
||||
::testing::Values(0, 15, 128, 255), // lowThresh
|
||||
::testing::Values(0, 15, 128, 255), // highThresh
|
||||
::testing::Values(0, 15, 128, 255), // trueValue
|
||||
::testing::Values(0, 15, 128, 255) // falseValue
|
||||
)
|
||||
)
|
||||
{
|
||||
auto p = GetParam();
|
||||
cv::Size size = std::get<0>(p);
|
||||
int loThresh = std::get<1>(p);
|
||||
int hiThresh = std::get<2>(p);
|
||||
int trueValue = std::get<3>(p);
|
||||
int falseValue = std::get<4>(p);
|
||||
|
||||
int lowThresh = std::min(loThresh, hiThresh);
|
||||
int highThresh = std::max(loThresh, hiThresh);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
|
||||
|
||||
Mat dst;
|
||||
while(next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::thresholdRange(src, dst, lowThresh, highThresh, trueValue, falseValue);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
typedef std::tuple<int /*winSize*/, bool /*useSobelPyramid*/, bool /*useInitialEstimate*/ > TrackingTestParams;
|
||||
class TrackingTest : public ::perf::TestBaseWithParam<TrackingTestParams> {};
|
||||
|
||||
PERF_TEST_P(TrackingTest, checkAllVersions,
|
||||
::testing::Combine(::testing::Values(5, 7, 9), // window size
|
||||
::testing::Bool(), // useSobelPyramid
|
||||
::testing::Bool() // useInitialEstimate
|
||||
))
|
||||
{
|
||||
auto par = GetParam();
|
||||
|
||||
int winSz = std::get<0>(par);
|
||||
bool useSobelPyramid = std::get<1>(par);
|
||||
bool useInitialEstimate = std::get<2>(par);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
double ang = 5.0 * CV_PI / 180.0;
|
||||
cv::Matx33d tr = {
|
||||
cos(ang), -sin(ang), 1,
|
||||
sin(ang), cos(ang), 2,
|
||||
0, 0, 1
|
||||
};
|
||||
cv::Matx33d orig {
|
||||
1, 0, -(double)src.cols / 2,
|
||||
0, 1, -(double)src.rows / 2,
|
||||
0, 0, 1
|
||||
};
|
||||
cv::Matx33d back {
|
||||
1, 0, (double)src.cols / 2,
|
||||
0, 1, (double)src.rows / 2,
|
||||
0, 0, 1
|
||||
};
|
||||
cv::Matx23d trans = (back * tr * orig).get_minor<2, 3>(0, 0);
|
||||
|
||||
cv::Mat dst;
|
||||
cv::warpAffine(src, dst, trans, src.size());
|
||||
|
||||
int nLevels = 4;
|
||||
std::vector<cv::Mat> srcPyr, dstPyr;
|
||||
|
||||
cv::buildPyramid(src, srcPyr, nLevels - 1);
|
||||
cv::buildPyramid(dst, dstPyr, nLevels - 1);
|
||||
|
||||
cv::Matx23f transf = trans;
|
||||
int nPts = 32;
|
||||
std::vector<cv::Point2f> ptsIn, ptsEst, ptsExpected;
|
||||
for (int i = 0; i < nPts; i++)
|
||||
{
|
||||
cv::Point2f p { (((float)cv::theRNG())*0.5f + 0.25f) * src.cols,
|
||||
(((float)cv::theRNG())*0.5f + 0.25f) * src.rows };
|
||||
ptsIn.push_back(p);
|
||||
ptsExpected.push_back(transf * cv::Vec3f(p.x, p.y, 1.0));
|
||||
ptsEst.push_back(p);
|
||||
}
|
||||
|
||||
cv::TermCriteria termCrit;
|
||||
termCrit.type = cv::TermCriteria::COUNT | cv::TermCriteria::EPS;
|
||||
termCrit.maxCount = 7;
|
||||
termCrit.epsilon = 0.03f * 0.03f;
|
||||
|
||||
std::vector<cv::Mat> srcDxPyr, srcDyPyr;
|
||||
if (useSobelPyramid)
|
||||
{
|
||||
cv::fastcv::sobelPyramid(srcPyr, srcDxPyr, srcDyPyr, CV_8S);
|
||||
}
|
||||
|
||||
while(next())
|
||||
{
|
||||
std::vector<int32_t> statusVec(nPts);
|
||||
std::vector<cv::Point2f> ptsOut(nPts);
|
||||
startTimer();
|
||||
if (useSobelPyramid)
|
||||
{
|
||||
cv::fastcv::trackOpticalFlowLK(src, dst, srcPyr, dstPyr, srcDxPyr, srcDyPyr,
|
||||
ptsIn, ptsOut, statusVec, {winSz, winSz});
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::fastcv::trackOpticalFlowLK(src, dst, srcPyr, dstPyr, ptsIn, ptsOut, (useInitialEstimate ? ptsEst : noArray()),
|
||||
statusVec, {winSz, winSz}, termCrit);
|
||||
}
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
static void getInvertMatrix(Mat& src, Size dstSize, Mat& M)
|
||||
{
|
||||
RNG& rng = cv::theRNG();
|
||||
Point2f s[4], d[4];
|
||||
|
||||
s[0] = Point2f(0,0);
|
||||
d[0] = Point2f(0,0);
|
||||
s[1] = Point2f(src.cols-1.f,0);
|
||||
d[1] = Point2f(dstSize.width-1.f,0);
|
||||
s[2] = Point2f(src.cols-1.f,src.rows-1.f);
|
||||
d[2] = Point2f(dstSize.width-1.f,dstSize.height-1.f);
|
||||
s[3] = Point2f(0,src.rows-1.f);
|
||||
d[3] = Point2f(0,dstSize.height-1.f);
|
||||
|
||||
float buffer[16];
|
||||
Mat tmp( 1, 16, CV_32FC1, buffer );
|
||||
rng.fill( tmp, 1, Scalar::all(0.), Scalar::all(0.1) );
|
||||
|
||||
for(int i = 0; i < 4; i++ )
|
||||
{
|
||||
s[i].x += buffer[i*4]*src.cols/2;
|
||||
s[i].y += buffer[i*4+1]*src.rows/2;
|
||||
d[i].x += buffer[i*4+2]*dstSize.width/2;
|
||||
d[i].y += buffer[i*4+3]*dstSize.height/2;
|
||||
}
|
||||
|
||||
cv::getPerspectiveTransform( s, d ).convertTo( M, M.depth() );
|
||||
|
||||
// Invert the perspective matrix
|
||||
invert(M,M);
|
||||
}
|
||||
|
||||
static cv::Mat getInverseAffine(const cv::Mat& affine)
|
||||
{
|
||||
// Extract the 2x2 part
|
||||
cv::Mat rotationScaling = affine(cv::Rect(0, 0, 2, 2));
|
||||
|
||||
// Invert the 2x2 part
|
||||
cv::Mat inverseRotationScaling;
|
||||
cv::invert(rotationScaling, inverseRotationScaling);
|
||||
|
||||
// Extract the translation part
|
||||
cv::Mat translation = affine(cv::Rect(2, 0, 1, 2));
|
||||
|
||||
// Compute the new translation
|
||||
cv::Mat inverseTranslation = -inverseRotationScaling * translation;
|
||||
|
||||
// Construct the inverse affine matrix
|
||||
cv::Mat inverseAffine = cv::Mat::zeros(2, 3, CV_32F);
|
||||
inverseRotationScaling.copyTo(inverseAffine(cv::Rect(0, 0, 2, 2)));
|
||||
inverseTranslation.copyTo(inverseAffine(cv::Rect(2, 0, 1, 2)));
|
||||
|
||||
return inverseAffine;
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<Size> WarpPerspective2PlanePerfTest;
|
||||
|
||||
PERF_TEST_P(WarpPerspective2PlanePerfTest, run,
|
||||
::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p))
|
||||
{
|
||||
cv::Size dstSize = GetParam();
|
||||
cv::Mat img = imread(cvtest::findDataFile("cv/shared/baboon.png"));
|
||||
Mat src(img.rows, img.cols, CV_8UC1);
|
||||
cvtColor(img,src,cv::COLOR_BGR2GRAY);
|
||||
cv::Mat dst1, dst2, matrix;
|
||||
matrix.create(3,3,CV_32FC1);
|
||||
|
||||
getInvertMatrix(src, dstSize, matrix);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::warpPerspective2Plane(src, src, dst1, dst2, matrix, dstSize);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<tuple<Size, int, int>> WarpPerspectivePerfTest;
|
||||
|
||||
PERF_TEST_P(WarpPerspectivePerfTest, run,
|
||||
::testing::Combine( ::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
::testing::Values(INTER_NEAREST, INTER_LINEAR, INTER_AREA),
|
||||
::testing::Values(BORDER_CONSTANT, BORDER_REPLICATE, BORDER_TRANSPARENT)))
|
||||
{
|
||||
cv::Size dstSize = get<0>(GetParam());
|
||||
int interplation = get<1>(GetParam());
|
||||
int borderType = get<2>(GetParam());
|
||||
cv::Scalar borderValue = Scalar::all(100);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
EXPECT_FALSE(src.empty());
|
||||
|
||||
cv::Mat dst, matrix, ref;
|
||||
matrix.create(3, 3, CV_32FC1);
|
||||
|
||||
getInvertMatrix(src, dstSize, matrix);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::warpPerspective(src, dst, matrix, dstSize, interplation, borderType, borderValue);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef TestBaseWithParam< tuple<MatType, Size> > WarpAffine3ChannelPerf;
|
||||
|
||||
PERF_TEST_P(WarpAffine3ChannelPerf, run, Combine(
|
||||
Values(CV_8UC3),
|
||||
Values( szVGA, sz720p, sz1080p)
|
||||
))
|
||||
{
|
||||
Size sz, szSrc(512, 512);
|
||||
int dataType;
|
||||
dataType = get<0>(GetParam());
|
||||
sz = get<1>(GetParam());
|
||||
|
||||
cv::Mat src(szSrc, dataType), dst(sz, dataType);
|
||||
|
||||
cvtest::fillGradient<uint8_t>(src);
|
||||
|
||||
//Affine matrix
|
||||
float angle = 30.0; // Rotation angle in degrees
|
||||
float scale = 2.2; // Scale factor
|
||||
cv::Mat affine = cv::getRotationMatrix2D(cv::Point2f(100, 100), angle, scale);
|
||||
|
||||
// Compute the inverse affine matrix
|
||||
cv::Mat inverseAffine = getInverseAffine(affine);
|
||||
|
||||
// Create the dstBorder array
|
||||
Mat dstBorder;
|
||||
|
||||
declare.in(src).out(dst);
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::warpAffine(src, dst, inverseAffine, sz);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef perf::TestBaseWithParam<std::tuple<cv::Size, cv::Point2f, cv::Mat>> WarpAffineROIPerfTest;
|
||||
|
||||
PERF_TEST_P(WarpAffineROIPerfTest, run, ::testing::Combine(
|
||||
::testing::Values(cv::Size(50, 50), cv::Size(100, 100)), // patch size
|
||||
::testing::Values(cv::Point2f(50.0f, 50.0f), cv::Point2f(100.0f, 100.0f)), // position
|
||||
::testing::Values((cv::Mat_<float>(2, 2) << 1, 0, 0, 1), // identity matrix
|
||||
(cv::Mat_<float>(2, 2) << cos(CV_PI), -sin(CV_PI), sin(CV_PI), cos(CV_PI))) // rotation matrix
|
||||
))
|
||||
{
|
||||
cv::Size patchSize = std::get<0>(GetParam());
|
||||
cv::Point2f position = std::get<1>(GetParam());
|
||||
cv::Mat affine = std::get<2>(GetParam());
|
||||
|
||||
cv::Mat src = cv::imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
// Create ROI with top-left at the specified position
|
||||
cv::Rect roiRect(static_cast<int>(position.x), static_cast<int>(position.y), patchSize.width, patchSize.height);
|
||||
|
||||
// Ensure ROI is within image bounds
|
||||
roiRect = roiRect & cv::Rect(0, 0, src.cols, src.rows);
|
||||
cv::Mat roi = src(roiRect);
|
||||
|
||||
cv::Mat patch;
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::warpAffine(roi, patch, affine, patchSize);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
typedef TestBaseWithParam<tuple<int, int> > WarpAffinePerfTest;
|
||||
|
||||
PERF_TEST_P(WarpAffinePerfTest, run, ::testing::Combine(
|
||||
::testing::Values(cv::InterpolationFlags::INTER_NEAREST, cv::InterpolationFlags::INTER_LINEAR, cv::InterpolationFlags::INTER_AREA),
|
||||
::testing::Values(0, 255) // Black and white borders
|
||||
))
|
||||
{
|
||||
// Load the source image
|
||||
cv::Mat src = cv::imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(src.empty());
|
||||
|
||||
// Generate random values for the affine matrix
|
||||
std::srand(std::time(0));
|
||||
float angle = static_cast<float>(std::rand() % 360); // Random angle between 0 and 360 degrees
|
||||
float scale = static_cast<float>(std::rand() % 200) / 100.0f + 0.5f; // Random scale between 0.5 and 2.5
|
||||
float tx = static_cast<float>(std::rand() % 100) - 50; // Random translation between -50 and 50
|
||||
float ty = static_cast<float>(std::rand() % 100) - 50; // Random translation between -50 and 50
|
||||
float radians = angle * CV_PI / 180.0;
|
||||
cv::Mat affine = (cv::Mat_<float>(2, 3) << scale * cos(radians), -scale * sin(radians), tx,
|
||||
scale * sin(radians), scale * cos(radians), ty);
|
||||
|
||||
// Compute the inverse affine matrix
|
||||
cv::Mat inverseAffine = getInverseAffine(affine);
|
||||
|
||||
// Define the destination size
|
||||
cv::Size dsize(src.cols, src.rows);
|
||||
|
||||
// Define the output matrix
|
||||
cv::Mat dst;
|
||||
|
||||
// Get the parameters
|
||||
int interpolation = std::get<0>(GetParam());
|
||||
int borderValue = std::get<1>(GetParam());
|
||||
|
||||
while (next())
|
||||
{
|
||||
startTimer();
|
||||
cv::fastcv::warpAffine(src, dst, inverseAffine, dsize, interpolation, borderValue);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
} //namespace
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
QcResourceManager& QcResourceManager::getInstance() {
|
||||
static QcResourceManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void QcResourceManager::addAllocation(void* ptr) {
|
||||
std::lock_guard<std::mutex> lock(resourceMutex);
|
||||
activeAllocations.insert(ptr);
|
||||
CV_LOG_DEBUG(NULL, cv::format("Active Allocations: %zu", activeAllocations.size()));
|
||||
}
|
||||
|
||||
void QcResourceManager::removeAllocation(void* ptr) {
|
||||
std::lock_guard<std::mutex> lock(resourceMutex);
|
||||
activeAllocations.erase(ptr);
|
||||
CV_LOG_DEBUG(NULL, cv::format("Active Allocations: %zu", activeAllocations.size()));
|
||||
}
|
||||
|
||||
QcAllocator::QcAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
QcAllocator::~QcAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
cv::UMatData* QcAllocator::allocate(int dims, const int* sizes, int type,
|
||||
void* data0, size_t* step, cv::AccessFlag flags,
|
||||
cv::UMatUsageFlags usageFlags) const
|
||||
{
|
||||
CV_UNUSED(flags);
|
||||
CV_UNUSED(usageFlags);
|
||||
|
||||
size_t total = CV_ELEM_SIZE(type);
|
||||
for( int i = dims-1; i >= 0; i-- )
|
||||
{
|
||||
if( step )
|
||||
{
|
||||
if( data0 && step[i] != cv::Mat::AUTO_STEP )
|
||||
{
|
||||
CV_Assert(total <= step[i]);
|
||||
total = step[i];
|
||||
}
|
||||
else
|
||||
step[i] = total;
|
||||
}
|
||||
total *= sizes[i];
|
||||
}
|
||||
|
||||
int fd = -1;
|
||||
uchar* data = data0 ? (uchar*)data0 : (uchar*)fcvHwMemAlloc(total, 16, &fd);
|
||||
cv::UMatData* u = new cv::UMatData(this);
|
||||
u->data = u->origdata = data;
|
||||
u->size = total;
|
||||
if(data0)
|
||||
u->flags |= cv::UMatData::USER_ALLOCATED;
|
||||
|
||||
// Store FD in userdata (cast to void*)
|
||||
if (fd >= 0)
|
||||
u->userdata = reinterpret_cast<void*>(static_cast<intptr_t>(fd));
|
||||
|
||||
// Add to active allocations
|
||||
cv::fastcv::QcResourceManager::getInstance().addAllocation(data);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
bool QcAllocator::allocate(cv::UMatData* u, cv::AccessFlag accessFlags, cv::UMatUsageFlags usageFlags) const
|
||||
{
|
||||
CV_UNUSED(accessFlags);
|
||||
CV_UNUSED(usageFlags);
|
||||
|
||||
return u != nullptr;
|
||||
}
|
||||
|
||||
void QcAllocator::deallocate(cv::UMatData* u) const
|
||||
{
|
||||
if(!u)
|
||||
return;
|
||||
|
||||
CV_Assert(u->urefcount == 0);
|
||||
CV_Assert(u->refcount == 0);
|
||||
if( !(u->flags & cv::UMatData::USER_ALLOCATED) )
|
||||
{
|
||||
fcvHwMemFree(u->origdata);
|
||||
|
||||
// Remove from active allocations
|
||||
cv::fastcv::QcResourceManager::getInstance().removeAllocation(u->origdata);
|
||||
u->origdata = 0;
|
||||
}
|
||||
|
||||
delete u;
|
||||
}
|
||||
|
||||
cv::MatAllocator* getQcAllocator()
|
||||
{
|
||||
static cv::MatAllocator* allocator = new QcAllocator;
|
||||
return allocator;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void matmuls8s32(InputArray _src1, InputArray _src2, OutputArray _dst)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src1.empty() && _src1.type() == CV_8SC1);
|
||||
CV_Assert(_src1.cols() <= 131072);
|
||||
CV_Assert(_src1.step() % 8 == 0);
|
||||
CV_Assert(_src1.cols() == _src2.rows());
|
||||
Mat src1 = _src1.getMat();
|
||||
|
||||
CV_Assert(!_src2.empty() && _src2.type() == CV_8SC1);
|
||||
CV_Assert(_src2.step() % 8 == 0);
|
||||
Mat src2 = _src2.getMat();
|
||||
|
||||
_dst.create(_src1.rows(), _src2.cols(), CV_32SC1);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvMatrixMultiplys8s32((const int8_t*)src1.data, src1.cols, src1.rows, src1.step,
|
||||
(const int8_t*)src2.data, src2.cols, src2.step,
|
||||
(int32_t*)dst.data, dst.step);
|
||||
}
|
||||
|
||||
void arithmetic_op(InputArray _src1, InputArray _src2, OutputArray _dst, int op)
|
||||
{
|
||||
CV_Assert(!_src1.empty() && (_src1.depth() == CV_8U || _src1.depth() == CV_16S || _src1.depth() == CV_32F));
|
||||
CV_Assert(!_src2.empty() && _src2.type() == _src1.type());
|
||||
CV_Assert(_src2.size() == _src1.size());
|
||||
|
||||
Mat src1 = _src1.getMat();
|
||||
Mat src2 = _src2.getMat();
|
||||
|
||||
_dst.create(_src1.rows(), _src1.cols(), _src1.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvConvertPolicy policy = FASTCV_CONVERT_POLICY_SATURATE;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
int func = FCV_OPTYPE(_src1.depth(), op);
|
||||
switch(func)
|
||||
{
|
||||
case FCV_OPTYPE(CV_8U, 0):
|
||||
cv::parallel_for_(cv::Range(0, src1.rows), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const uchar* yS1 = src1.data + static_cast<size_t>(range.start)*src1.step[0];
|
||||
const uchar* yS2 = src2.data + static_cast<size_t>(range.start)*src2.step[0];
|
||||
uchar* yD = dst.data + static_cast<size_t>(range.start)*dst.step[0];
|
||||
fcvAddu8(yS1, src1.cols, rangeHeight, src1.step[0],
|
||||
yS2, src2.step[0], policy, yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
break;
|
||||
case FCV_OPTYPE(CV_16S, 0):
|
||||
cv::parallel_for_(cv::Range(0, src1.rows), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const short* yS1 = (short*)src1.data + static_cast<size_t>(range.start)*(src1.step[0]/sizeof(short));
|
||||
const short* yS2 = (short*)src2.data + static_cast<size_t>(range.start)*(src2.step[0]/sizeof(short));
|
||||
short* yD = (short*)dst.data + static_cast<size_t>(range.start)*(dst.step[0]/sizeof(short));
|
||||
fcvAdds16_v2(yS1, src1.cols, rangeHeight, src1.step[0],
|
||||
yS2, src2.step[0], policy, yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
break;
|
||||
case FCV_OPTYPE(CV_32F, 0):
|
||||
cv::parallel_for_(cv::Range(0, src1.rows), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const float* yS1 = (float*)src1.data + static_cast<size_t>(range.start)*(src1.step[0]/sizeof(float));
|
||||
const float* yS2 = (float*)src2.data + static_cast<size_t>(range.start)*(src2.step[0]/sizeof(float));
|
||||
float* yD = (float*)dst.data + static_cast<size_t>(range.start)*(dst.step[0]/sizeof(float));
|
||||
fcvAddf32(yS1, src1.cols, rangeHeight, src1.step[0],
|
||||
yS2, src2.step[0], yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
break;
|
||||
case FCV_OPTYPE(CV_8U, 1):
|
||||
cv::parallel_for_(cv::Range(0, src1.rows), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const uchar* yS1 = src1.data + static_cast<size_t>(range.start)*src1.step[0];
|
||||
const uchar* yS2 = src2.data + static_cast<size_t>(range.start)*src2.step[0];
|
||||
uchar* yD = dst.data + static_cast<size_t>(range.start)*dst.step[0];
|
||||
fcvSubtractu8(yS1, src1.cols, rangeHeight, src1.step[0],
|
||||
yS2, src2.step[0], policy, yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
break;
|
||||
case FCV_OPTYPE(CV_16S, 1):
|
||||
cv::parallel_for_(cv::Range(0, src1.rows), [&](const cv::Range &range){
|
||||
int rangeHeight = range.end - range.start;
|
||||
const short* yS1 = (short*)src1.data + static_cast<size_t>(range.start)*(src1.step[0]/sizeof(short));
|
||||
const short* yS2 = (short*)src2.data + static_cast<size_t>(range.start)*(src2.step[0]/sizeof(short));
|
||||
short* yD = (short*)dst.data + static_cast<size_t>(range.start)*(dst.step[0]/sizeof(short));
|
||||
fcvSubtracts16(yS1, src1.cols, rangeHeight, src1.step[0],
|
||||
yS2, src2.step[0], policy, yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
break;
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("op type is not supported"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gemm(InputArray _src1, InputArray _src2, OutputArray _dst, float alpha, InputArray _src3, float beta)
|
||||
{
|
||||
CV_Assert(!_src1.empty() && _src1.type() == CV_32FC1);
|
||||
CV_Assert(_src1.cols() == _src2.rows());
|
||||
Mat src1 = _src1.getMat();
|
||||
|
||||
CV_Assert(!_src2.empty() && _src2.type() == CV_32FC1);
|
||||
Mat src2 = _src2.getMat();
|
||||
|
||||
bool isSrc3 = !_src3.empty();
|
||||
|
||||
Mat src3 = _src3.getMat();
|
||||
|
||||
_dst.create(_src1.rows(), _src2.cols(), CV_32FC1);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_Assert(!FCV_CMP_EQ(alpha,0));
|
||||
|
||||
cv::Mat dst_temp1, dst_temp2;
|
||||
float *dstp = NULL;
|
||||
bool inplace = false;
|
||||
size_t dst_stride;
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
int n = src1.cols, m = src1.rows, k = src2.cols;
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
if(src1.data == dst.data || src2.data == dst.data || (isSrc3 && (src3.data == dst.data)))
|
||||
{
|
||||
dst_temp1 = cv::Mat(m, k, CV_32FC1);
|
||||
dstp = dst_temp1.ptr<float>();
|
||||
inplace = true;
|
||||
dst_stride = dst_temp1.step[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
dstp = (float32_t*)dst.data;
|
||||
dst_stride = dst.step[0];
|
||||
}
|
||||
float32_t *dstp1 = dstp;
|
||||
status = fcvMatrixMultiplyf32_v2((float32_t*)src1.data, n, m, src1.step[0], (float32_t*)src2.data, k,
|
||||
src2.step[0], dstp, dst_stride);
|
||||
|
||||
bool isAlpha = !(FCV_CMP_EQ(alpha,0) || FCV_CMP_EQ(alpha,1));
|
||||
if(isAlpha && status == FASTCV_SUCCESS)
|
||||
{
|
||||
status = fcvMultiplyScalarf32(dstp, k, m, dst_stride, alpha, dstp1, dst_stride);
|
||||
}
|
||||
|
||||
if(isSrc3 && (!FCV_CMP_EQ(beta,0)) && status == FASTCV_SUCCESS)
|
||||
{
|
||||
cv::Mat dst3 = cv::Mat(m, k, CV_32FC1);
|
||||
if(!FCV_CMP_EQ(beta,1))
|
||||
{
|
||||
status = fcvMultiplyScalarf32((float32_t*)src3.data, k, m, src3.step[0], beta, (float32_t*)dst3.data, dst3.step[0]);
|
||||
if(status == FASTCV_SUCCESS)
|
||||
fcvAddf32_v2(dstp, k, m, dst_stride, (float32_t*)dst3.data, dst3.step[0], dstp1, dst_stride);
|
||||
}
|
||||
else
|
||||
fcvAddf32_v2(dstp, k, m, dst_stride, (float32_t*)src3.data, src3.step[0], dstp1, dst_stride);
|
||||
}
|
||||
|
||||
if(inplace == true)
|
||||
{
|
||||
dst_temp1(cv::Rect(0, 0, k, m)).copyTo(dst(cv::Rect(0, 0, k, m)));
|
||||
}
|
||||
}
|
||||
|
||||
void integrateYUV(InputArray _Y, InputArray _CbCr, OutputArray _IY, OutputArray _ICb, OutputArray _ICr)
|
||||
{
|
||||
CV_Assert(!_Y.empty() && !_CbCr.empty());
|
||||
CV_Assert(_Y.type() == _CbCr.type() && _Y.type() == CV_8UC1);
|
||||
Mat Y = _Y.getMat();
|
||||
Mat CbCr = _CbCr.getMat();
|
||||
int Ywidth = Y.cols;
|
||||
int Yheight = Y.rows;
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
_IY.create(Yheight + 1, Ywidth + 1, CV_32SC1);
|
||||
_ICb.create(Yheight/2 + 1, Ywidth/2 + 1, CV_32SC1);
|
||||
_ICr.create(Yheight/2 + 1, Ywidth/2 + 1, CV_32SC1);
|
||||
|
||||
Mat IY_ = _IY.getMat();
|
||||
Mat ICb_ = _ICb.getMat();
|
||||
Mat ICr_ = _ICr.getMat();
|
||||
|
||||
fcvIntegrateImageYCbCr420PseudoPlanaru8(Y.data, CbCr.data, Ywidth, Yheight, Y.step[0],
|
||||
CbCr.step[0], (uint32_t*)IY_.data, (uint32_t*)ICb_.data, (uint32_t*)ICr_.data,
|
||||
IY_.step[0], ICb_.step[0], ICr_.step[0]);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class FcvFilterLoop_Invoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvFilterLoop_Invoker(cv::Mat src_, size_t src_step_, cv::Mat dst_, size_t dst_step_, int width_, int height_,
|
||||
int bdr_, int knl_, float32_t sigma_color_, float32_t sigma_space_) :
|
||||
cv::ParallelLoopBody(), src_step(src_step_), dst_step(dst_step_), width(width_), height(height_),
|
||||
bdr(bdr_), knl(knl_), sigma_color(sigma_color_), sigma_space(sigma_space_), src(src_), dst(dst_)
|
||||
{ }
|
||||
|
||||
virtual void operator()(const cv::Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int height_ = range.end - range.start;
|
||||
int width_ = width;
|
||||
cv::Mat src_;
|
||||
int n = knl/2;
|
||||
|
||||
src_ = cv::Mat(height_ + 2 * n, width_ + 2 * n, CV_8U);
|
||||
if (range.start == 0 && range.end == height)
|
||||
{
|
||||
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 == (height))
|
||||
{
|
||||
cv::copyMakeBorder(src(cv::Rect(0, range.start - n, width_, height_ + n)), src_, 0, n, n, n, bdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::copyMakeBorder(src(cv::Rect(0, range.start - n, width_, height_ + 2 * n)), src_, 0, 0, n, n, bdr);
|
||||
}
|
||||
|
||||
cv::Mat dst_padded = cv::Mat(height_ + 2*n, width_ + 2*n, CV_8U);
|
||||
|
||||
auto func = (knl == 5) ? fcvBilateralFilter5x5u8_v3 :
|
||||
(knl == 7) ? fcvBilateralFilter7x7u8_v3 :
|
||||
(knl == 9) ? fcvBilateralFilter9x9u8_v3 :
|
||||
nullptr;
|
||||
func(src_.data, width_ + 2 * n, height_ + 2 * n, width_ + 2 * n,
|
||||
dst_padded.data, width_ + 2 * n, sigma_color, sigma_space, 0);
|
||||
|
||||
cv::Mat dst_temp1 = dst_padded(cv::Rect(n, n, width_, height_));
|
||||
cv::Mat dst_temp2 = dst(cv::Rect(0, range.start, width_, height_));
|
||||
dst_temp1.copyTo(dst_temp2);
|
||||
}
|
||||
|
||||
private:
|
||||
const size_t src_step;
|
||||
const size_t dst_step;
|
||||
const int width;
|
||||
const int height;
|
||||
const int bdr;
|
||||
const int knl;
|
||||
float32_t sigma_color;
|
||||
float32_t sigma_space;
|
||||
int ret;
|
||||
cv::Mat src;
|
||||
cv::Mat dst;
|
||||
|
||||
FcvFilterLoop_Invoker(const FcvFilterLoop_Invoker &); // = delete;
|
||||
const FcvFilterLoop_Invoker& operator= (const FcvFilterLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
float sigmaColor, float sigmaSpace,
|
||||
int borderType )
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty());
|
||||
int type = _src.type();
|
||||
CV_Assert(type == CV_8UC1);
|
||||
CV_Assert(d == 5 || d == 7 || d == 9);
|
||||
|
||||
Size size = _src.size();
|
||||
_dst.create( size, type );
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_Assert(src.data != dst.data);
|
||||
|
||||
if( sigmaColor <= 0 )
|
||||
sigmaColor = 1;
|
||||
if( sigmaSpace <= 0 )
|
||||
sigmaSpace = 1;
|
||||
|
||||
int nStripes = (src.rows / 20 == 0) ? 1 : (src.rows / 20);
|
||||
cv::parallel_for_(cv::Range(0, src.rows),
|
||||
FcvFilterLoop_Invoker(src, src.step, dst, dst.step, src.cols, src.rows, borderType, d, sigmaColor, sigmaSpace), nStripes);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class FcvGaussianBlurLoop_Invoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvGaussianBlurLoop_Invoker(const Mat& _src, Mat& _dst, int _ksize, fcvBorderType _fcvBorder, int _fcvBorderValue) :
|
||||
ParallelLoopBody(), src(_src),dst(_dst), ksize(_ksize), fcvBorder(_fcvBorder), fcvBorderValue(_fcvBorderValue)
|
||||
{
|
||||
width = src.cols;
|
||||
height = src.rows;
|
||||
halfKsize = ksize / 2;
|
||||
fcvFuncType = FCV_MAKETYPE(ksize, src.depth());
|
||||
}
|
||||
|
||||
virtual void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int topLines = 0;
|
||||
int rangeHeight = range.end-range.start;
|
||||
int paddedHeight = rangeHeight;
|
||||
|
||||
if(range.start != 0)
|
||||
{
|
||||
topLines += halfKsize;
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
if(range.end != height)
|
||||
{
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
const Mat srcPadded = src(Rect(0, range.start - topLines, width, paddedHeight));
|
||||
Mat dstPadded = Mat(paddedHeight, width, dst.depth());
|
||||
|
||||
if (fcvFuncType == FCV_MAKETYPE(3,CV_8U))
|
||||
fcvFilterGaussian3x3u8_v4(srcPadded.data, width, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step, fcvBorder, 0);
|
||||
else if (fcvFuncType == FCV_MAKETYPE(5,CV_8U))
|
||||
fcvFilterGaussian5x5u8_v3(srcPadded.data, width, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step, fcvBorder, 0);
|
||||
else if (fcvFuncType == FCV_MAKETYPE(5,CV_16S))
|
||||
fcvFilterGaussian5x5s16_v3((int16_t*)srcPadded.data, width, paddedHeight, srcPadded.step, (int16_t*)dstPadded.data,
|
||||
dstPadded.step, fcvBorder, 0);
|
||||
else if (fcvFuncType == FCV_MAKETYPE(5,CV_32S))
|
||||
fcvFilterGaussian5x5s32_v3((int32_t*)srcPadded.data, width, paddedHeight, srcPadded.step, (int32_t*)dstPadded.data,
|
||||
dstPadded.step, fcvBorder, 0);
|
||||
else if (fcvFuncType == FCV_MAKETYPE(11,CV_8U))
|
||||
fcvFilterGaussian11x11u8_v2(srcPadded.data, width, rangeHeight, srcPadded.step, dstPadded.data, dstPadded.step, fcvBorder);
|
||||
|
||||
// Only copy center part back to output image and ignore the padded lines
|
||||
Mat temp1 = dstPadded(Rect(0, topLines, width, rangeHeight));
|
||||
Mat temp2 = dst(Rect(0, range.start, width, rangeHeight));
|
||||
temp1.copyTo(temp2);
|
||||
}
|
||||
|
||||
private:
|
||||
const Mat& src;
|
||||
Mat& dst;
|
||||
int width;
|
||||
int height;
|
||||
const int ksize;
|
||||
int halfKsize;
|
||||
int fcvFuncType;
|
||||
fcvBorderType fcvBorder;
|
||||
int fcvBorderValue;
|
||||
|
||||
FcvGaussianBlurLoop_Invoker(const FcvGaussianBlurLoop_Invoker &); // = delete;
|
||||
const FcvGaussianBlurLoop_Invoker& operator= (const FcvGaussianBlurLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void gaussianBlur(InputArray _src, OutputArray _dst, int kernel_size, bool blur_border)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && CV_MAT_CN(_src.type()) == 1);
|
||||
|
||||
Size size = _src.size();
|
||||
int type = _src.type();
|
||||
_dst.create( size, type );
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int nThreads = getNumThreads();
|
||||
int nStripes = (nThreads > 1) ? ((src.rows > 60) ? 3 * nThreads : 1) : 1;
|
||||
|
||||
fcvBorderType fcvBorder = blur_border ? FASTCV_BORDER_ZERO_PADDING : FASTCV_BORDER_UNDEFINED;
|
||||
|
||||
if (((type == CV_8UC1) && ((kernel_size == 3) || (kernel_size == 5) || (kernel_size == 11))) ||
|
||||
((type == CV_16SC1) && (kernel_size == 5)) ||
|
||||
((type == CV_32SC1) && (kernel_size == 5)))
|
||||
{
|
||||
parallel_for_(Range(0, src.rows), FcvGaussianBlurLoop_Invoker(src, dst, kernel_size, fcvBorder, 0), nStripes);
|
||||
}
|
||||
else
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Src type %d, kernel size %d is not supported", type, kernel_size));
|
||||
}
|
||||
|
||||
class FcvFilter2DLoop_Invoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvFilter2DLoop_Invoker(const Mat& _src, Mat& _dst, const Mat& _kernel) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), kernel(_kernel)
|
||||
{
|
||||
width = src.cols;
|
||||
height = src.rows;
|
||||
ksize = kernel.size().width;
|
||||
halfKsize = ksize/2;
|
||||
}
|
||||
|
||||
virtual void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int topLines = 0;
|
||||
int rangeHeight = range.end-range.start;
|
||||
int paddedHeight = rangeHeight;
|
||||
|
||||
if(range.start >= halfKsize)
|
||||
{
|
||||
topLines += halfKsize;
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
if(range.end <= height-halfKsize)
|
||||
{
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
const Mat srcPadded = src(Rect(0, range.start - topLines, width, paddedHeight));
|
||||
Mat dstPadded = Mat(paddedHeight, width, dst.depth());
|
||||
|
||||
if (dst.depth() == CV_8U)
|
||||
fcvFilterCorrNxNu8((int8_t*)kernel.data, ksize, 0, srcPadded.data, width, paddedHeight, srcPadded.step,
|
||||
dstPadded.data, dstPadded.step);
|
||||
else if (dst.depth() == CV_16S)
|
||||
fcvFilterCorrNxNu8s16((int8_t*)kernel.data, ksize, 0, srcPadded.data, width, paddedHeight, srcPadded.step,
|
||||
(int16_t*)dstPadded.data, dstPadded.step);
|
||||
else if (dst.depth() == CV_32F)
|
||||
fcvFilterCorrNxNu8f32((float32_t*)kernel.data, ksize, srcPadded.data, width, paddedHeight, srcPadded.step,
|
||||
(float32_t*)dstPadded.data, dstPadded.step);
|
||||
|
||||
// Only copy center part back to output image and ignore the padded lines
|
||||
Mat temp1 = dstPadded(Rect(0, topLines, width, rangeHeight));
|
||||
Mat temp2 = dst(Rect(0, range.start, width, rangeHeight));
|
||||
temp1.copyTo(temp2);
|
||||
}
|
||||
|
||||
private:
|
||||
const Mat& src;
|
||||
Mat& dst;
|
||||
const Mat& kernel;
|
||||
int width;
|
||||
int height;
|
||||
int ksize;
|
||||
int halfKsize;
|
||||
|
||||
FcvFilter2DLoop_Invoker(const FcvFilter2DLoop_Invoker &); // = delete;
|
||||
const FcvFilter2DLoop_Invoker& operator= (const FcvFilter2DLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void filter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
|
||||
Mat kernel = _kernel.getMat();
|
||||
Size ksize = kernel.size();
|
||||
CV_Assert(ksize.width == ksize.height);
|
||||
CV_Assert(ksize.width % 2 == 1);
|
||||
|
||||
_dst.create(_src.size(), ddepth);
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int nThreads = getNumThreads();
|
||||
int nStripes = (nThreads > 1) ? ((src.rows > 60) ? 3 * nThreads : 1) : 1;
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
case CV_16S:
|
||||
{
|
||||
CV_Assert(CV_MAT_DEPTH(kernel.type()) == CV_8S);
|
||||
parallel_for_(Range(0, src.rows), FcvFilter2DLoop_Invoker(src, dst, kernel), nStripes);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
CV_Assert(CV_MAT_DEPTH(kernel.type()) == CV_32F);
|
||||
parallel_for_(Range(0, src.rows), FcvFilter2DLoop_Invoker(src, dst, kernel), nStripes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Kernel Size:%d, Dst type:%s is not supported", ksize.width,
|
||||
depthToString(ddepth)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FcvSepFilter2DLoop_Invoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvSepFilter2DLoop_Invoker(const Mat& _src, Mat& _dst, const Mat& _kernelX, const Mat& _kernelY) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), kernelX(_kernelX), kernelY(_kernelY)
|
||||
{
|
||||
width = src.cols;
|
||||
height = src.rows;
|
||||
kernelXSize = kernelX.size().width;
|
||||
kernelYSize = kernelY.size().width;
|
||||
halfKsize = kernelXSize/2;
|
||||
}
|
||||
|
||||
virtual void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int topLines = 0;
|
||||
int rangeHeight = range.end-range.start;
|
||||
int paddedHeight = rangeHeight;
|
||||
|
||||
if(range.start >= halfKsize)
|
||||
{
|
||||
topLines += halfKsize;
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
if(range.end <= height-halfKsize)
|
||||
{
|
||||
paddedHeight += halfKsize;
|
||||
}
|
||||
|
||||
const Mat srcPadded = src(Rect(0, range.start - topLines, width, paddedHeight));
|
||||
Mat dstPadded = Mat(paddedHeight, width, dst.depth());
|
||||
|
||||
switch (dst.depth())
|
||||
{
|
||||
case CV_8U:
|
||||
{
|
||||
fcvFilterCorrSepMxNu8((int8_t*)kernelX.data, kernelXSize, (int8_t*)kernelY.data, kernelYSize, 0, srcPadded.data,
|
||||
width, paddedHeight, srcPadded.step, dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
case CV_16S:
|
||||
{
|
||||
std::vector<int16_t> tmpImage(width * (paddedHeight + kernelXSize - 1));
|
||||
switch (kernelXSize)
|
||||
{
|
||||
case 9:
|
||||
{
|
||||
fcvFilterCorrSep9x9s16_v2((int16_t*)kernelX.data, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
fcvFilterCorrSep11x11s16_v2((int16_t*)kernelX.data, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
fcvFilterCorrSep13x13s16_v2((int16_t*)kernelX.data, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
fcvFilterCorrSep15x15s16_v2((int16_t*)kernelX.data, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
fcvFilterCorrSep17x17s16_v2((int16_t*)kernelX.data, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
fcvFilterCorrSepNxNs16((int16_t*)kernelX.data, kernelXSize, (int16_t*)srcPadded.data, width, paddedHeight,
|
||||
srcPadded.step, tmpImage.data(), (int16_t*)dstPadded.data, dstPadded.step);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Dst type:%s is not supported", depthToString(dst.depth())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only copy center part back to output image and ignore the padded lines
|
||||
Mat temp1 = dstPadded(Rect(0, topLines, width, rangeHeight));
|
||||
Mat temp2 = dst(Rect(0, range.start, width, rangeHeight));
|
||||
temp1.copyTo(temp2);
|
||||
}
|
||||
|
||||
private:
|
||||
const Mat& src;
|
||||
Mat& dst;
|
||||
int width;
|
||||
int height;
|
||||
const Mat& kernelX;
|
||||
const Mat& kernelY;
|
||||
int kernelXSize;
|
||||
int kernelYSize;
|
||||
int halfKsize;
|
||||
|
||||
FcvSepFilter2DLoop_Invoker(const FcvSepFilter2DLoop_Invoker &); // = delete;
|
||||
const FcvSepFilter2DLoop_Invoker& operator= (const FcvSepFilter2DLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void sepFilter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src.empty() && (_src.type() == CV_8UC1 || _src.type() == CV_16SC1));
|
||||
_dst.create(_src.size(), ddepth);
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
Mat kernelX = _kernelX.getMat();
|
||||
Mat kernelY = _kernelY.getMat();
|
||||
|
||||
int nThreads = getNumThreads();
|
||||
int nStripes = (nThreads > 1) ? ((src.rows > 60) ? 3 * nThreads : 1) : 1;
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, src.rows), FcvSepFilter2DLoop_Invoker(src, dst, kernelX, kernelY), nStripes);
|
||||
break;
|
||||
}
|
||||
case CV_16S:
|
||||
{
|
||||
CV_Assert(CV_MAT_DEPTH(src.type()) == CV_16S);
|
||||
CV_Assert(kernelX.size() == kernelY.size());
|
||||
// kernalX and kernelY shhould be same.
|
||||
Mat diff;
|
||||
absdiff(kernelX, kernelY, diff);
|
||||
CV_Assert(countNonZero(diff) == 0);
|
||||
|
||||
cv::parallel_for_(cv::Range(0, src.rows), FcvSepFilter2DLoop_Invoker(src, dst, kernelX, kernelY), nStripes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Dst type:%s is not supported", depthToString(ddepth)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void normalizeLocalBox(InputArray _src, OutputArray _dst, Size pSize, bool useStdDev)
|
||||
{
|
||||
CV_Assert(!_src.empty());
|
||||
int type = _src.type();
|
||||
CV_Assert(type == CV_8UC1 || type == CV_32FC1);
|
||||
|
||||
Size size = _src.size();
|
||||
int dst_type = type == CV_8UC1 ? CV_8SC1 : CV_32FC1;
|
||||
_dst.create(size, dst_type);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
if(type == CV_8UC1)
|
||||
fcvNormalizeLocalBoxu8(src.data, src.cols, src.rows, src.step[0],
|
||||
pSize.width, pSize.height, useStdDev, (int8_t*)dst.data, dst.step[0]);
|
||||
else if(type == CV_32FC1)
|
||||
fcvNormalizeLocalBoxf32((float*)src.data, src.cols, src.rows, src.step[0],
|
||||
pSize.width, pSize.height, useStdDev, (float*)dst.data, dst.step[0]);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
void filter2D(InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel)
|
||||
{
|
||||
CV_Assert(
|
||||
!_src.empty() &&
|
||||
_src.type() == CV_8UC1 &&
|
||||
IS_FASTCV_ALLOCATED(_src.getMat()) &&
|
||||
IS_FASTCV_ALLOCATED(_kernel.getMat())
|
||||
);
|
||||
|
||||
Mat kernel = _kernel.getMat();
|
||||
|
||||
Size ksize = kernel.size();
|
||||
CV_Assert(ksize.width == ksize.height);
|
||||
CV_Assert(ksize.width % 2 == 1);
|
||||
|
||||
_dst.create(_src.size(), ddepth);
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
{
|
||||
if(ksize.width == 3)
|
||||
fcvFilterCorr3x3s8_v2Q((int8_t*)kernel.data, src.data, src.cols, src.rows, src.step, dst.data, dst.step);
|
||||
else
|
||||
fcvFilterCorrNxNu8Q((int8_t*)kernel.data, ksize.width, 0, src.data, src.cols, src.rows, src.step, dst.data, dst.step);
|
||||
|
||||
break;
|
||||
}
|
||||
case CV_16S:
|
||||
{
|
||||
fcvFilterCorrNxNu8s16Q((int8_t*)kernel.data, ksize.width, 0, src.data, src.cols, src.rows, src.step, (int16_t*)dst.data, dst.step);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
fcvFilterCorrNxNu8f32Q((float32_t*)kernel.data, ksize.width, src.data, src.cols, src.rows, src.step, (float32_t*)dst.data, dst.step);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Kernel Size:%d, Dst type:%s is not supported", ksize.width,
|
||||
depthToString(ddepth)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void merge(InputArrayOfArrays _mv, OutputArray _dst)
|
||||
{
|
||||
CV_Assert(!_mv.empty());
|
||||
std::vector<cv::Mat> mv;
|
||||
_mv.getMatVector(mv);
|
||||
int count = mv.size();
|
||||
|
||||
CV_Assert(!mv.empty());
|
||||
|
||||
CV_Assert(count == 2 || count == 3 || count == 4);
|
||||
CV_Assert(!mv[0].empty());
|
||||
CV_Assert(mv[0].dims <= 2);
|
||||
|
||||
for(int i = 0; i < count; i++ )
|
||||
{
|
||||
CV_Assert(mv[i].size == mv[0].size && mv[i].step[0] == mv[0].step[0] && mv[i].type() == CV_8UC1);
|
||||
}
|
||||
|
||||
_dst.create(mv[0].size, CV_MAKE_TYPE(CV_8U,count));
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
switch(count)
|
||||
{
|
||||
case 2:
|
||||
cv::parallel_for_(cv::Range(0, mv[0].rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS1 = mv[0].data + static_cast<size_t>(range.start) * mv[0].step[0];
|
||||
const uchar* yS2 = mv[1].data + static_cast<size_t>(range.start) * mv[1].step[0];
|
||||
uchar* yD = dst.data + static_cast<size_t>(range.start) * dst.step[0];
|
||||
fcvChannelCombine2Planesu8(yS1, mv[0].cols, height_, mv[0].step[0], yS2, mv[1].step[0], yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
cv::parallel_for_(cv::Range(0, mv[0].rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS1 = mv[0].data + static_cast<size_t>(range.start) * mv[0].step[0];
|
||||
const uchar* yS2 = mv[1].data + static_cast<size_t>(range.start) * mv[1].step[0];
|
||||
const uchar* yS3 = mv[2].data + static_cast<size_t>(range.start) * mv[2].step[0];
|
||||
uchar* yD = dst.data + static_cast<size_t>(range.start) * dst.step[0];
|
||||
fcvChannelCombine3Planesu8(yS1, mv[0].cols, height_, mv[0].step[0], yS2, mv[1].step[0], yS3, mv[2].step[0], yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cv::parallel_for_(cv::Range(0, mv[0].rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS1 = mv[0].data + static_cast<size_t>(range.start) * mv[0].step[0];
|
||||
const uchar* yS2 = mv[1].data + static_cast<size_t>(range.start) * mv[1].step[0];
|
||||
const uchar* yS3 = mv[2].data + static_cast<size_t>(range.start) * mv[2].step[0];
|
||||
const uchar* yS4 = mv[3].data + static_cast<size_t>(range.start) * mv[3].step[0];
|
||||
uchar* yD = dst.data + static_cast<size_t>(range.start) * dst.step[0];
|
||||
fcvChannelCombine4Planesu8(yS1, mv[0].cols, height_, mv[0].step[0], yS2, mv[1].step[0], yS3, mv[2].step[0], yS4, mv[3].step[0], yD, dst.step[0]);
|
||||
}, nStripes);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("count is not supported"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void split(InputArray _src, OutputArrayOfArrays _mv)
|
||||
{
|
||||
CV_Assert(!_src.empty());
|
||||
Mat src = _src.getMat();
|
||||
|
||||
int depth = src.depth(), cn = src.channels();
|
||||
|
||||
CV_Assert(depth == CV_8U && (cn == 2 || cn == 3 || cn == 4));
|
||||
CV_Assert(src.dims <= 2);
|
||||
_mv.create(cn, 1, depth);
|
||||
for( int k = 0; k < cn; k++ )
|
||||
{
|
||||
_mv.create(src.size, depth, k);
|
||||
}
|
||||
|
||||
std::vector<cv::Mat> mv(cn);
|
||||
_mv.getMatVector(mv);
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
|
||||
if(src.rows * src.cols < 640 * 480)
|
||||
if(cn == 3 || cn == 4)
|
||||
nStripes = 1;
|
||||
|
||||
if(cn == 2)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, src.rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS = src.data + static_cast<size_t>(range.start) * src.step[0];
|
||||
uchar* y1D = mv[0].data + static_cast<size_t>(range.start) * mv[0].step[0];
|
||||
uchar* y2D = mv[1].data + static_cast<size_t>(range.start) * mv[1].step[0];
|
||||
fcvDeinterleaveu8(yS, src.cols, height_, src.step[0], y1D, mv[0].step[0], y2D, mv[1].step[0]);
|
||||
}, nStripes);
|
||||
}
|
||||
else if(cn == 3)
|
||||
{
|
||||
for(int i=0; i<cn; i++)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, src.rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS = src.data + static_cast<size_t>(range.start) * src.step[0];
|
||||
uchar* yD = mv[i].data + static_cast<size_t>(range.start) * mv[i].step[0];
|
||||
fcvChannelExtractu8(yS, src.cols, height_, src.step[0], NULL, 0, NULL, 0, (fcvChannelType)i, (fcvImageFormat)FASTCV_RGB, yD, mv[i].step[0]);
|
||||
}, nStripes);
|
||||
}
|
||||
}
|
||||
else if(cn == 4)
|
||||
{
|
||||
for(int i=0; i<cn; i++)
|
||||
{
|
||||
cv::parallel_for_(cv::Range(0, src.rows), [&](const cv::Range &range){
|
||||
int height_ = range.end - range.start;
|
||||
const uchar* yS = src.data + static_cast<size_t>(range.start) * src.step[0];
|
||||
uchar* yD = mv[i].data + static_cast<size_t>(range.start) * mv[i].step[0];
|
||||
fcvChannelExtractu8(yS, src.cols, height_, src.step[0], NULL, 0, NULL, 0, (fcvChannelType)i, (fcvImageFormat)FASTCV_RGBX, yD, mv[i].step[0]);
|
||||
}, nStripes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void clusterEuclidean(InputArray _points, InputArray _clusterCenters, OutputArray _newClusterCenters,
|
||||
OutputArray _clusterSizes, OutputArray _clusterBindings, OutputArray _clusterSumDists,
|
||||
int numPointsUsed)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_points.empty() && _points.type() == CV_8UC1);
|
||||
int nPts = _points.rows();
|
||||
int nDims = _points.cols();
|
||||
int ptsStride = _points.step();
|
||||
|
||||
CV_Assert(!_clusterCenters.empty() && _clusterCenters.depth() == CV_32F);
|
||||
int nClusters = _clusterCenters.rows();
|
||||
int clusterCenterStride = _clusterCenters.step();
|
||||
|
||||
CV_Assert(_clusterCenters.cols() == nDims);
|
||||
|
||||
CV_Assert(numPointsUsed <= nPts);
|
||||
if (numPointsUsed < 0)
|
||||
{
|
||||
numPointsUsed = nPts;
|
||||
}
|
||||
|
||||
_newClusterCenters.create(nClusters, nDims, CV_32FC1);
|
||||
_clusterSizes.create(1, nClusters, CV_32SC1);
|
||||
_clusterBindings.create(1, numPointsUsed, CV_32SC1);
|
||||
_clusterSumDists.create(1, nClusters, CV_32FC1);
|
||||
|
||||
Mat points = _points.getMat();
|
||||
Mat clusterCenters = _clusterCenters.getMat();
|
||||
Mat newClusterCenters = _newClusterCenters.getMat();
|
||||
Mat clusterSizes = _clusterSizes.getMat();
|
||||
Mat clusterBindings = _clusterBindings.getMat();
|
||||
Mat clusterSumDists = _clusterSumDists.getMat();
|
||||
|
||||
int result = fcvClusterEuclideanu8(points.data,
|
||||
nPts,
|
||||
nDims,
|
||||
ptsStride,
|
||||
numPointsUsed,
|
||||
nClusters,
|
||||
(float32_t*)clusterCenters.data,
|
||||
clusterCenterStride,
|
||||
(float32_t*)newClusterCenters.data,
|
||||
(uint32_t*)clusterSizes.data,
|
||||
(uint32_t*)clusterBindings.data,
|
||||
(float32_t*)clusterSumDists.data);
|
||||
|
||||
if (result)
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, cv::format("Failed to clusterize, error code: %d", result));
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,372 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv { namespace fastcv {
|
||||
|
||||
static void fastcvColorWrapper(const Mat& src, Mat& dst, int code);
|
||||
|
||||
inline double heightFactor(int fmt /*420 / 422 / 444*/)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case 420: return 1.5; // YUV420 has 1.5× rows
|
||||
case 422: return 2.0; // YUV422 have 2× rows
|
||||
case 444: return 2.0; // YUV444 have 3× rows
|
||||
default: return 1.0; // packed RGB565/RGB888 → no extra plane
|
||||
}
|
||||
}
|
||||
|
||||
inline void getFormats(int code, int& srcFmt, int& dstFmt)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case COLOR_YUV2YUV444sp_NV12: srcFmt=420; dstFmt=444; break;
|
||||
case COLOR_YUV2YUV422sp_NV12: srcFmt=420; dstFmt=422; break;
|
||||
case COLOR_YUV422sp2YUV444sp: srcFmt=422; dstFmt=444; break;
|
||||
case COLOR_YUV422sp2YUV_NV12: srcFmt=422; dstFmt=420; break;
|
||||
case COLOR_YUV444sp2YUV422sp: srcFmt=444; dstFmt=422; break;
|
||||
case COLOR_YUV444sp2YUV_NV12: srcFmt=444; dstFmt=420; break;
|
||||
case COLOR_YUV2RGB565_NV12: srcFmt=420; dstFmt=565; break;
|
||||
case COLOR_YUV422sp2RGB565: srcFmt=422; dstFmt=565; break;
|
||||
case COLOR_YUV422sp2RGB: srcFmt=422; dstFmt=888; break;
|
||||
case COLOR_YUV422sp2RGBA:srcFmt=422; dstFmt=8888; break;
|
||||
case COLOR_YUV444sp2RGB565: srcFmt=444; dstFmt=565; break;
|
||||
case COLOR_YUV444sp2RGB: srcFmt=444; dstFmt=888; break;
|
||||
case COLOR_YUV444sp2RGBA:srcFmt=444; dstFmt=8888; break;
|
||||
case COLOR_RGB5652YUV444sp: srcFmt=565; dstFmt=444; break;
|
||||
case COLOR_RGB5652YUV422sp: srcFmt=565; dstFmt=422; break;
|
||||
case COLOR_RGB5652YUV_NV12: srcFmt=565; dstFmt=420; break;
|
||||
case COLOR_RGB2YUV444sp: srcFmt=888; dstFmt=444; break;
|
||||
case COLOR_RGB2YUV422sp: srcFmt=888; dstFmt=422; break;
|
||||
case COLOR_RGB2YUV_NV12: srcFmt=888; dstFmt=420; break;
|
||||
|
||||
default:
|
||||
CV_Error(Error::StsBadArg, "Unknown FastCV color-code");
|
||||
}
|
||||
}
|
||||
|
||||
void cvtColor( InputArray _src, OutputArray _dst, int code)
|
||||
{
|
||||
switch( code )
|
||||
{
|
||||
case COLOR_YUV2YUV444sp_NV12:
|
||||
case COLOR_YUV2YUV422sp_NV12:
|
||||
case COLOR_YUV422sp2YUV444sp:
|
||||
case COLOR_YUV422sp2YUV_NV12:
|
||||
case COLOR_YUV444sp2YUV422sp:
|
||||
case COLOR_YUV444sp2YUV_NV12:
|
||||
case COLOR_YUV2RGB565_NV12:
|
||||
case COLOR_YUV422sp2RGB565:
|
||||
case COLOR_YUV422sp2RGB:
|
||||
case COLOR_YUV422sp2RGBA:
|
||||
case COLOR_YUV444sp2RGB565:
|
||||
case COLOR_YUV444sp2RGB:
|
||||
case COLOR_YUV444sp2RGBA:
|
||||
case COLOR_RGB5652YUV444sp:
|
||||
case COLOR_RGB5652YUV422sp:
|
||||
case COLOR_RGB5652YUV_NV12:
|
||||
case COLOR_RGB2YUV444sp:
|
||||
case COLOR_RGB2YUV422sp:
|
||||
case COLOR_RGB2YUV_NV12:
|
||||
fastcvColorWrapper(_src.getMat(), _dst.getMatRef(), code);
|
||||
break;
|
||||
|
||||
default:
|
||||
CV_Error( cv::Error::StsBadFlag, "Unknown/unsupported color conversion code" );
|
||||
}
|
||||
}
|
||||
|
||||
void fastcvColorWrapper(const Mat& src, Mat& dst, int code)
|
||||
{
|
||||
CV_Assert(src.isContinuous());
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(src.data) % 16 == 0);
|
||||
|
||||
const uint32_t width = static_cast<uint32_t>(src.cols);
|
||||
int srcFmt, dstFmt;
|
||||
getFormats(code, srcFmt, dstFmt);
|
||||
|
||||
const double hFactorSrc = heightFactor(srcFmt);
|
||||
CV_Assert(std::fmod(src.rows, hFactorSrc) == 0.0);
|
||||
|
||||
const uint32_t height = static_cast<uint32_t>(src.rows / hFactorSrc); // Y-plane height we pass to FastCV
|
||||
|
||||
const uint8_t* srcY = src.data;
|
||||
const size_t srcYBytes = static_cast<size_t>(src.step) * height;
|
||||
const uint8_t* srcC = srcY + srcYBytes;
|
||||
const uint32_t srcStride = static_cast<uint32_t>(src.step);
|
||||
|
||||
const int dstRows = static_cast<int>(height * heightFactor(dstFmt)); // 1.5·H or 2·H
|
||||
|
||||
int dstType = CV_8UC1; // default for planar/semi-planar YUV formats (1 byte per pixel)
|
||||
|
||||
switch (dstFmt)
|
||||
{
|
||||
case 420: case 422: case 444:
|
||||
dstType = CV_8UC1;
|
||||
break;
|
||||
|
||||
case 565: // RGB565 – 16-bit packed RGB, 2 bytes per pixel
|
||||
dstType = CV_8UC2;
|
||||
break;
|
||||
|
||||
case 888: // RGB888 – 3 bytes per pixel
|
||||
dstType = CV_8UC3;
|
||||
break;
|
||||
|
||||
case 8888: // RGBA8888 – 4 bytes per pixel
|
||||
dstType = CV_8UC4;
|
||||
break;
|
||||
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, "Unsupported destination pixel format for FastCV");
|
||||
}
|
||||
|
||||
dst.create(dstRows, width, dstType);
|
||||
|
||||
CV_Assert(dst.isContinuous());
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(dst.data) % 16 == 0);
|
||||
|
||||
uint8_t* dstY = dst.data;
|
||||
uint8_t* dstC = dstY + static_cast<size_t>(dst.step) * height; // offset by Y-plane bytes
|
||||
const uint32_t dstStride = static_cast<uint32_t>(dst.step);
|
||||
|
||||
switch(code)
|
||||
{
|
||||
case COLOR_YUV2YUV444sp_NV12:
|
||||
{
|
||||
fcvColorYCbCr420PseudoPlanarToYCbCr444PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV2YUV422sp_NV12:
|
||||
{
|
||||
fcvColorYCbCr420PseudoPlanarToYCbCr422PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV422sp2YUV444sp:
|
||||
{
|
||||
fcvColorYCbCr422PseudoPlanarToYCbCr444PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV422sp2YUV_NV12:
|
||||
{
|
||||
fcvColorYCbCr422PseudoPlanarToYCbCr420PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV444sp2YUV422sp:
|
||||
{
|
||||
fcvColorYCbCr444PseudoPlanarToYCbCr422PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV444sp2YUV_NV12:
|
||||
{
|
||||
fcvColorYCbCr444PseudoPlanarToYCbCr420PseudoPlanaru8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB5652YUV444sp:
|
||||
{
|
||||
fcvColorRGB565ToYCbCr444PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB5652YUV422sp:
|
||||
{
|
||||
fcvColorRGB565ToYCbCr422PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB5652YUV_NV12:
|
||||
{
|
||||
fcvColorRGB565ToYCbCr420PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB2YUV444sp:
|
||||
{
|
||||
fcvColorRGB888ToYCbCr444PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB2YUV422sp:
|
||||
{
|
||||
fcvColorRGB888ToYCbCr422PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_RGB2YUV_NV12:
|
||||
{
|
||||
fcvColorRGB888ToYCbCr420PseudoPlanaru8(
|
||||
srcY,
|
||||
width, height,
|
||||
srcStride,
|
||||
dstY, dstC,
|
||||
dstStride, dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV2RGB565_NV12:
|
||||
{
|
||||
fcvColorYCbCr420PseudoPlanarToRGB565u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV422sp2RGB565:
|
||||
{
|
||||
fcvColorYCbCr422PseudoPlanarToRGB565u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV422sp2RGB:
|
||||
{
|
||||
fcvColorYCbCr422PseudoPlanarToRGB888u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV422sp2RGBA:
|
||||
{
|
||||
fcvColorYCbCr422PseudoPlanarToRGBA8888u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV444sp2RGB565:
|
||||
{
|
||||
fcvColorYCbCr444PseudoPlanarToRGB565u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV444sp2RGB:
|
||||
{
|
||||
fcvColorYCbCr444PseudoPlanarToRGB888u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLOR_YUV444sp2RGBA:
|
||||
{
|
||||
fcvColorYCbCr444PseudoPlanarToRGBA8888u8(
|
||||
srcY, srcC,
|
||||
width, height,
|
||||
srcStride, srcStride,
|
||||
dstY,
|
||||
dstStride
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, "Unsupported FastCV color code");
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace cv::fastcv
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
//CHANGE FASTCV Q6 INIT
|
||||
int fcvdspinit()
|
||||
{
|
||||
FastCvDspContext& context = FastCvDspContext::getContext();
|
||||
|
||||
if (context.isInitialized()) {
|
||||
CV_LOG_INFO(NULL, "FastCV DSP already initialized, skipping initialization");
|
||||
return 0;
|
||||
}
|
||||
if (!context.initialize()) {
|
||||
CV_LOG_ERROR(NULL, "Failed to initialize FastCV DSP");
|
||||
return -1;
|
||||
}
|
||||
CV_LOG_INFO(NULL, "FastCV DSP initialized successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fcvdspdeinit()
|
||||
{
|
||||
// Deinitialize the DSP environment
|
||||
FastCvDspContext& context = FastCvDspContext::getContext();
|
||||
|
||||
if (!context.isInitialized()) {
|
||||
CV_LOG_INFO(NULL, "FastCV DSP already deinitialized, skipping deinitialization");
|
||||
return;
|
||||
}
|
||||
if (!context.deinitialize()) {
|
||||
CV_LOG_ERROR(NULL, "Failed to deinitialize FastCV DSP");
|
||||
}
|
||||
CV_LOG_INFO(NULL, "FastCV DSP deinitialized successfully");
|
||||
}
|
||||
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace fastcv
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void sobel3x3u8(cv::InputArray _src, cv::OutputArray _dst, cv::OutputArray _dsty, int ddepth, bool normalization)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
|
||||
Size size = _src.size();
|
||||
_dst.create(size, ddepth);
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
if (_dsty.needed())
|
||||
{
|
||||
_dsty.create(size, ddepth);
|
||||
Mat dsty = _dsty.getMat();
|
||||
|
||||
switch(ddepth)
|
||||
{
|
||||
case CV_8S:
|
||||
if (normalization)
|
||||
fcvImageGradientSobelPlanars8_v2(src.data, src.cols, src.rows, src.step, (int8_t*)dst.data,
|
||||
(int8_t*)dsty.data, dst.step);
|
||||
else
|
||||
CV_Error(cv::Error::StsBadArg,
|
||||
cv::format("Depth: %d should do normalization, make sure the normalization parameter is true", ddepth));
|
||||
break;
|
||||
case CV_16S:
|
||||
if (normalization)
|
||||
fcvImageGradientSobelPlanars16_v2(src.data, src.cols, src.rows, src.step, (int16_t*)dst.data,
|
||||
(int16_t*)dsty.data, dst.step);
|
||||
else
|
||||
fcvImageGradientSobelPlanars16_v3(src.data, src.cols, src.rows, src.step, (int16_t*)dst.data,
|
||||
(int16_t*)dsty.data, dst.step);
|
||||
break;
|
||||
case CV_32F:
|
||||
if (normalization)
|
||||
fcvImageGradientSobelPlanarf32_v2(src.data, src.cols, src.rows, src.step, (float32_t*)dst.data,
|
||||
(float32_t*)dsty.data, dst.step);
|
||||
else
|
||||
fcvImageGradientSobelPlanarf32_v3(src.data, src.cols, src.rows, src.step, (float32_t*)dst.data,
|
||||
(float32_t*)dsty.data, dst.step);
|
||||
break;
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("depth: %d is not supported", ddepth));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fcvFilterSobel3x3u8_v2(src.data, src.cols, src.rows, src.step, dst.data, dst.step);
|
||||
}
|
||||
}
|
||||
|
||||
void sobel(cv::InputArray _src, cv::OutputArray _dx, cv::OutputArray _dy, int kernel_size, int borderType, int borderValue)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
Size size = _src.size();
|
||||
_dx.create( size, CV_16SC1);
|
||||
_dy.create( size, CV_16SC1);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat dx = _dx.getMat();
|
||||
Mat dy = _dy.getMat();
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
fcvBorderType fcvBorder;
|
||||
|
||||
switch (borderType)
|
||||
{
|
||||
case cv::BorderTypes::BORDER_CONSTANT:
|
||||
{
|
||||
fcvBorder = fcvBorderType::FASTCV_BORDER_CONSTANT;
|
||||
break;
|
||||
}
|
||||
case cv::BorderTypes::BORDER_REPLICATE:
|
||||
{
|
||||
fcvBorder = fcvBorderType::FASTCV_BORDER_REPLICATE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Border type: %d is not supported", borderType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (kernel_size)
|
||||
{
|
||||
case 3:
|
||||
status = fcvFilterSobel3x3u8s16(src.data, src.cols, src.rows, src.step, (int16_t*)dx.data, (int16_t*)dy.data,
|
||||
dx.step, fcvBorder, borderValue);
|
||||
break;
|
||||
case 5:
|
||||
status = fcvFilterSobel5x5u8s16(src.data, src.cols, src.rows, src.step, (int16_t*)dx.data, (int16_t*)dy.data,
|
||||
dx.step, fcvBorder, borderValue);
|
||||
break;
|
||||
case 7:
|
||||
status = fcvFilterSobel7x7u8s16(src.data, src.cols, src.rows, src.step, (int16_t*)dx.data, (int16_t*)dy.data,
|
||||
dx.step, fcvBorder, borderValue);
|
||||
break;
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Kernel size %d is not supported", kernel_size));
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
void Canny(InputArray _src, OutputArray _dst, int lowThreshold, int highThreshold, int apertureSize, bool L2gradient)
|
||||
{
|
||||
CV_Assert(
|
||||
!_src.empty() &&
|
||||
lowThreshold <= highThreshold &&
|
||||
IS_FASTCV_ALLOCATED(_src.getMat())
|
||||
);
|
||||
|
||||
int type = _src.type();
|
||||
CV_Assert(type == CV_8UC1);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Size size = _src.size();
|
||||
_dst.create(size, type);
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(src.step >= (size_t)src.cols);
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(src.data) % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(dst.data) % 8 == 0);
|
||||
CV_Assert(dst.step >= (size_t)src.cols);
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
fcvNormType norm;
|
||||
|
||||
if (L2gradient)
|
||||
norm = FASTCV_NORM_L2;
|
||||
else
|
||||
norm = FASTCV_NORM_L1;
|
||||
|
||||
int16_t* gx = (int16_t*)fcvHwMemAlloc(src.cols * src.rows * sizeof(int16_t), 16);
|
||||
int16_t* gy = (int16_t*)fcvHwMemAlloc(src.cols * src.rows * sizeof(int16_t), 16);
|
||||
uint32_t gstride = 2 * src.cols;
|
||||
fcvStatus status = fcvFilterCannyu8Q((uint8_t*)src.data, src.cols, src.rows, src.step, apertureSize, lowThreshold, highThreshold, norm, (uint8_t*)dst.data, dst.step, gx, gy, gstride);
|
||||
fcvHwMemFree(gx);
|
||||
fcvHwMemFree(gy);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error(cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void FAST10(InputArray _src, InputArray _mask, OutputArray _coords, OutputArray _scores, int barrier, int border, bool nmsEnabled)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.cols() <= 2048);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
// segfaults at border <= 3, fixing it
|
||||
border = std::max(4, border);
|
||||
|
||||
CV_Assert(_src.cols() > 2*border);
|
||||
CV_Assert(_src.rows() > 2*border);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
Mat mask;
|
||||
if (!_mask.empty())
|
||||
{
|
||||
CV_Assert(_mask.type() == CV_8UC1);
|
||||
float kw = (float)src.cols / (float)_mask.cols();
|
||||
float kh = (float)src.rows / (float)_mask.rows();
|
||||
float eps = std::numeric_limits<float>::epsilon();
|
||||
if (std::abs(kw - kh) > eps)
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "Mask proportions do not correspond to image proportions");
|
||||
}
|
||||
bool sizeFits = false;
|
||||
for (int k = -3; k <= 3; k++)
|
||||
{
|
||||
if (std::abs(kw - std::pow(2.f, (float)k)) < eps)
|
||||
{
|
||||
sizeFits = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sizeFits)
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "Mask size do not correspond to image size divided by k from -3 to 3");
|
||||
}
|
||||
|
||||
mask = _mask.getMat();
|
||||
}
|
||||
|
||||
CV_Assert(_coords.needed());
|
||||
|
||||
const int maxCorners = 32768;
|
||||
|
||||
Mat coords(1, maxCorners * 2, CV_32SC1);
|
||||
|
||||
AutoBuffer<uint32_t> tempBuf;
|
||||
Mat scores;
|
||||
if (_scores.needed())
|
||||
{
|
||||
scores.create(1, maxCorners, CV_32SC1);
|
||||
|
||||
tempBuf.allocate(maxCorners * 3 + src.rows + 1);
|
||||
}
|
||||
|
||||
uint32_t nCorners = maxCorners;
|
||||
|
||||
if (!mask.empty())
|
||||
{
|
||||
if (!scores.empty())
|
||||
{
|
||||
fcvCornerFast10InMaskScoreu8(src.data, src.cols, src.rows, src.step,
|
||||
barrier, border,
|
||||
(uint32_t*)coords.data, (uint32_t*)scores.data, maxCorners, &nCorners,
|
||||
mask.data, mask.cols, mask.rows,
|
||||
nmsEnabled,
|
||||
tempBuf.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
fcvCornerFast10InMasku8(src.data, src.cols, src.rows, src.step,
|
||||
barrier, border,
|
||||
(uint32_t*)coords.data, maxCorners, &nCorners,
|
||||
mask.data, mask.cols, mask.rows);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!scores.empty())
|
||||
{
|
||||
fcvCornerFast10Scoreu8(src.data, src.cols, src.rows, src.step,
|
||||
barrier, border,
|
||||
(uint32_t*)coords.data, (uint32_t*)scores.data, maxCorners, &nCorners,
|
||||
nmsEnabled,
|
||||
tempBuf.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
fcvCornerFast10u8(src.data, src.cols, src.rows, src.step,
|
||||
barrier, border,
|
||||
(uint32_t*)coords.data, maxCorners, &nCorners);
|
||||
}
|
||||
}
|
||||
|
||||
_coords.create(1, nCorners*2, CV_32SC1);
|
||||
coords(Range::all(), Range(0, nCorners*2)).copyTo(_coords);
|
||||
|
||||
if (_scores.needed())
|
||||
{
|
||||
scores(Range::all(), Range(0, nCorners)).copyTo(_scores);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
static bool isPow2(int x)
|
||||
{
|
||||
return x && (!(x & (x - 1)));
|
||||
}
|
||||
|
||||
void FFT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(isPow2(_src.rows()) || _src.rows() == 1);
|
||||
CV_Assert(isPow2(_src.cols()));
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_32FC2);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvStatus status = fcvFFTu8(src.data, src.cols, src.rows, src.step,
|
||||
(float*)dst.data, dst.step);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
void IFFT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_32FC2);
|
||||
CV_Assert(isPow2(_src.rows()) || _src.rows() == 1);
|
||||
CV_Assert(isPow2(_src.cols()));
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_8UC1);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvStatus status = fcvIFFTf32((const float*)src.data, src.cols * 2, src.rows, src.step,
|
||||
dst.data, dst.step);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
static bool isPow2(int x)
|
||||
{
|
||||
return x && (!(x & (x - 1)));
|
||||
}
|
||||
|
||||
void FFT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
CV_Assert(
|
||||
!_src.empty() &&
|
||||
_src.type() == CV_8UC1 &&
|
||||
IS_FASTCV_ALLOCATED(_src.getMat())
|
||||
);
|
||||
|
||||
CV_Assert(isPow2(_src.rows()) || _src.rows() == 1);
|
||||
CV_Assert(isPow2(_src.cols()));
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
CV_Assert(static_cast<unsigned long>(_src.rows() * _src.cols()) > MIN_REMOTE_BUF_SIZE);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(src.data) % 8 == 0);
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_32FC2);
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(dst.data) % 8 == 0);
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
fcvStatus status = fcvFFTu8Q(src.data, src.cols, src.rows, src.step,
|
||||
(float*)dst.data, dst.step);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error(cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
void IFFT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
CV_Assert(
|
||||
!_src.empty() &&
|
||||
_src.type() == CV_32FC2 &&
|
||||
IS_FASTCV_ALLOCATED(_src.getMat())
|
||||
);
|
||||
|
||||
CV_Assert(isPow2(_src.rows()) || _src.rows() == 1);
|
||||
CV_Assert(isPow2(_src.cols()));
|
||||
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
CV_Assert(static_cast<unsigned long>(_src.rows() * _src.cols() * sizeof(float32_t)) > MIN_REMOTE_BUF_SIZE);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(src.data) % 8 == 0);
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_8UC1);
|
||||
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(dst.data) % 8 == 0);
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
fcvStatus status = fcvIFFTf32Q((const float*)src.data, src.cols * 2, src.rows, src.step,
|
||||
dst.data, dst.step);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error(cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void fillConvexPoly(InputOutputArray _img, InputArray _pts, Scalar color)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_img.empty() && _img.depth() == CV_8U && _img.channels() <= 4);
|
||||
CV_Assert(_img.cols() % 8 == 0);
|
||||
CV_Assert(_img.step() % 8 == 0);
|
||||
|
||||
Mat img = _img.getMat();
|
||||
|
||||
CV_Assert(!_pts.empty() && (_pts.type() == CV_32SC1 || _pts.type() == CV_32SC2));
|
||||
CV_Assert(_pts.isContinuous());
|
||||
CV_Assert(_pts.total() * _pts.channels() % 2 == 0);
|
||||
|
||||
Mat pts = _pts.getMat();
|
||||
uint32_t nPts = pts.total() * pts.channels() / 2;
|
||||
|
||||
Vec4b coloru8 = color;
|
||||
|
||||
fcvFillConvexPolyu8(nPts, (const uint32_t*)pts.data,
|
||||
img.channels(), coloru8.val,
|
||||
img.data, img.cols, img.rows, img.step);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class FcvHistogramLoop_Invoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvHistogramLoop_Invoker(const uchar * src_data_, size_t src_step_, int width_, int height_, int32_t* gl_hist_, int stripeHeight_, cv::Mutex* histogramLock, int nStripes_):
|
||||
cv::ParallelLoopBody(), src_data(src_data_), src_step(src_step_), width(width_), height(height_), gl_hist(gl_hist_), stripeHeight(stripeHeight_), histogramLock_(histogramLock), nStripes(nStripes_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(const cv::Range& range) const CV_OVERRIDE
|
||||
{
|
||||
int height_ = stripeHeight;
|
||||
if(range.end == nStripes)
|
||||
height_ += (height % nStripes);
|
||||
const uchar* yS = src_data;
|
||||
int32_t l_hist[256] = {0};
|
||||
fcvImageIntensityHistogram(yS, src_step, 0, range.start, width, height_, l_hist);
|
||||
cv::AutoLock lock(*histogramLock_);
|
||||
|
||||
for( int i = 0; i < 256; i++ )
|
||||
gl_hist[i] += l_hist[i];
|
||||
}
|
||||
|
||||
private:
|
||||
const uchar * src_data;
|
||||
const size_t src_step;
|
||||
const int width;
|
||||
const int height;
|
||||
int32_t *gl_hist;
|
||||
int ret;
|
||||
int stripeHeight;
|
||||
cv::Mutex* histogramLock_;
|
||||
int nStripes;
|
||||
|
||||
FcvHistogramLoop_Invoker(const FcvHistogramLoop_Invoker &); // = delete;
|
||||
const FcvHistogramLoop_Invoker& operator= (const FcvHistogramLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void calcHist( InputArray _src, OutputArray _hist )
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty());
|
||||
int type = _src.type();
|
||||
CV_Assert(type == CV_8UC1);
|
||||
|
||||
_hist.create( cv::Size(256, 1), CV_32SC1 );
|
||||
Mat src = _src.getMat();
|
||||
Mat hist = _hist.getMat();
|
||||
|
||||
for( int i = 0; i < 256; i++ )
|
||||
hist.ptr<int>()[i] = 0;
|
||||
|
||||
cv::Mutex histogramLockInstance;
|
||||
|
||||
int nStripes = cv::getNumThreads();
|
||||
int stripeHeight = src.rows / nStripes;
|
||||
|
||||
cv::parallel_for_(cv::Range(0, nStripes),
|
||||
FcvHistogramLoop_Invoker(src.data, src.step[0], src.cols, src.rows, hist.ptr<int>(), stripeHeight, &histogramLockInstance, nStripes), nStripes);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void houghLines(InputArray _src, OutputArray _lines, double threshold)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
const uint32_t maxLines = 16384;
|
||||
|
||||
cv::Mat lines(1, maxLines, CV_32FC4);
|
||||
|
||||
uint32_t nLines = maxLines;
|
||||
|
||||
fcvHoughLineu8(src.data, src.cols, src.rows, src.step,
|
||||
(float)threshold, maxLines, &nLines, (fcvLine*)lines.data);
|
||||
|
||||
_lines.create(1, nLines, CV_32FC4);
|
||||
lines(Range::all(), Range(0, nLines)).copyTo(_lines);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void DCT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_16SC1);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvDCTu8(src.data, src.cols, src.rows, src.step, (short*)dst.data, dst.step);
|
||||
}
|
||||
|
||||
void IDCT(InputArray _src, OutputArray _dst)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_16SC1);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(_src.rows(), _src.cols(), CV_8UC1);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvIDCTs16((const short*)src.data, src.cols, src.rows, src.step, dst.data, dst.step);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
cv::Moments moments(InputArray _src, bool binary)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty());
|
||||
int type = _src.type();
|
||||
CV_Assert(type == CV_8UC1 || type == CV_32SC1 || type == CV_32FC1);
|
||||
|
||||
Size size = _src.size();
|
||||
Mat src = _src.getMat();
|
||||
|
||||
cv::Moments m;
|
||||
fcvMoments mFCV;
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
if(binary)
|
||||
{
|
||||
cv::Mat src_binary(size, CV_8UC1);
|
||||
cv::compare( src, 0, src_binary, cv::CMP_NE );
|
||||
fcvImageMomentsu8(src_binary.data, src_binary.cols,
|
||||
src_binary.rows, src_binary.step[0], &mFCV, binary);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CV_8UC1:
|
||||
fcvImageMomentsu8(src.data, src.cols, src.rows, src.step[0], &mFCV, binary);
|
||||
break;
|
||||
case CV_32SC1:
|
||||
fcvImageMomentss32(src.ptr<int>(), src.cols, src.rows, src.step[0], &mFCV, binary);
|
||||
break;
|
||||
case CV_32FC1:
|
||||
fcvImageMomentsf32(src.ptr<float>(), src.cols, src.rows, src.step[0], &mFCV, binary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
CV_Error( cv::Error::StsError, cv::format("Error occurred!") );
|
||||
return m;
|
||||
}
|
||||
|
||||
m.m00 = mFCV.m00; m.m10 = mFCV.m10; m.m01 = mFCV.m01;
|
||||
m.m20 = mFCV.m20; m.m11 = mFCV.m11; m.m02 = mFCV.m02;
|
||||
m.m30 = mFCV.m30; m.m21 = mFCV.m21; m.m12 = mFCV.m12;
|
||||
m.m03 = mFCV.m03; m.mu02 = mFCV.mu02; m.m03 = mFCV.mu03;
|
||||
m.mu11 = mFCV.mu11; m.mu12 = mFCV.mu12; m.mu20 = mFCV.mu20;
|
||||
m.mu21 = mFCV.mu21; m.mu30 = mFCV.mu30;
|
||||
|
||||
float32_t inv_m00 = 1.0/mFCV.m00;
|
||||
float32_t inv_sqrt_m00 = mFCV.inv_sqrt_m00;
|
||||
float32_t s2 = inv_m00 * inv_m00, s3 = s2 * inv_sqrt_m00;
|
||||
|
||||
m.nu20 = mFCV.mu20 * s2; m.nu11 = mFCV.mu11 * s2;
|
||||
m.nu02 = mFCV.mu02 * s2; m.nu30 = mFCV.mu30 * s3;
|
||||
m.nu21 = mFCV.mu21 * s3; m.nu12 = mFCV.mu12 * s3;
|
||||
m.nu03 = mFCV.mu03 * s3;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class MSER_Impl CV_FINAL : public cv::fastcv::FCVMSER
|
||||
{
|
||||
public:
|
||||
explicit MSER_Impl(cv::Size imgSize,
|
||||
int numNeighbors,
|
||||
int delta,
|
||||
int minArea,
|
||||
int maxArea,
|
||||
float maxVariation,
|
||||
float minDiversity);
|
||||
|
||||
~MSER_Impl() CV_OVERRIDE;
|
||||
|
||||
cv::Size getImgSize() CV_OVERRIDE { return imgSize; };
|
||||
int getNumNeighbors() CV_OVERRIDE { return numNeighbors; };
|
||||
int getDelta() CV_OVERRIDE { return delta; };
|
||||
int getMinArea() CV_OVERRIDE { return minArea; };
|
||||
int getMaxArea() CV_OVERRIDE { return maxArea; };
|
||||
float getMaxVariation() CV_OVERRIDE { return maxVariation; };
|
||||
float getMinDiversity() CV_OVERRIDE { return minDiversity; };
|
||||
|
||||
void detect(InputArray src, std::vector<std::vector<Point>>& contours) CV_OVERRIDE;
|
||||
void detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes) CV_OVERRIDE;
|
||||
void detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes,
|
||||
std::vector<ContourData>& contourData) CV_OVERRIDE;
|
||||
|
||||
void detectRegions(InputArray src,
|
||||
std::vector<std::vector<Point>>& contours,
|
||||
std::vector<cv::Rect>& boundingBoxes,
|
||||
std::vector<ContourData>& contourData,
|
||||
bool useBoundingBoxes = true,
|
||||
bool useContourData = true);
|
||||
|
||||
cv::Size imgSize;
|
||||
int numNeighbors;
|
||||
int delta;
|
||||
int minArea;
|
||||
int maxArea;
|
||||
float maxVariation;
|
||||
float minDiversity;
|
||||
|
||||
void *mserHandle;
|
||||
};
|
||||
|
||||
|
||||
MSER_Impl::MSER_Impl(cv::Size _imgSize,
|
||||
int _numNeighbors,
|
||||
int _delta,
|
||||
int _minArea,
|
||||
int _maxArea,
|
||||
float _maxVariation,
|
||||
float _minDiversity)
|
||||
{
|
||||
CV_Assert(_imgSize.width > 50);
|
||||
CV_Assert(_imgSize.height > 5);
|
||||
|
||||
CV_Assert(_numNeighbors == 4 || _numNeighbors == 8);
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
this->imgSize = _imgSize;
|
||||
this->numNeighbors = _numNeighbors;
|
||||
this->delta = _delta;
|
||||
this->minArea = _minArea;
|
||||
this->maxArea = _maxArea;
|
||||
this->maxVariation = _maxVariation;
|
||||
this->minDiversity = _minDiversity;
|
||||
|
||||
auto initFunc = (this->numNeighbors == 4) ? fcvMserInit : fcvMserNN8Init;
|
||||
|
||||
if (!initFunc(this->imgSize.width, this->imgSize.height, this->delta, this->minArea, this->maxArea,
|
||||
this->maxVariation, this->minDiversity, &this->mserHandle))
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, "Failed to initialize MSER");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MSER_Impl::~MSER_Impl()
|
||||
{
|
||||
fcvMserRelease(mserHandle);
|
||||
}
|
||||
|
||||
|
||||
void MSER_Impl::detectRegions(InputArray _src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes,
|
||||
std::vector<ContourData>& contourData, bool useBoundingBoxes, bool useContourData)
|
||||
{
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.size() == this->imgSize);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
bool usePointsArray = (this->numNeighbors == 8);
|
||||
|
||||
//bufSize for pts and bboxes
|
||||
const uint32_t maxContours = 16384;
|
||||
uint32_t numContours;
|
||||
std::vector<uint32_t> numPointsInContour(maxContours);
|
||||
|
||||
std::vector<uint16_t> rectArray;
|
||||
rectArray.resize(4 * maxContours); // xMin, xMax, yMax, yMin
|
||||
|
||||
uint32_t pointsArraySize = src.total() * 30; // Recommended typical size
|
||||
std::vector<uint16_t> pointsArray;
|
||||
std::vector<uint32_t> contourStartingPoints;
|
||||
uint32_t pathArraySize = src.total() * 4; // Recommended size
|
||||
std::vector<uint16_t> pathArray;
|
||||
if (usePointsArray)
|
||||
{
|
||||
pointsArray.resize(pointsArraySize);
|
||||
}
|
||||
else
|
||||
{
|
||||
contourStartingPoints.resize(maxContours);
|
||||
pathArray.resize(pathArraySize);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> contourVariation(maxContours), contourNodeId(maxContours), contourNodeCounter(maxContours);
|
||||
std::vector<int8_t> contourPolarity(maxContours);
|
||||
|
||||
int mserRetcode = -1;
|
||||
if (this->numNeighbors == 4)
|
||||
{
|
||||
mserRetcode = fcvMserExtu8_v3(mserHandle, src.data, src.cols, src.rows, src.step,
|
||||
maxContours, &numContours,
|
||||
rectArray.data(),
|
||||
contourStartingPoints.data(),
|
||||
numPointsInContour.data(),
|
||||
pathArraySize, pathArray.data(),
|
||||
contourVariation.data(), contourPolarity.data(), contourNodeId.data(), contourNodeCounter.data());
|
||||
CV_LOG_INFO(NULL, "fcvMserExtu8_v3");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (useContourData)
|
||||
{
|
||||
mserRetcode = fcvMserExtNN8u8(mserHandle, src.data, src.cols, src.rows, src.step,
|
||||
maxContours, &numContours,
|
||||
rectArray.data(),
|
||||
numPointsInContour.data(), pointsArraySize, pointsArray.data(),
|
||||
contourVariation.data(), contourPolarity.data(), contourNodeId.data(), contourNodeCounter.data());
|
||||
CV_LOG_INFO(NULL, "fcvMserExtNN8u8");
|
||||
}
|
||||
else
|
||||
{
|
||||
mserRetcode = fcvMserNN8u8(mserHandle, src.data, src.cols, src.rows, src.step,
|
||||
maxContours, &numContours,
|
||||
rectArray.data(),
|
||||
numPointsInContour.data(), pointsArraySize, pointsArray.data());
|
||||
CV_LOG_INFO(NULL, "fcvMserNN8u8");
|
||||
}
|
||||
}
|
||||
|
||||
if (mserRetcode != 1)
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, "Failed to run MSER");
|
||||
}
|
||||
|
||||
contours.clear();
|
||||
contours.reserve(numContours);
|
||||
if (useBoundingBoxes)
|
||||
{
|
||||
boundingBoxes.clear();
|
||||
boundingBoxes.reserve(numContours);
|
||||
}
|
||||
if (useContourData)
|
||||
{
|
||||
contourData.clear();
|
||||
contourData.reserve(numContours);
|
||||
}
|
||||
int ptCtr = 0;
|
||||
for (uint32_t i = 0; i < numContours; i++)
|
||||
{
|
||||
std::vector<Point> contour;
|
||||
contour.reserve(numPointsInContour[i]);
|
||||
for (uint32_t j = 0; j < numPointsInContour[i]; j++)
|
||||
{
|
||||
Point pt;
|
||||
if (usePointsArray)
|
||||
{
|
||||
uint32_t idx = (ptCtr + j) * 2;
|
||||
pt = Point {pointsArray[idx + 0], pointsArray[idx + 1]};
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t idx = contourStartingPoints[i] + j * 2;
|
||||
pt = Point {pathArray[idx + 0], pathArray[idx + 1]};
|
||||
}
|
||||
contour.push_back(pt);
|
||||
}
|
||||
contours.push_back(contour);
|
||||
ptCtr += numPointsInContour[i];
|
||||
|
||||
if (useBoundingBoxes)
|
||||
{
|
||||
uint16_t xMin = rectArray[i * 4 + 0];
|
||||
uint16_t xMax = rectArray[i * 4 + 1];
|
||||
uint16_t yMax = rectArray[i * 4 + 2];
|
||||
uint16_t yMin = rectArray[i * 4 + 3];
|
||||
// +1 is because max limit in cv::Rect() is exclusive
|
||||
cv::Rect bbox(Point {xMin, yMin},
|
||||
Point {xMax + 1, yMax + 1});
|
||||
boundingBoxes.push_back(bbox);
|
||||
}
|
||||
|
||||
if (useContourData)
|
||||
{
|
||||
ContourData data;
|
||||
data.variation = contourVariation[i];
|
||||
data.polarity = contourPolarity[i];
|
||||
data.nodeId = contourNodeId[i];
|
||||
data.nodeCounter = contourNodeCounter[i];
|
||||
contourData.push_back(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MSER_Impl::detect(InputArray src, std::vector<std::vector<Point>> &contours)
|
||||
{
|
||||
std::vector<cv::Rect> boundingBoxes;
|
||||
std::vector<ContourData> contourData;
|
||||
this->detectRegions(src, contours, boundingBoxes, contourData, /*useBoundingBoxes*/ false, /*useContourData*/ false);
|
||||
}
|
||||
|
||||
void MSER_Impl::detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes)
|
||||
{
|
||||
std::vector<ContourData> contourData;
|
||||
this->detectRegions(src, contours, boundingBoxes, contourData, /*useBoundingBoxes*/ true, /*useContourData*/ false);
|
||||
}
|
||||
|
||||
void MSER_Impl::detect(InputArray src, std::vector<std::vector<Point>>& contours, std::vector<cv::Rect>& boundingBoxes,
|
||||
std::vector<ContourData>& contourData)
|
||||
{
|
||||
this->detectRegions(src, contours, boundingBoxes, contourData, /*useBoundingBoxes*/ true, /*useContourData*/ true);
|
||||
}
|
||||
|
||||
Ptr<FCVMSER> FCVMSER::create(const cv::Size& imgSize,
|
||||
int numNeighbors,
|
||||
int delta,
|
||||
int minArea,
|
||||
int maxArea,
|
||||
float maxVariation,
|
||||
float minDiversity)
|
||||
{
|
||||
CV_Assert(numNeighbors > 0 && delta >= 0 && minArea >= 0 && maxArea >= 0);
|
||||
return makePtr<MSER_Impl>(imgSize, numNeighbors, delta, minArea, maxArea, maxVariation, minDiversity);
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef OPENCV_FASTCV_PRECOMP_HPP
|
||||
#define OPENCV_FASTCV_PRECOMP_HPP
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include "opencv2/core/private.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
#include <opencv2/fastcv.hpp>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
#include "fastcv.h"
|
||||
#include "fastcvDsp.h"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
#define INITIALIZATION_CHECK \
|
||||
{ \
|
||||
if (!FastCvContext::getContext().isInitialized) \
|
||||
{ \
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Set mode failed!")); \
|
||||
} \
|
||||
CV_INSTRUMENT_REGION(); \
|
||||
}
|
||||
|
||||
#define FCV_KernelSize_SHIFT 3
|
||||
#define FCV_MAKETYPE(ksize,depth) ((ksize<<FCV_KernelSize_SHIFT) + depth)
|
||||
#define MIN_REMOTE_BUF_SIZE 176*144*sizeof(uint8_t)
|
||||
|
||||
const std::map<fcvStatus, std::string> fcvStatusStrings =
|
||||
{
|
||||
{ FASTCV_SUCCESS, "Success"},
|
||||
{ FASTCV_EFAIL, "General failure"},
|
||||
{ FASTCV_EUNALIGNPARAM, "Unaligned pointer parameter"},
|
||||
{ FASTCV_EBADPARAM, "Bad parameters"},
|
||||
{ FASTCV_EINVALSTATE, "Called at invalid state"},
|
||||
{ FASTCV_ENORES, "Insufficient resources, memory, thread"},
|
||||
{ FASTCV_EUNSUPPORTED, "Unsupported feature"},
|
||||
{ FASTCV_EHWQDSP, "Hardware QDSP failed to respond"},
|
||||
{ FASTCV_EHWGPU, "Hardware GPU failed to respond"},
|
||||
};
|
||||
|
||||
struct FastCvContext
|
||||
{
|
||||
public:
|
||||
// initialize at first call
|
||||
// Defines a static local variable context. Variable is created only once.
|
||||
static FastCvContext& getContext()
|
||||
{
|
||||
static FastCvContext context;
|
||||
return context;
|
||||
}
|
||||
|
||||
FastCvContext()
|
||||
{
|
||||
if (fcvSetOperationMode(FASTCV_OP_CPU_PERFORMANCE) != 0)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to switch FastCV operation mode");
|
||||
isInitialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_INFO(NULL, "FastCV Operation Mode Switched");
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isInitialized;
|
||||
};
|
||||
|
||||
namespace dsp {
|
||||
struct FastCvDspContext;
|
||||
|
||||
#define IS_FASTCV_ALLOCATED(mat) \
|
||||
((mat.allocator == cv::fastcv::getQcAllocator()) ? true : \
|
||||
(CV_Error(cv::Error::StsBadArg, cv::format("Matrix '%s' not allocated with FastCV allocator. " \
|
||||
"Please ensure that the matrix is created using " \
|
||||
"cv::fastcv::getQcAllocator().", #mat)), false))
|
||||
|
||||
#define FASTCV_CHECK_DSP_INIT() \
|
||||
if (!FastCvDspContext::getContext().isInitialized() && \
|
||||
fcvdspinit() != 0) \
|
||||
{ \
|
||||
CV_Error(cv::Error::StsError, "Failed to initialize DSP"); \
|
||||
}
|
||||
|
||||
struct FastCvDspContext
|
||||
{
|
||||
private:
|
||||
mutable cv::Mutex initMutex;
|
||||
std::atomic<bool> isDspInitialized{false};
|
||||
std::atomic<uint64_t> initializationCount{0};
|
||||
std::atomic<uint64_t> deInitializationCount{0};
|
||||
|
||||
static FastCvDspContext& getInstanceImpl() {
|
||||
static FastCvDspContext context;
|
||||
return context;
|
||||
}
|
||||
public:
|
||||
static FastCvDspContext& getContext() {
|
||||
return getInstanceImpl();
|
||||
}
|
||||
|
||||
FastCvDspContext(const FastCvDspContext&) = delete;
|
||||
FastCvDspContext& operator=(const FastCvDspContext&) = delete;
|
||||
|
||||
bool initialize() {
|
||||
cv::AutoLock lock(initMutex);
|
||||
|
||||
if (isDspInitialized.load(std::memory_order_acquire)) {
|
||||
CV_LOG_INFO(NULL, "FastCV DSP already initialized, skipping initialization");
|
||||
return true;
|
||||
}
|
||||
|
||||
CV_LOG_INFO(NULL, "Initializing FastCV DSP");
|
||||
|
||||
if (fcvQ6Init() == 0) {
|
||||
isDspInitialized.store(true, std::memory_order_release);
|
||||
initializationCount++;
|
||||
CV_LOG_DEBUG(NULL, cv::format("FastCV DSP initialized (init count: %lu, deinit count: %lu)",
|
||||
initializationCount.load(), deInitializationCount.load()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CV_LOG_ERROR(NULL, "FastCV DSP initialization failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool deinitialize() {
|
||||
cv::AutoLock lock(initMutex);
|
||||
|
||||
if (!isDspInitialized.load(std::memory_order_acquire)) {
|
||||
CV_LOG_DEBUG(NULL, "FastCV DSP already deinitialized, skipping deinitialization");
|
||||
return true;
|
||||
}
|
||||
|
||||
CV_LOG_INFO(NULL, "Deinitializing FastCV DSP");
|
||||
|
||||
try {
|
||||
fcvQ6DeInit();
|
||||
isDspInitialized.store(false, std::memory_order_release);
|
||||
deInitializationCount++;
|
||||
CV_LOG_DEBUG(NULL, cv::format("FastCV DSP deinitialized (init count: %lu, deinit count: %lu)",
|
||||
initializationCount.load(), deInitializationCount.load()));
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
CV_LOG_ERROR(NULL, "Exception occurred during FastCV DSP deinitialization");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isInitialized() const {
|
||||
return isDspInitialized.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
uint64_t getDspInitCount() const {
|
||||
return initializationCount.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
uint64_t getDspDeInitCount() const {
|
||||
return deInitializationCount.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
const cv::Mutex& getInitMutex() const {
|
||||
return initMutex;
|
||||
}
|
||||
|
||||
private:
|
||||
FastCvDspContext() = default;
|
||||
};
|
||||
|
||||
} // namespace dsp
|
||||
} // namespace fastcv
|
||||
} // namespace cv
|
||||
|
||||
#endif // OPENCV_FASTCV_PRECOMP_HPP
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void sobelPyramid(InputArrayOfArrays _pyr, OutputArrayOfArrays _dx, OutputArrayOfArrays _dy, int outType)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(_pyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_pyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_pyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
CV_Assert(_dx.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_dx.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_dx.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
CV_Assert(_dy.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_dy.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_dy.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
|
||||
std::vector<cv::Mat> pyr;
|
||||
_pyr.getMatVector(pyr);
|
||||
size_t nLevels = pyr.size();
|
||||
|
||||
CV_Assert(!pyr.empty());
|
||||
|
||||
// this should be smaller I guess
|
||||
CV_Assert(nLevels > 0 && nLevels < 16);
|
||||
|
||||
for (size_t i = 0; i < nLevels; i++)
|
||||
{
|
||||
// fcvPyramidLeved does not support other cases
|
||||
CV_Assert(pyr[i].isContinuous());
|
||||
CV_Assert(pyr[i].type() == CV_8UC1);
|
||||
}
|
||||
|
||||
CV_Assert(outType == CV_8S || outType == CV_16S || outType == CV_32F);
|
||||
|
||||
std::vector<fcvPyramidLevel> lpyr;
|
||||
for (size_t i = 0; i < nLevels; i++)
|
||||
{
|
||||
fcvPyramidLevel lev;
|
||||
lev.width = pyr[i].cols;
|
||||
lev.height = pyr[i].rows;
|
||||
lev.ptr = pyr[i].data;
|
||||
lpyr.push_back(lev);
|
||||
}
|
||||
|
||||
std::vector<fcvPyramidLevel> ldx(nLevels), ldy(nLevels);
|
||||
int pyrElemSz = (outType == CV_8S ) ? 1 :
|
||||
(outType == CV_16S) ? 2 :
|
||||
(outType == CV_32F) ? 4 : 0;
|
||||
int retCodex = fcvPyramidAllocate(ldx.data(), pyr[0].cols, pyr[0].rows, pyrElemSz, nLevels, 1);
|
||||
if (retCodex != 0)
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, cv::format("fcvPyramidAllocate returned code %d", retCodex));
|
||||
}
|
||||
int retCodey = fcvPyramidAllocate(ldy.data(), pyr[0].cols, pyr[0].rows, pyrElemSz, nLevels, 1);
|
||||
if (retCodey != 0)
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, cv::format("fcvPyramidAllocate returned code %d", retCodey));
|
||||
}
|
||||
|
||||
int returnCode = -1;
|
||||
switch (outType)
|
||||
{
|
||||
case CV_8S: returnCode = fcvPyramidSobelGradientCreatei8 (lpyr.data(), ldx.data(), ldy.data(), nLevels);
|
||||
break;
|
||||
case CV_16S: returnCode = fcvPyramidSobelGradientCreatei16(lpyr.data(), ldx.data(), ldy.data(), nLevels);
|
||||
break;
|
||||
case CV_32F: returnCode = fcvPyramidSobelGradientCreatef32(lpyr.data(), ldx.data(), ldy.data(), nLevels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (returnCode != 0)
|
||||
{
|
||||
CV_Error(cv::Error::StsInternal, cv::format("FastCV returned code %d", returnCode));
|
||||
}
|
||||
|
||||
// resize arrays of Mats
|
||||
_dx.create(1, nLevels, /* type does not matter here */ -1, -1);
|
||||
_dy.create(1, nLevels, /* type does not matter here */ -1, -1);
|
||||
|
||||
for (size_t i = 0; i < nLevels; i++)
|
||||
{
|
||||
cv::Mat dx((int)ldx[i].height, (int)ldx[i].width, outType, (uchar*)ldx[i].ptr);
|
||||
_dx.create(pyr[i].size(), outType, i);
|
||||
dx.copyTo(_dx.getMat(i));
|
||||
|
||||
cv::Mat dy((int)ldy[i].height, (int)ldy[i].width, outType, (uchar*)ldy[i].ptr);
|
||||
_dy.create(pyr[i].size(), outType, i);
|
||||
dy.copyTo(_dy.getMat(i));
|
||||
}
|
||||
|
||||
fcvPyramidDelete(ldx.data(), nLevels, 0);
|
||||
fcvPyramidDelete(ldy.data(), nLevels, 0);
|
||||
}
|
||||
|
||||
|
||||
void buildPyramid(InputArray _src, OutputArrayOfArrays _pyr, int nLevels, bool scaleBy2, int borderType, uint8_t borderValue)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && (_src.type() == CV_8UC1 || _src.type() == CV_32FC1));
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
cv::Mat src = _src.getMat();
|
||||
bool useFloat = src.depth() == CV_32F;
|
||||
int bytesPerPixel = useFloat ? 4 : 1;
|
||||
|
||||
CV_Assert(_pyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_pyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_pyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
|
||||
// this should be smaller I guess
|
||||
CV_Assert(nLevels > 0 && nLevels < 16);
|
||||
|
||||
if (useFloat && !scaleBy2)
|
||||
{
|
||||
CV_Error( cv::Error::StsBadArg, "ORB scale is not supported for float images (fcvPyramidCreatef32_v2)");
|
||||
}
|
||||
|
||||
fcvPyramidScale scaleOption = scaleBy2 ? FASTCV_PYRAMID_SCALE_HALF : FASTCV_PYRAMID_SCALE_ORB;
|
||||
fcvBorderType borderOption;
|
||||
switch (borderType)
|
||||
{
|
||||
case cv::BORDER_REFLECT: borderOption = FASTCV_BORDER_REFLECT; break;
|
||||
case cv::BORDER_REFLECT_101: borderOption = FASTCV_BORDER_REFLECT_V2; break;
|
||||
case cv::BORDER_REPLICATE: borderOption = FASTCV_BORDER_REPLICATE; break;
|
||||
default: borderOption = FASTCV_BORDER_UNDEFINED; break;
|
||||
}
|
||||
|
||||
std::vector<fcvPyramidLevel_v2> lpyrSrc2(nLevels);
|
||||
|
||||
int alignment = 8;
|
||||
if (useFloat)
|
||||
{
|
||||
// use version 2
|
||||
CV_Assert(fcvPyramidAllocate_v2(lpyrSrc2.data(), src.cols, src.rows, src.step, bytesPerPixel, nLevels, 0) == 0);
|
||||
CV_Assert(fcvPyramidCreatef32_v2((const float*)src.data, src.cols, src.rows, src.step, nLevels, lpyrSrc2.data()) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use version 4
|
||||
fcvStatus statusAlloc = fcvPyramidAllocate_v3(lpyrSrc2.data(), src.cols, src.rows, src.step,
|
||||
bytesPerPixel, alignment, nLevels, scaleOption, 0);
|
||||
if (statusAlloc != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(statusAlloc) ? fcvStatusStrings.at(statusAlloc) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "fcvPyramidAllocate_v3 error: " + s);
|
||||
}
|
||||
|
||||
fcvStatus statusPyr = fcvPyramidCreateu8_v4(src.data, src.cols, src.rows, src.step, nLevels, scaleOption,
|
||||
lpyrSrc2.data(), borderOption, borderValue);
|
||||
if (statusPyr != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(statusPyr) ? fcvStatusStrings.at(statusPyr) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "fcvPyramidCreateu8_v4 error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
// create vector
|
||||
_pyr.create(nLevels, 1, src.type(), -1);
|
||||
for (int i = 0; i < nLevels; i++)
|
||||
{
|
||||
cv::Mat m = cv::Mat((uint32_t)lpyrSrc2[i].height, (uint32_t)lpyrSrc2[i].width,
|
||||
src.type(), (void*)lpyrSrc2[i].ptr, (size_t)lpyrSrc2[i].stride);
|
||||
|
||||
_pyr.create(m.size(), m.type(), i);
|
||||
m.copyTo(_pyr.getMat(i));
|
||||
}
|
||||
|
||||
fcvPyramidDelete_v2(lpyrSrc2.data(), nLevels, 1);
|
||||
}
|
||||
|
||||
} // namespace fastcv
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class RemapParallel : public cv::ParallelLoopBody {
|
||||
public:
|
||||
RemapParallel(int src_type, const uint8_t* src, uint32_t srcWidth, uint32_t srcHeight, uint32_t srcStride, uint8_t* dst,
|
||||
uint32_t dstWidth, uint32_t dstHeight, uint32_t dstStride, const float32_t* __restrict mapX,
|
||||
const float32_t* __restrict mapY, uint32_t mapStride, fcvInterpolationType interpolation, uint8_t borderValue)
|
||||
: src_type_(src_type), src_(src), srcWidth_(srcWidth), srcHeight_(srcHeight), srcStride_(srcStride), dst_(dst), dstWidth_(dstWidth),
|
||||
dstHeight_(dstHeight), dstStride_(dstStride), mapX_(mapX), mapY_(mapY), mapStride_(mapStride),
|
||||
fcvInterpolation_(interpolation), borderValue_(borderValue) {}
|
||||
|
||||
void operator()(const cv::Range& range) const override {
|
||||
CV_UNUSED(srcHeight_);
|
||||
CV_UNUSED(dstHeight_);
|
||||
int rangeHeight = range.end-range.start;
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
if(src_type_==CV_8UC1)
|
||||
{
|
||||
status = fcvRemapu8_v2(src_ + range.start*srcStride_, srcWidth_, rangeHeight, srcStride_, dst_ + range.start*dstStride_,
|
||||
srcWidth_, rangeHeight, dstStride_, mapX_, mapY_, mapStride_, fcvInterpolation_, FASTCV_BORDER_CONSTANT, borderValue_);
|
||||
}
|
||||
else if(src_type_==CV_8UC4)
|
||||
{
|
||||
if(fcvInterpolation_ == FASTCV_INTERPOLATION_TYPE_BILINEAR)
|
||||
{
|
||||
fcvRemapRGBA8888BLu8(src_ + range.start*srcStride_, srcWidth_, rangeHeight, srcStride_, dst_ + range.start*dstStride_, dstWidth_, rangeHeight,
|
||||
dstStride_, mapX_, mapY_, mapStride_);
|
||||
}
|
||||
else if(fcvInterpolation_ == FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR)
|
||||
{
|
||||
fcvRemapRGBA8888NNu8(src_ + range.start*srcStride_, srcWidth_, rangeHeight, srcStride_, dst_ + range.start*dstStride_, dstWidth_, rangeHeight,
|
||||
dstStride_, mapX_, mapY_, mapStride_);
|
||||
}
|
||||
}
|
||||
|
||||
if(status!=FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int src_type_;
|
||||
const uint8_t* src_;
|
||||
uint32_t srcWidth_;
|
||||
uint32_t srcHeight_;
|
||||
uint32_t srcStride_;
|
||||
uint8_t* dst_;
|
||||
uint32_t dstWidth_;
|
||||
uint32_t dstHeight_;
|
||||
uint32_t dstStride_;
|
||||
const float32_t* __restrict mapX_;
|
||||
const float32_t* __restrict mapY_;
|
||||
uint32_t mapStride_;
|
||||
fcvInterpolationType fcvInterpolation_;
|
||||
uint8_t borderValue_;
|
||||
};
|
||||
|
||||
void remap(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _map1, cv::InputArray _map2,
|
||||
int interpolation, int borderValue)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(_src.type() == CV_8UC1);
|
||||
CV_Assert(_map1.type()==CV_32FC1);
|
||||
CV_Assert(interpolation == cv::InterpolationFlags::INTER_NEAREST || interpolation == cv::InterpolationFlags::INTER_LINEAR);
|
||||
CV_Assert(!_map1.empty() && !_map2.empty());
|
||||
CV_Assert(_map1.size() == _map2.size());
|
||||
CV_Assert(borderValue >= 0 && borderValue < 256);
|
||||
|
||||
Size size = _map1.size();
|
||||
int type = _src.type();
|
||||
_dst.create( size, type);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat map1 = _map1.getMat();
|
||||
Mat map2 = _map2.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
CV_Assert(map1.step == map2.step);
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
fcvInterpolationType fcvInterpolation;
|
||||
|
||||
if(interpolation==cv::InterpolationFlags::INTER_NEAREST)
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
|
||||
else
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
|
||||
|
||||
|
||||
cv::parallel_for_(cv::Range(0, src.rows), RemapParallel(CV_8UC1, src.data, src.cols, src.rows, src.step, dst.data, dst.cols, dst.rows, dst.step,
|
||||
(float32_t*)map1.data, (float32_t*)map2.data, map1.step, fcvInterpolation, borderValue), (src.cols*src.rows)/(double)(1 << 16));
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
void remapRGBA(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _map1, cv::InputArray _map2, int interpolation)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(_src.type() == CV_8UC4);
|
||||
CV_Assert(_map1.type()==CV_32FC1);
|
||||
CV_Assert(interpolation == cv::InterpolationFlags::INTER_NEAREST || interpolation == cv::InterpolationFlags::INTER_LINEAR);
|
||||
CV_Assert(!_map1.empty() && !_map2.empty());
|
||||
CV_Assert(_map1.size() == _map2.size());
|
||||
|
||||
Size size = _map1.size();
|
||||
int type = _src.type();
|
||||
_dst.create( size, type);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat map1 = _map1.getMat();
|
||||
Mat map2 = _map2.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
CV_Assert(map1.step == map2.step);
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
fcvInterpolationType fcvInterpolation;
|
||||
|
||||
if(interpolation==cv::InterpolationFlags::INTER_NEAREST)
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
|
||||
else
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
|
||||
|
||||
cv::parallel_for_(cv::Range(0, src.rows), RemapParallel(CV_8UC4, src.data, src.cols, src.rows, src.step, dst.data, dst.cols, dst.rows, dst.step,
|
||||
(float32_t*)map1.data, (float32_t*)map2.data, map1.step, fcvInterpolation, 0), (src.cols*src.rows)/(double)(1 << 16) );
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
void sumOfAbsoluteDiffs(cv::InputArray _patch, cv::InputArray _src, cv::OutputArray _dst)
|
||||
{
|
||||
cv::Mat patch = _patch.getMat();
|
||||
cv::Mat src = _src.getMat();
|
||||
|
||||
// Check if matrices are allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(patch));
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(src));
|
||||
|
||||
CV_Assert(!_src.empty() && "src is empty");
|
||||
CV_Assert(_src.type() == CV_8UC1 && "src type is not CV_8UC1");
|
||||
CV_Assert(_src.step() * _src.rows() > MIN_REMOTE_BUF_SIZE && "src buffer size is too small");
|
||||
CV_Assert(!_patch.empty() && "patch is empty");
|
||||
CV_Assert(_patch.type() == CV_8UC1 && "patch type is not CV_8UC1");
|
||||
CV_Assert(_patch.size() == cv::Size(8, 8) && "patch size is not 8x8");
|
||||
|
||||
cv::Size size = _src.size();
|
||||
_dst.create(size, CV_16UC1);
|
||||
cv::Mat dst = _dst.getMat();
|
||||
|
||||
CV_Assert(((intptr_t)src.data & 0x7) == 0 && "src data is not 8-byte aligned");
|
||||
CV_Assert(((intptr_t)dst.data & 0x7) == 0 && "dst data is not 8-byte aligned");
|
||||
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
fcvSumOfAbsoluteDiffs8x8u8_v2Q((uint8_t*)patch.data, patch.step, (uint8_t*)src.data, src.cols, src.rows, src.step, (uint16_t*)dst.data, dst.step);
|
||||
}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void resizeDown(cv::InputArray _src, cv::OutputArray _dst, Size dsize, double inv_scale_x, double inv_scale_y)
|
||||
{
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
Size ssize = _src.size();
|
||||
|
||||
CV_Assert(!_src.empty() );
|
||||
CV_Assert( _src.type() == CV_8UC1 || _src.type() == CV_8UC2 );
|
||||
|
||||
if( dsize.empty() )
|
||||
{
|
||||
CV_Assert(inv_scale_x > 0);
|
||||
CV_Assert(inv_scale_y > 0);
|
||||
dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
|
||||
saturate_cast<int>(ssize.height*inv_scale_y));
|
||||
CV_Assert( !dsize.empty() );
|
||||
}
|
||||
else
|
||||
{
|
||||
inv_scale_x = static_cast<double>(dsize.width) / ssize.width;
|
||||
inv_scale_y = static_cast<double>(dsize.height) / ssize.height;
|
||||
CV_Assert(inv_scale_x > 0);
|
||||
CV_Assert(inv_scale_y > 0);
|
||||
}
|
||||
|
||||
CV_Assert(dsize.width <= ssize.width && dsize.height <= ssize.height);
|
||||
|
||||
CV_Assert(dsize.width * 20 > ssize.width);
|
||||
CV_Assert(dsize.height * 20 > ssize.height);
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(dsize, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// Alignment checks
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(src.data) % 16 == 0);
|
||||
CV_Assert(reinterpret_cast<uintptr_t>(dst.data) % 16 == 0);
|
||||
|
||||
if(src.type() == CV_8UC2)
|
||||
{
|
||||
fcvScaleDownMNInterleaveu8((const uint8_t*)src.data, src.cols, src.rows, src.step, (uint8_t*)dst.data, dst.cols, dst.rows, dst.step);
|
||||
}
|
||||
else if (src.cols/dst.cols == 4 && src.rows/dst.rows == 4 && src.cols % dst.cols == 0 && src.rows % dst.rows == 0)
|
||||
{
|
||||
CV_Assert(src.rows % 4 == 0);
|
||||
status = (fcvStatus)fcvScaleDownBy4u8_v2((const uint8_t*)src.data, src.cols, src.rows, src.step, (uint8_t*)dst.data, dst.step);
|
||||
}
|
||||
else if (src.cols/dst.cols == 2 && src.rows/dst.rows == 2 && src.cols % dst.cols == 0 && src.rows % dst.rows == 0)
|
||||
{
|
||||
CV_Assert(src.rows % 2 == 0);
|
||||
status = (fcvStatus)fcvScaleDownBy2u8_v2((const uint8_t*)src.data, src.cols, src.rows, src.step, (uint8_t*)dst.data, dst.step);
|
||||
}
|
||||
else
|
||||
{
|
||||
fcvScaleDownMNu8((const uint8_t*)src.data, src.cols, src.rows, src.step, (uint8_t*)dst.data, dst.cols, dst.rows, dst.step);
|
||||
}
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error(cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
int meanShift(InputArray _src, Rect& rect, TermCriteria termCrit)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && (_src.type() == CV_8UC1 || _src.type() == CV_32SC1 || _src.type() == CV_32FC1));
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
fcvRectangleInt window;
|
||||
window.x = rect.x;
|
||||
window.y = rect.y;
|
||||
window.width = rect.width;
|
||||
window.height = rect.height;
|
||||
|
||||
fcvTermCriteria criteria;
|
||||
criteria.epsilon = (termCrit.type & TermCriteria::EPS) ? termCrit.epsilon : 0;
|
||||
criteria.max_iter = (termCrit.type & TermCriteria::COUNT) ? termCrit.maxCount : 1024;
|
||||
uint32_t nIterations = 0;
|
||||
if (src.depth() == CV_8U)
|
||||
{
|
||||
nIterations = fcvMeanShiftu8(src.data, src.cols, src.rows, src.step,
|
||||
&window, criteria);
|
||||
}
|
||||
else if (src.depth() == CV_32S)
|
||||
{
|
||||
nIterations = fcvMeanShifts32((const int *)src.data, src.cols, src.rows, src.step,
|
||||
&window, criteria);
|
||||
}
|
||||
else if (src.depth() == CV_32F)
|
||||
{
|
||||
nIterations = fcvMeanShiftf32((const float*)src.data, src.cols, src.rows, src.step,
|
||||
&window, criteria);
|
||||
}
|
||||
|
||||
rect.x = window.x;
|
||||
rect.y = window.y;
|
||||
rect.width = window.width;
|
||||
rect.height = window.height;
|
||||
|
||||
return nIterations;
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void bilateralRecursive(cv::InputArray _src, cv::OutputArray _dst, float sigmaColor, float sigmaSpace)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Size size = _src.size();
|
||||
int type = _src.type();
|
||||
_dst.create(size, type);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvStatus status = fcvBilateralFilterRecursiveu8(src.data, src.cols, src.rows, src.step,
|
||||
dst.data, dst.step, sigmaColor, sigmaSpace);
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
void thresholdRange(InputArray _src, OutputArray _dst, int lowThresh, int highThresh, int trueValue, int falseValue)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(lowThresh >= 0 && lowThresh < 256);
|
||||
CV_Assert(highThresh >= 0 && highThresh < 256);
|
||||
CV_Assert(falseValue >= 0 && falseValue < 256);
|
||||
CV_Assert(trueValue >= 0 && trueValue < 256);
|
||||
|
||||
CV_Assert(lowThresh <= highThresh);
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(_src.size(), CV_8UC1);
|
||||
// in case of fixed layout array we cannot fix this on our side, can only fail if false
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
fcvStatus status = fcvFilterThresholdRangeu8_v2(src.data, src.cols, src.rows, src.step,
|
||||
dst.data, dst.step,
|
||||
lowThresh, highThresh, trueValue, falseValue);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
namespace dsp {
|
||||
|
||||
void thresholdOtsu(InputArray _src, OutputArray _dst, bool type)
|
||||
{
|
||||
CV_Assert(
|
||||
!_src.empty() &&
|
||||
_src.type() == CV_8UC1 &&
|
||||
IS_FASTCV_ALLOCATED(_src.getMat())
|
||||
);
|
||||
|
||||
CV_Assert((_src.step() * _src.rows()) > MIN_REMOTE_BUF_SIZE);
|
||||
CV_Assert(_src.cols() % 8 == 0);
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert(((uintptr_t)src.data & 0x7) == 0);
|
||||
|
||||
_dst.create(_src.size(), CV_8UC1);
|
||||
CV_Assert(_dst.step() % 8 == 0);
|
||||
CV_Assert(_dst.cols() % 8 == 0);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
// Check if dst is allocated by the QcAllocator
|
||||
CV_Assert(IS_FASTCV_ALLOCATED(dst));
|
||||
CV_Assert(((uintptr_t)dst.data & 0x7) == 0);
|
||||
|
||||
if (src.data == dst.data) {
|
||||
CV_Assert(src.step == dst.step);
|
||||
}
|
||||
|
||||
// Check DSP initialization status and initialize if needed
|
||||
FASTCV_CHECK_DSP_INIT();
|
||||
|
||||
fcvThreshType threshType;
|
||||
|
||||
if (type)
|
||||
threshType = FCV_THRESH_BINARY_INV;
|
||||
else
|
||||
threshType = FCV_THRESH_BINARY;
|
||||
|
||||
fcvFilterThresholdOtsuu8Q(src.data, src.cols, src.rows, src.step, dst.data, dst.step, threshType);
|
||||
}
|
||||
|
||||
} // dsp::
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
static void trackOpticalFlowLKInternal(InputArray _src, InputArray _dst,
|
||||
InputArrayOfArrays _srcPyr, InputArrayOfArrays _dstPyr,
|
||||
InputArrayOfArrays _srcDxPyr, InputArrayOfArrays _srcDyPyr,
|
||||
InputArray _ptsIn, OutputArray _ptsOut, InputArray _ptsEst,
|
||||
OutputArray _statusVec, cv::Size winSize,
|
||||
cv::TermCriteria termCriteria)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
CV_Assert(winSize.width % 2 == 1 && winSize.height % 2 == 1);
|
||||
|
||||
CV_Assert(!_src.empty() && _src.type() == CV_8UC1);
|
||||
CV_Assert(!_dst.empty() && _dst.type() == CV_8UC1);
|
||||
CV_Assert(_src.size() == _dst.size());
|
||||
CV_Assert(_src.step() % 8 == 0);
|
||||
CV_Assert(_dst.step() == _src.step());
|
||||
|
||||
cv::Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
CV_Assert(_srcPyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_srcPyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_srcPyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
CV_Assert(_dstPyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_dstPyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_dstPyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
CV_Assert(_srcPyr.size() == _dstPyr.size());
|
||||
|
||||
int nLevels = _srcPyr.size().area();
|
||||
|
||||
std::vector<cv::Mat> srcPyr, dstPyr;
|
||||
_srcPyr.getMatVector(srcPyr);
|
||||
_dstPyr.getMatVector(dstPyr);
|
||||
|
||||
cv::Size imSz = src.size();
|
||||
for (int i = 0; i < nLevels; i++)
|
||||
{
|
||||
const cv::Mat& s = srcPyr[i];
|
||||
const cv::Mat& d = dstPyr[i];
|
||||
|
||||
CV_Assert(!s.empty() && s.type() == CV_8UC1);
|
||||
CV_Assert(!d.empty() && d.type() == CV_8UC1);
|
||||
CV_Assert(s.size() == imSz);
|
||||
CV_Assert(d.size() == imSz);
|
||||
|
||||
imSz.width /= 2; imSz.height /= 2;
|
||||
}
|
||||
|
||||
bool useDxDy = !_srcDxPyr.empty() && !_srcDyPyr.empty();
|
||||
int version = useDxDy ? 1 : 3;
|
||||
|
||||
std::vector<cv::Mat> srcDxPyr, srcDyPyr;
|
||||
if (version == 1)
|
||||
{
|
||||
CV_Assert(_srcDxPyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_srcDxPyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_srcDxPyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
CV_Assert(_srcDyPyr.kind() == _InputArray::KindFlag::STD_ARRAY_MAT ||
|
||||
_srcDyPyr.kind() == _InputArray::KindFlag::STD_VECTOR_MAT ||
|
||||
_srcDyPyr.kind() == _InputArray::KindFlag::STD_VECTOR_UMAT);
|
||||
|
||||
CV_Assert(_srcDxPyr.size() == _srcDyPyr.size());
|
||||
_srcDxPyr.getMatVector(srcDxPyr);
|
||||
_srcDyPyr.getMatVector(srcDyPyr);
|
||||
|
||||
imSz = src.size();
|
||||
for (int i = 0; i < nLevels; i++)
|
||||
{
|
||||
const cv::Mat& dx = srcDxPyr[i];
|
||||
const cv::Mat& dy = srcDyPyr[i];
|
||||
|
||||
CV_Assert(!dx.empty() && dx.type() == CV_8SC1);
|
||||
CV_Assert(!dy.empty() && dy.type() == CV_8SC1);
|
||||
CV_Assert(dx.size() == imSz);
|
||||
CV_Assert(dy.size() == imSz);
|
||||
|
||||
imSz.width /= 2; imSz.height /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<fcvPyramidLevel> lpyrSrc1, lpyrDst1, lpyrDxSrc, lpyrDySrc;
|
||||
std::vector<fcvPyramidLevel_v2> lpyrSrc2, lpyrDst2;
|
||||
for (int i = 0; i < nLevels; i++)
|
||||
{
|
||||
fcvPyramidLevel lsrc1, ldst1;
|
||||
fcvPyramidLevel_v2 lsrc2, ldst2;
|
||||
lsrc1.width = srcPyr[i].cols;
|
||||
lsrc1.height = srcPyr[i].rows;
|
||||
lsrc1.ptr = srcPyr[i].data;
|
||||
|
||||
lsrc2.width = srcPyr[i].cols;
|
||||
lsrc2.height = srcPyr[i].rows;
|
||||
lsrc2.stride = srcPyr[i].step;
|
||||
lsrc2.ptr = srcPyr[i].data;
|
||||
|
||||
ldst1.width = dstPyr[i].cols;
|
||||
ldst1.height = dstPyr[i].rows;
|
||||
ldst1.ptr = dstPyr[i].data;
|
||||
ldst2.width = dstPyr[i].cols;
|
||||
ldst2.height = dstPyr[i].rows;
|
||||
ldst2.stride = dstPyr[i].step;
|
||||
ldst2.ptr = dstPyr[i].data;
|
||||
lpyrSrc1.push_back(lsrc1); lpyrDst1.push_back(ldst1);
|
||||
lpyrSrc2.push_back(lsrc2); lpyrDst2.push_back(ldst2);
|
||||
|
||||
if (version == 1)
|
||||
{
|
||||
fcvPyramidLevel ldx, ldy;
|
||||
CV_Assert(srcDxPyr[i].isContinuous());
|
||||
ldx.width = srcDxPyr[i].cols;
|
||||
ldx.height = srcDxPyr[i].rows;
|
||||
ldx.ptr = srcDxPyr[i].data;
|
||||
CV_Assert(srcDyPyr[i].isContinuous());
|
||||
ldy.width = srcDyPyr[i].cols;
|
||||
ldy.height = srcDyPyr[i].rows;
|
||||
ldy.ptr = srcDyPyr[i].data;
|
||||
lpyrDxSrc.push_back(ldx); lpyrDySrc.push_back(ldy);
|
||||
}
|
||||
}
|
||||
|
||||
CV_Assert(!_ptsIn.empty() && (_ptsIn.type() == CV_32FC1 || _ptsIn.type() == CV_32FC2));
|
||||
CV_Assert(_ptsIn.isContinuous());
|
||||
CV_Assert(_ptsIn.total() * _ptsIn.channels() % 2 == 0);
|
||||
|
||||
cv::Mat ptsIn = _ptsIn.getMat();
|
||||
int nPts = ptsIn.total() * ptsIn.channels() / 2;
|
||||
|
||||
bool useInitialEstimate;
|
||||
cv::Mat ptsEst;
|
||||
const float32_t* ptsEstData;
|
||||
if (!_ptsEst.empty())
|
||||
{
|
||||
CV_Assert(_ptsEst.type() == CV_32FC1 || _ptsEst.type() == CV_32FC2);
|
||||
CV_Assert(_ptsEst.isContinuous());
|
||||
int estElems = _ptsEst.total() * _ptsEst.channels();
|
||||
CV_Assert(estElems % 2 == 0);
|
||||
CV_Assert(estElems / 2 == nPts);
|
||||
|
||||
ptsEst = _ptsEst.getMat();
|
||||
ptsEstData = (const float32_t*)ptsEst.data;
|
||||
useInitialEstimate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
useInitialEstimate = false;
|
||||
ptsEstData = (const float32_t*)ptsIn.data;
|
||||
}
|
||||
|
||||
CV_Assert(_ptsOut.needed());
|
||||
_ptsOut.create(1, nPts, CV_32FC2);
|
||||
cv::Mat ptsOut = _ptsOut.getMat();
|
||||
|
||||
cv::Mat statusVec;
|
||||
if (!_statusVec.empty())
|
||||
{
|
||||
_statusVec.create(1, nPts, CV_32SC1);
|
||||
statusVec = _statusVec.getMat();
|
||||
}
|
||||
else
|
||||
{
|
||||
statusVec = cv::Mat(1, nPts, CV_32SC1);
|
||||
}
|
||||
|
||||
fcvTerminationCriteria termCrit;
|
||||
if (termCriteria.type & cv::TermCriteria::COUNT)
|
||||
{
|
||||
if (termCriteria.type & cv::TermCriteria::EPS)
|
||||
{
|
||||
termCrit = FASTCV_TERM_CRITERIA_BOTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
termCrit = FASTCV_TERM_CRITERIA_ITERATIONS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (termCriteria.type & cv::TermCriteria::EPS)
|
||||
{
|
||||
termCrit = FASTCV_TERM_CRITERIA_EPSILON;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "Incorrect termination criteria");
|
||||
}
|
||||
}
|
||||
int maxIterations = termCriteria.maxCount;
|
||||
double maxEpsilon = termCriteria.epsilon;
|
||||
|
||||
fcvStatus status = FASTCV_SUCCESS;
|
||||
|
||||
if (version == 3)
|
||||
{
|
||||
status = fcvTrackLKOpticalFlowu8_v3(src.data, dst.data, src.cols, src.rows, src.step,
|
||||
lpyrSrc2.data(), lpyrDst2.data(),
|
||||
(const float32_t*)ptsIn.data,
|
||||
ptsEstData,
|
||||
(float32_t*)ptsOut.data,
|
||||
(int32_t*)statusVec.data,
|
||||
nPts,
|
||||
winSize.width, winSize.height,
|
||||
nLevels,
|
||||
termCrit, maxIterations, maxEpsilon,
|
||||
useInitialEstimate);
|
||||
}
|
||||
else // if (version == 1)
|
||||
{
|
||||
CV_Assert(src.isContinuous() && dst.isContinuous());
|
||||
// Obsolete parameters, set to 0
|
||||
float maxResidue = 0, minDisplacement = 0, minEigenvalue = 0;
|
||||
int lightingNormalized = 0;
|
||||
fcvTrackLKOpticalFlowu8(src.data, dst.data, src.cols, src.rows,
|
||||
lpyrSrc1.data(), lpyrDst1.data(),
|
||||
lpyrDxSrc.data(), lpyrDySrc.data(),
|
||||
(const float32_t*)ptsIn.data,
|
||||
(float32_t*)ptsOut.data,
|
||||
(int32_t*)statusVec.data,
|
||||
nPts,
|
||||
winSize.width, winSize.height,
|
||||
maxIterations,
|
||||
nLevels,
|
||||
maxResidue, minDisplacement, minEigenvalue, lightingNormalized);
|
||||
}
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error( cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void trackOpticalFlowLK(InputArray _src, InputArray _dst,
|
||||
InputArrayOfArrays _srcPyr, InputArrayOfArrays _dstPyr,
|
||||
InputArray _ptsIn, OutputArray _ptsOut, InputArray _ptsEst,
|
||||
OutputArray _statusVec, cv::Size winSize,
|
||||
cv::TermCriteria termCriteria)
|
||||
{
|
||||
trackOpticalFlowLKInternal(_src, _dst, _srcPyr, _dstPyr, noArray(), noArray(),
|
||||
_ptsIn, _ptsOut, _ptsEst,
|
||||
_statusVec, winSize,
|
||||
termCriteria);
|
||||
}
|
||||
|
||||
void trackOpticalFlowLK(InputArray _src, InputArray _dst,
|
||||
InputArrayOfArrays _srcPyr, InputArrayOfArrays _dstPyr,
|
||||
InputArrayOfArrays _srcDxPyr, InputArrayOfArrays _srcDyPyr,
|
||||
InputArray _ptsIn, OutputArray _ptsOut,
|
||||
OutputArray _statusVec, cv::Size winSize, int maxIterations)
|
||||
{
|
||||
trackOpticalFlowLKInternal(_src, _dst, _srcPyr, _dstPyr,
|
||||
_srcDxPyr, _srcDyPyr,
|
||||
_ptsIn, _ptsOut, cv::noArray(),
|
||||
_statusVec, winSize,
|
||||
{cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,
|
||||
maxIterations, /* maxEpsilon */ 0.03f * 0.03f});
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
} // namespace fastcv
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv {
|
||||
namespace fastcv {
|
||||
|
||||
class FcvWarpPerspectiveLoop_Invoker : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
|
||||
FcvWarpPerspectiveLoop_Invoker(const Mat& _src1, const Mat& _src2, Mat& _dst1, Mat& _dst2,
|
||||
const float * _M, fcvInterpolationType _interpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR,
|
||||
fcvBorderType _borderType = fcvBorderType::FASTCV_BORDER_UNDEFINED, const int _borderValue = 0)
|
||||
: ParallelLoopBody(), src1(_src1), src2(_src2), dst1(_dst1), dst2(_dst2), M(_M), interpolation(_interpolation),
|
||||
borderType(_borderType), borderValue(_borderValue)
|
||||
{}
|
||||
|
||||
virtual void operator()(const cv::Range& range) const CV_OVERRIDE
|
||||
{
|
||||
uchar* dst1_ptr = dst1.data + range.start * dst1.step;
|
||||
int rangeHeight = range.end - range.start;
|
||||
|
||||
float rangeMatrix[9];
|
||||
rangeMatrix[0] = M[0];
|
||||
rangeMatrix[1] = M[1];
|
||||
rangeMatrix[2] = M[2]+range.start*M[1];
|
||||
rangeMatrix[3] = M[3];
|
||||
rangeMatrix[4] = M[4];
|
||||
rangeMatrix[5] = M[5]+range.start*M[4];
|
||||
rangeMatrix[6] = M[6];
|
||||
rangeMatrix[7] = M[7];
|
||||
rangeMatrix[8] = M[8]+range.start*M[7];
|
||||
|
||||
if ((src2.empty()) || (dst2.empty()))
|
||||
{
|
||||
fcvWarpPerspectiveu8_v5(src1.data, src1.cols, src1.rows, src1.step, src1.channels(), dst1_ptr, dst1.cols, rangeHeight,
|
||||
dst1.step, rangeMatrix, interpolation, borderType, borderValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar* dst2_ptr = dst2.data + range.start * dst2.step;
|
||||
fcv2PlaneWarpPerspectiveu8(src1.data, src2.data, src1.cols, src1.rows, src1.step, src2.step, dst1_ptr, dst2_ptr,
|
||||
dst1.cols, rangeHeight, dst1.step, dst2.step, rangeMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Mat& src1;
|
||||
const Mat& src2;
|
||||
Mat& dst1;
|
||||
Mat& dst2;
|
||||
const float* M;
|
||||
fcvInterpolationType interpolation;
|
||||
fcvBorderType borderType;
|
||||
int borderValue;
|
||||
|
||||
FcvWarpPerspectiveLoop_Invoker(const FcvWarpPerspectiveLoop_Invoker &); // = delete;
|
||||
const FcvWarpPerspectiveLoop_Invoker& operator= (const FcvWarpPerspectiveLoop_Invoker &); // = delete;
|
||||
};
|
||||
|
||||
void warpPerspective2Plane(InputArray _src1, InputArray _src2, OutputArray _dst1, OutputArray _dst2, InputArray _M0,
|
||||
Size dsize)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src1.empty() && _src1.type() == CV_8UC1);
|
||||
CV_Assert(!_src2.empty() && _src2.type() == CV_8UC1);
|
||||
CV_Assert(!_M0.empty());
|
||||
|
||||
Mat src1 = _src1.getMat();
|
||||
Mat src2 = _src2.getMat();
|
||||
|
||||
_dst1.create(dsize, src1.type());
|
||||
_dst2.create(dsize, src2.type());
|
||||
Mat dst1 = _dst1.getMat();
|
||||
Mat dst2 = _dst2.getMat();
|
||||
|
||||
Mat M0 = _M0.getMat();
|
||||
CV_Assert((M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3);
|
||||
float matrix[9];
|
||||
Mat M(3, 3, CV_32F, matrix);
|
||||
M0.convertTo(M, M.type());
|
||||
|
||||
int nThreads = getNumThreads();
|
||||
int nStripes = nThreads > 1 ? 2*nThreads : 1;
|
||||
|
||||
cv::parallel_for_(cv::Range(0, dsize.height),
|
||||
FcvWarpPerspectiveLoop_Invoker(src1, src2, dst1, dst2, matrix), nStripes);
|
||||
}
|
||||
|
||||
void warpPerspective(InputArray _src, OutputArray _dst, InputArray _M0, Size dsize, int interpolation, int borderType,
|
||||
const Scalar& borderValue)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat M0 = _M0.getMat();
|
||||
CV_Assert((M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3);
|
||||
float matrix[9];
|
||||
Mat M(3, 3, CV_32F, matrix);
|
||||
M0.convertTo(M, M.type());
|
||||
|
||||
// Do not support inplace case
|
||||
CV_Assert(src.data != dst.data);
|
||||
// Only support CV_8U
|
||||
CV_Assert(src.depth() == CV_8U);
|
||||
|
||||
INITIALIZATION_CHECK;
|
||||
|
||||
fcvBorderType fcvBorder;
|
||||
uint8_t fcvBorderValue = 0;
|
||||
fcvInterpolationType fcvInterpolation;
|
||||
|
||||
switch (borderType)
|
||||
{
|
||||
case BORDER_CONSTANT:
|
||||
{
|
||||
// Border value should be same
|
||||
CV_Assert((borderValue[0] == borderValue[1]) &&
|
||||
(borderValue[0] == borderValue[2]) &&
|
||||
(borderValue[0] == borderValue[3]));
|
||||
|
||||
fcvBorder = fcvBorderType::FASTCV_BORDER_CONSTANT;
|
||||
fcvBorderValue = static_cast<uint8_t>(borderValue[0]);
|
||||
break;
|
||||
}
|
||||
case BORDER_REPLICATE:
|
||||
{
|
||||
fcvBorder = fcvBorderType::FASTCV_BORDER_REPLICATE;
|
||||
break;
|
||||
}
|
||||
case BORDER_TRANSPARENT:
|
||||
{
|
||||
fcvBorder = fcvBorderType::FASTCV_BORDER_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Border type:%d is not supported", borderType));
|
||||
}
|
||||
|
||||
switch(interpolation)
|
||||
{
|
||||
case INTER_NEAREST:
|
||||
{
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
|
||||
break;
|
||||
}
|
||||
case INTER_LINEAR:
|
||||
{
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
|
||||
break;
|
||||
}
|
||||
case INTER_AREA:
|
||||
{
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_AREA;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, cv::format("Interpolation type:%d is not supported", interpolation));
|
||||
}
|
||||
|
||||
int nThreads = cv::getNumThreads();
|
||||
int nStripes = nThreads > 1 ? 2*nThreads : 1;
|
||||
|
||||
// placeholder
|
||||
Mat tmp;
|
||||
|
||||
cv::parallel_for_(cv::Range(0, dsize.height),
|
||||
FcvWarpPerspectiveLoop_Invoker(src, tmp, dst, tmp, matrix, fcvInterpolation, fcvBorder, fcvBorderValue), nStripes);
|
||||
}
|
||||
|
||||
void warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size dsize,
|
||||
int interpolation, int borderValue)
|
||||
{
|
||||
INITIALIZATION_CHECK;
|
||||
CV_Assert(!_src.empty());
|
||||
CV_Assert(!_M.empty());
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat M = _M.getMat();
|
||||
|
||||
CV_CheckEQ(M.rows, 2, "Affine Matrix must have 2 rows");
|
||||
CV_Check(M.cols, M.cols == 2 || M.cols == 3, "Affine Matrix must be 2x2 or 2x3");
|
||||
|
||||
if (M.rows == 2 && M.cols == 2)
|
||||
{
|
||||
CV_CheckTypeEQ(src.type(), CV_8UC1, "2x2 matrix transformation only supports CV_8UC1");
|
||||
|
||||
// Check if src is a ROI
|
||||
Size wholeSize;
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
bool isROI = (wholeSize.width > src.cols || wholeSize.height > src.rows);
|
||||
|
||||
Mat fullImage;
|
||||
Point2f center;
|
||||
|
||||
if (isROI)
|
||||
{
|
||||
center.x = ofs.x + src.cols / 2.0f;
|
||||
center.y = ofs.y + src.rows / 2.0f;
|
||||
|
||||
CV_Check(center.x, center.x >= 0 && center.x < wholeSize.width, "ROI center X is outside full image bounds");
|
||||
CV_Check(center.y, center.y >= 0 && center.y < wholeSize.height, "ROI center Y is outside full image bounds");
|
||||
|
||||
size_t offset = ofs.y * src.step + ofs.x * src.elemSize();
|
||||
fullImage = Mat(wholeSize, src.type(), src.data - offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use src as is, center at image center
|
||||
fullImage = src;
|
||||
center.x = src.cols / 2.0f;
|
||||
center.y = src.rows / 2.0f;
|
||||
|
||||
CV_LOG_WARNING(NULL, "2x2 matrix with non-ROI input. Using image center for patch extraction.");
|
||||
}
|
||||
|
||||
float affineMatrix[4] = {
|
||||
M.at<float>(0, 0), M.at<float>(0, 1),
|
||||
M.at<float>(1, 0), M.at<float>(1, 1)};
|
||||
|
||||
float position[2] = {center.x, center.y};
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
dst.step = dst.cols * src.elemSize();
|
||||
|
||||
int status = fcvTransformAffineu8_v2(
|
||||
(const uint8_t *)fullImage.data,
|
||||
fullImage.cols, fullImage.rows, fullImage.step,
|
||||
position,
|
||||
affineMatrix,
|
||||
(uint8_t *)dst.data,
|
||||
dst.cols, dst.rows, dst.step);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
CV_Error(Error::StsInternal, "FastCV patch extraction failed");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate 2x3 matrix for standard transformation
|
||||
CV_CheckEQ(M.cols, 3, "Matrix must be 2x3 for standard affine transformation");
|
||||
CV_Check(src.type(), src.type() == CV_8UC1 || src.type() == CV_8UC3, "Standard transformation supports CV_8UC1 or CV_8UC3");
|
||||
|
||||
float32_t affineMatrix[6] = {
|
||||
M.at<float>(0, 0), M.at<float>(0, 1), M.at<float>(0, 2),
|
||||
M.at<float>(1, 0), M.at<float>(1, 1), M.at<float>(1, 2)};
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
if (src.channels() == 1)
|
||||
{
|
||||
fcvStatus status;
|
||||
fcvInterpolationType fcvInterpolation;
|
||||
|
||||
switch (interpolation)
|
||||
{
|
||||
case cv::InterpolationFlags::INTER_NEAREST:
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
|
||||
break;
|
||||
case cv::InterpolationFlags::INTER_LINEAR:
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_BILINEAR;
|
||||
break;
|
||||
case cv::InterpolationFlags::INTER_AREA:
|
||||
fcvInterpolation = FASTCV_INTERPOLATION_TYPE_AREA;
|
||||
break;
|
||||
default:
|
||||
CV_Error(cv::Error::StsBadArg, "Unsupported interpolation type");
|
||||
}
|
||||
|
||||
status = fcvTransformAffineClippedu8_v3(
|
||||
(const uint8_t *)src.data, src.cols, src.rows, src.step,
|
||||
affineMatrix,
|
||||
(uint8_t *)dst.data, dst.cols, dst.rows, dst.step,
|
||||
NULL,
|
||||
fcvInterpolation,
|
||||
FASTCV_BORDER_CONSTANT,
|
||||
borderValue);
|
||||
|
||||
if (status != FASTCV_SUCCESS)
|
||||
{
|
||||
std::string s = fcvStatusStrings.count(status) ? fcvStatusStrings.at(status) : "unknown";
|
||||
CV_Error(cv::Error::StsInternal, "FastCV error: " + s);
|
||||
}
|
||||
}
|
||||
else if (src.channels() == 3)
|
||||
{
|
||||
CV_LOG_INFO(NULL, "warpAffine: 3-channel images use bicubic interpolation internally.");
|
||||
|
||||
std::vector<uint32_t> dstBorder;
|
||||
try
|
||||
{
|
||||
dstBorder.resize(dsize.height * 2);
|
||||
}
|
||||
catch (const std::bad_alloc &)
|
||||
{
|
||||
CV_Error(Error::StsNoMem, "Failed to allocate border array");
|
||||
}
|
||||
|
||||
fcv3ChannelTransformAffineClippedBCu8(
|
||||
(const uint8_t *)src.data, src.cols, src.rows, src.step[0],
|
||||
affineMatrix,
|
||||
(uint8_t *)dst.data, dst.cols, dst.rows, dst.step[0],
|
||||
dstBorder.data());
|
||||
}
|
||||
}
|
||||
|
||||
} // fastcv::
|
||||
} // cv::
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef std::tuple<int /*rows1*/, int /*cols1*/, int /*cols2*/> MatMulTestParams;
|
||||
class MatMulTest : public ::testing::TestWithParam<MatMulTestParams> {};
|
||||
|
||||
typedef std::tuple<Size, int /*depth*/, int /*op type*/> ArithmOpTestParams;
|
||||
class ArithmOpTest : public ::testing::TestWithParam<ArithmOpTestParams> {};
|
||||
|
||||
TEST_P(MatMulTest, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
int rows1 = std::get<0>(p);
|
||||
int cols1 = std::get<1>(p);
|
||||
int cols2 = std::get<2>(p);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src1(rows1, cols1, CV_8SC1), src2(cols1, cols2, CV_8SC1);
|
||||
cvtest::randUni(rng, src1, Scalar::all(-128), Scalar::all(128));
|
||||
cvtest::randUni(rng, src2, Scalar::all(-128), Scalar::all(128));
|
||||
|
||||
Mat dst;
|
||||
cv::fastcv::matmuls8s32(src1, src2, dst);
|
||||
Mat fdst;
|
||||
dst.convertTo(fdst, CV_32F);
|
||||
|
||||
Mat fsrc1, fsrc2;
|
||||
src1.convertTo(fsrc1, CV_32F);
|
||||
src2.convertTo(fsrc2, CV_32F);
|
||||
Mat ref;
|
||||
cv::gemm(fsrc1, fsrc2, 1.0, noArray(), 0, ref, 0);
|
||||
|
||||
double normInf = cvtest::norm(ref, fdst, cv::NORM_INF);
|
||||
double normL2 = cvtest::norm(ref, fdst, cv::NORM_L2);
|
||||
|
||||
EXPECT_EQ(normInf, 0);
|
||||
EXPECT_EQ(normL2, 0);
|
||||
|
||||
if (cvtest::debugLevel > 0 && (normInf > 0 || normL2 > 0))
|
||||
{
|
||||
std::ofstream of(cv::format("out_%d_%d_%d.txt", rows1, cols1, cols2));
|
||||
of << ref << std::endl;
|
||||
of << dst << std::endl;
|
||||
of.close();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ArithmOpTest, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
Size sz = std::get<0>(p);
|
||||
int depth = std::get<1>(p);
|
||||
int op = std::get<2>(p);
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src1(sz, depth), src2(sz, depth);
|
||||
|
||||
cvtest::randUni(rng, src1, Scalar::all(0), Scalar::all(128));
|
||||
cvtest::randUni(rng, src2, Scalar::all(0), Scalar::all(128));
|
||||
|
||||
Mat dst;
|
||||
cv::fastcv::arithmetic_op(src1, src2, dst, op);
|
||||
|
||||
Mat ref;
|
||||
if(op == 0)
|
||||
cv::add(src1, src2, ref);
|
||||
else if(op == 1)
|
||||
cv::subtract(src1, src2, ref);
|
||||
|
||||
double normInf = cvtest::norm(ref, dst, cv::NORM_INF);
|
||||
double normL2 = cvtest::norm(ref, dst, cv::NORM_L2);
|
||||
|
||||
EXPECT_EQ(normInf, 0);
|
||||
EXPECT_EQ(normL2, 0);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size>> IntegrateYUVTest;
|
||||
|
||||
TEST_P(IntegrateYUVTest, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
Size srcSize = std::get<0>(p);
|
||||
int depth = CV_8U;
|
||||
|
||||
cv::Mat Y(srcSize, depth), CbCr(srcSize.height/2, srcSize.width, depth);
|
||||
cv::Mat IY, ICb, ICr;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, Y, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, CbCr, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
cv::fastcv::integrateYUV(Y, CbCr, IY, ICb, ICr);
|
||||
|
||||
CbCr = CbCr.reshape(2,0);
|
||||
std::vector<cv::Mat> ref;
|
||||
cv::fastcv::split(CbCr, ref);
|
||||
|
||||
cv::Mat IY_ref, ICb_ref, ICr_ref;
|
||||
cv::integral(Y,IY_ref,CV_32S);
|
||||
cv::integral(ref[0],ICb_ref,CV_32S);
|
||||
cv::integral(ref[1],ICr_ref,CV_32S);
|
||||
|
||||
EXPECT_EQ(IY_ref.at<int>(IY_ref.rows - 1, IY_ref.cols - 1), IY.at<int>(IY.rows - 1, IY.cols - 1));
|
||||
EXPECT_EQ(ICb_ref.at<int>(ICb_ref.rows - 1, ICb_ref.cols - 1), ICb.at<int>(ICb.rows - 1, ICb.cols - 1));
|
||||
EXPECT_EQ(ICr_ref.at<int>(ICr_ref.rows - 1, ICr_ref.cols - 1), ICr.at<int>(ICr.rows - 1, ICr.cols - 1));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, MatMulTest,
|
||||
::testing::Combine(::testing::Values(8, 16, 128, 256), // rows1
|
||||
::testing::Values(8, 16, 128, 256), // cols1
|
||||
::testing::Values(8, 16, 128, 256))); // cols2
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, ArithmOpTest,
|
||||
::testing::Combine(::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p), // sz
|
||||
::testing::Values(CV_8U, CV_16S), // depth
|
||||
::testing::Values(0,1))); // op type
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, IntegrateYUVTest,
|
||||
Values(perf::szVGA, perf::sz720p, perf::sz1080p)); // sz
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef testing::TestWithParam<tuple<cv::Size,int,int>> fcv_bilateralFilterTest;
|
||||
|
||||
TEST_P(fcv_bilateralFilterTest, accuracy)
|
||||
{
|
||||
cv::Size size = get<0>(GetParam());
|
||||
int d = get<1>(GetParam());
|
||||
double sigmaColor = get<2>(GetParam());
|
||||
double sigmaSpace = sigmaColor;
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(size, CV_8UC1);
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
cv::Mat dst;
|
||||
|
||||
cv::fastcv::bilateralFilter(src, dst, d, sigmaColor, sigmaSpace);
|
||||
|
||||
EXPECT_FALSE(dst.empty());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, fcv_bilateralFilterTest, Combine(
|
||||
::testing::Values(Size(8, 8), Size(640, 480), Size(800, 600)),
|
||||
::testing::Values(5, 7, 9),
|
||||
::testing::Values(1., 10.)
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size, int, int, bool>> GaussianBlurTest;
|
||||
|
||||
TEST_P(GaussianBlurTest, accuracy)
|
||||
{
|
||||
cv::Size srcSize = get<0>(GetParam());
|
||||
int depth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
bool border = get<3>(GetParam());
|
||||
|
||||
// For some cases FastCV not support, so skip them
|
||||
if((ksize!=5) && (depth!=CV_8U))
|
||||
return;
|
||||
|
||||
cv::Mat src(srcSize, depth);
|
||||
cv::Mat dst,ref;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
cv::fastcv::gaussianBlur(src, dst, ksize, border);
|
||||
|
||||
if(depth == CV_32S)
|
||||
src.convertTo(src, CV_32F);
|
||||
cv::GaussianBlur(src,ref,Size(ksize,ksize),0,0,border);
|
||||
ref.convertTo(ref,depth);
|
||||
|
||||
cv::Mat difference;
|
||||
cv::absdiff(dst, ref, difference);
|
||||
|
||||
int num_diff_pixels = cv::countNonZero(difference);
|
||||
|
||||
EXPECT_LT(num_diff_pixels, (src.rows+src.cols)*ksize);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size, int, int>> Filter2DTest;
|
||||
|
||||
TEST_P(Filter2DTest, accuracy)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
|
||||
cv::Mat src(srcSize, CV_8U);
|
||||
cv::Mat kernel;
|
||||
cv::Mat dst, ref;
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
case CV_16S:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_8S);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_32F);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, kernel, Scalar::all(INT8_MIN), Scalar::all(INT8_MAX));
|
||||
|
||||
cv::fastcv::filter2D(src, dst, ddepth, kernel);
|
||||
cv::filter2D(src, ref, ddepth, kernel);
|
||||
|
||||
cv::Mat difference;
|
||||
dst.convertTo(dst, CV_8U);
|
||||
ref.convertTo(ref, CV_8U);
|
||||
cv::absdiff(dst, ref, difference);
|
||||
|
||||
int num_diff_pixels = cv::countNonZero(difference);
|
||||
EXPECT_LT(num_diff_pixels, (src.rows+src.cols)*ksize);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size, int>> SepFilter2DTest;
|
||||
|
||||
TEST_P(SepFilter2DTest, accuracy)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ksize = get<1>(GetParam());
|
||||
|
||||
cv::Mat src(srcSize, CV_8U);
|
||||
cv::Mat kernel(1,ksize,CV_8S);
|
||||
cv::Mat dst,ref;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, kernel, Scalar::all(INT8_MIN), Scalar::all(INT8_MAX));
|
||||
|
||||
cv::fastcv::sepFilter2D(src, dst, CV_8U, kernel, kernel);
|
||||
cv::sepFilter2D(src,ref,CV_8U,kernel,kernel);
|
||||
|
||||
cv::Mat difference;
|
||||
cv::absdiff(dst, ref, difference);
|
||||
int num_diff_pixels = cv::countNonZero(difference);
|
||||
EXPECT_LT(num_diff_pixels, (src.rows+src.cols)*ksize);
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<tuple<int>> NormalizeLocalBoxTest;
|
||||
|
||||
TEST_P(NormalizeLocalBoxTest, accuracy)
|
||||
{
|
||||
bool use_stddev = get<0>(GetParam());
|
||||
cv::Mat src, dst;
|
||||
src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
cv::fastcv::normalizeLocalBox(src, dst, Size(5,5), use_stddev);
|
||||
Scalar s = cv::mean(dst);
|
||||
|
||||
if(use_stddev)
|
||||
EXPECT_LT(s[0],1);
|
||||
else
|
||||
EXPECT_LT(s[0],50);
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, GaussianBlurTest, Combine(
|
||||
/*image size*/ ::testing::Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
/*image depth*/ ::testing::Values(CV_8U,CV_16S,CV_32S),
|
||||
/*kernel size*/ ::testing::Values(3, 5),
|
||||
/*blur border*/ ::testing::Values(true,false)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, Filter2DTest, Combine(
|
||||
/*image sie*/ Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
/*dst depth*/ Values(CV_8U,CV_16S,CV_32F),
|
||||
/*kernel size*/ Values(3, 5, 7, 9, 11)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, SepFilter2DTest, Combine(
|
||||
/*image size*/ Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
/*kernel size*/ Values(3, 5, 7, 9, 11)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, NormalizeLocalBoxTest, Values(0,1));
|
||||
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size, int, int>> Filter2DTest_DSP;
|
||||
|
||||
TEST_P(Filter2DTest_DSP, accuracy)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
int ksize = get<2>(GetParam());
|
||||
|
||||
cv::Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
src.create(srcSize, CV_8U);
|
||||
|
||||
cv::Mat kernel;
|
||||
cv::Mat dst, ref;
|
||||
kernel.allocator = cv::fastcv::getQcAllocator();
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
switch (ddepth)
|
||||
{
|
||||
case CV_8U:
|
||||
case CV_16S:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_8S);
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
kernel.create(ksize,ksize,CV_32F);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
cvtest::randUni(rng, kernel, Scalar::all(INT8_MIN), Scalar::all(INT8_MAX));
|
||||
|
||||
cv::fastcv::dsp::filter2D(src, dst, ddepth, kernel);
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
cv::filter2D(src, ref, ddepth, kernel);
|
||||
cv::Mat difference;
|
||||
dst.convertTo(dst, CV_8U);
|
||||
ref.convertTo(ref, CV_8U);
|
||||
cv::absdiff(dst, ref, difference);
|
||||
|
||||
int num_diff_pixels = cv::countNonZero(difference);
|
||||
EXPECT_LT(num_diff_pixels, (src.rows+src.cols)*ksize);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, Filter2DTest_DSP, Combine(
|
||||
/*image size*/ Values(perf::szVGA, perf::sz720p),
|
||||
/*dst depth*/ Values(CV_8U,CV_16S,CV_32F),
|
||||
/*kernel size*/ Values(3, 5, 7, 9, 11)
|
||||
));
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef std::tuple<Size, int> ChannelMergeTestParams;
|
||||
class ChannelMergeTest : public ::testing::TestWithParam<ChannelMergeTestParams> {};
|
||||
|
||||
typedef std::tuple<Size, int> ChannelSplitTestParams;
|
||||
class ChannelSplitTest : public ::testing::TestWithParam<ChannelSplitTestParams> {};
|
||||
|
||||
TEST_P(ChannelMergeTest, accuracy)
|
||||
{
|
||||
int depth = CV_8UC1;
|
||||
Size sz = std::get<0>(GetParam());
|
||||
int count = std::get<1>(GetParam());
|
||||
std::vector<Mat> src_mats;
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
Mat tmp(sz, depth);
|
||||
src_mats.push_back(tmp);
|
||||
cvtest::randUni(rng, src_mats[i], Scalar::all(0), Scalar::all(127));
|
||||
}
|
||||
|
||||
Mat dst;
|
||||
cv::fastcv::merge(src_mats, dst);
|
||||
|
||||
Mat ref;
|
||||
cv::merge(src_mats, ref);
|
||||
|
||||
double normInf = cvtest::norm(ref, dst, cv::NORM_INF);
|
||||
|
||||
EXPECT_EQ(normInf, 0);
|
||||
}
|
||||
|
||||
TEST_P(ChannelSplitTest, accuracy)
|
||||
{
|
||||
Size sz = std::get<0>(GetParam());
|
||||
int cn = std::get<1>(GetParam());
|
||||
std::vector<Mat> dst_mats(cn), ref_mats(cn);
|
||||
|
||||
RNG& rng = cv::theRNG();
|
||||
Mat src(sz, CV_MAKE_TYPE(CV_8U,cn));
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(127));
|
||||
|
||||
cv::fastcv::split(src, dst_mats);
|
||||
|
||||
cv::split(src, ref_mats);
|
||||
|
||||
for(int i=0; i<cn; i++)
|
||||
{
|
||||
double normInf = cvtest::norm(ref_mats[i], dst_mats[i], cv::NORM_INF);
|
||||
EXPECT_EQ(normInf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, ChannelMergeTest,
|
||||
::testing::Combine(::testing::Values(perf::szODD, perf::szVGA, perf::sz720p, perf::sz1080p), // sz
|
||||
::testing::Values(2,3,4))); // count
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, ChannelSplitTest,
|
||||
::testing::Combine(::testing::Values(perf::szODD, perf::szVGA, perf::sz720p, perf::sz1080p), // sz
|
||||
::testing::Values(2,3,4))); // cn
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
// nPts, nDims, nClusters
|
||||
typedef std::tuple<int, int, int> ClusterEuclideanTestParams;
|
||||
class ClusterEuclideanTest : public ::testing::TestWithParam<ClusterEuclideanTestParams> {};
|
||||
|
||||
TEST_P(ClusterEuclideanTest, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
int nPts = std::get<0>(p);
|
||||
int nDims = std::get<1>(p);
|
||||
int nClusters = std::get<2>(p);
|
||||
|
||||
Mat points(nPts, nDims, CV_8U);
|
||||
Mat clusterCenters(nClusters, nDims, CV_32F);
|
||||
|
||||
Mat trueMeans(nClusters, nDims, CV_32F);
|
||||
Mat stddevs(nClusters, nDims, CV_32F);
|
||||
std::vector<int> trueClusterSizes(nClusters, 0);
|
||||
std::vector<int> trueClusterBindings(nPts, 0);
|
||||
std::vector<float> trueSumDists(nClusters, 0);
|
||||
|
||||
cv::RNG& rng = cv::theRNG();
|
||||
for (int i = 0; i < nClusters; i++)
|
||||
{
|
||||
Mat mean(1, nDims, CV_64F), stdev(1, nDims, CV_64F);
|
||||
rng.fill(mean, cv::RNG::UNIFORM, 0, 256);
|
||||
rng.fill(stdev, cv::RNG::UNIFORM, 5.f, 16);
|
||||
int lo = i * nPts / nClusters;
|
||||
int hi = (i + 1) * nPts / nClusters;
|
||||
|
||||
for (int d = 0; d < nDims; d++)
|
||||
{
|
||||
rng.fill(points.col(d).rowRange(lo, hi), cv::RNG::NORMAL,
|
||||
mean.at<double>(d), stdev.at<double>(d));
|
||||
}
|
||||
|
||||
float sd = 0;
|
||||
for (int j = lo; j < hi; j++)
|
||||
{
|
||||
Mat pts64f;
|
||||
points.row(j).convertTo(pts64f, CV_64F);
|
||||
sd += cv::norm(mean, pts64f, NORM_L2);
|
||||
trueClusterBindings.at(j) = i;
|
||||
trueClusterSizes.at(i)++;
|
||||
}
|
||||
trueSumDists.at(i) = sd;
|
||||
|
||||
// let's shift initial cluster center a bit
|
||||
Mat(mean + stdev * 0.5).copyTo(clusterCenters.row(i));
|
||||
|
||||
mean.copyTo(trueMeans.row(i));
|
||||
stdev.copyTo(stddevs.row(i));
|
||||
}
|
||||
|
||||
Mat newClusterCenters;
|
||||
std::vector<int> clusterSizes, clusterBindings;
|
||||
std::vector<float> clusterSumDists;
|
||||
cv::fastcv::clusterEuclidean(points, clusterCenters, newClusterCenters, clusterSizes, clusterBindings, clusterSumDists);
|
||||
|
||||
if (cvtest::debugLevel > 0 && nDims == 2)
|
||||
{
|
||||
Mat draw(256, 256, CV_8UC3, Scalar(0));
|
||||
for (int i = 0; i < nPts; i++)
|
||||
{
|
||||
int x = std::rint(points.at<uchar>(i, 0));
|
||||
int y = std::rint(points.at<uchar>(i, 1));
|
||||
draw.at<Vec3b>(y, x) = Vec3b::all(128);
|
||||
}
|
||||
for (int i = 0; i < nClusters; i++)
|
||||
{
|
||||
float cx = trueMeans.at<double>(i, 0);
|
||||
float cy = trueMeans.at<double>(i, 1);
|
||||
draw.at<Vec3b>(cy, cx) = Vec3b(0, 255, 0);
|
||||
|
||||
float sx = stddevs.at<double>(i, 0);
|
||||
float sy = stddevs.at<double>(i, 1);
|
||||
cv::ellipse(draw, Point(cx, cy), Size(sx, sy), 0, 0, 360, Scalar(255, 0, 0));
|
||||
|
||||
float ox = clusterCenters.at<float>(i, 0);
|
||||
float oy = clusterCenters.at<float>(i, 1);
|
||||
draw.at<Vec3b>(oy, ox) = Vec3b(0, 0, 255);
|
||||
|
||||
float nx = newClusterCenters.at<float>(i, 0);
|
||||
float ny = newClusterCenters.at<float>(i, 1);
|
||||
draw.at<Vec3b>(ny, nx) = Vec3b(255, 255, 0);
|
||||
}
|
||||
cv::imwrite(cv::format("draw_%d_%d_%d.png", nPts, nDims, nClusters), draw);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<double> diffs;
|
||||
for (int i = 0; i < nClusters; i++)
|
||||
{
|
||||
double cs = std::abs((trueClusterSizes[i] - clusterSizes[i]) / double(trueClusterSizes[i]));
|
||||
diffs.push_back(cs);
|
||||
}
|
||||
double normL2 = cv::norm(diffs, NORM_L2) / nClusters;
|
||||
|
||||
EXPECT_LT(normL2, 0.392);
|
||||
}
|
||||
|
||||
{
|
||||
Mat bindings8u, trueBindings8u;
|
||||
Mat(clusterBindings).convertTo(bindings8u, CV_8U);
|
||||
Mat(trueClusterBindings).convertTo(trueBindings8u, CV_8U);
|
||||
double normH = cv::norm(bindings8u, trueBindings8u, NORM_HAMMING) / nPts;
|
||||
EXPECT_LT(normH, 0.66);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, ClusterEuclideanTest,
|
||||
::testing::Combine(::testing::Values(100, 1000, 10000), // nPts
|
||||
::testing::Values(2, 10, 32), // nDims
|
||||
::testing::Values(5, 10, 16))); // nClusters
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static inline void fillRandom8U(cv::Mat& m)
|
||||
{
|
||||
cv::RNG& rng = cv::theRNG();
|
||||
rng.fill(m, cv::RNG::UNIFORM, 0, 256);
|
||||
}
|
||||
|
||||
TEST(Fastcv_cvtColor, YUV420_to_YUV422_and_back_roundtrip)
|
||||
{
|
||||
const cv::Size sz(640, 480);
|
||||
|
||||
cv::Mat bgr(sz, CV_8UC3);
|
||||
fillRandom8U(bgr);
|
||||
|
||||
cv::Mat rgb;
|
||||
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
|
||||
|
||||
cv::Mat yuv420_before;
|
||||
yuv420_before.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(rgb, yuv420_before, cv::fastcv::COLOR_RGB2YUV_NV12);
|
||||
|
||||
cv::Mat yuv422;
|
||||
yuv422.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv420_before, yuv422, cv::fastcv::COLOR_YUV2YUV422sp_NV12);
|
||||
|
||||
cv::Mat yuv422_to_bgr;
|
||||
|
||||
cv::Mat yuv420_after;
|
||||
yuv420_after.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv422, yuv420_after, cv::fastcv::COLOR_YUV422sp2YUV_NV12);
|
||||
|
||||
ASSERT_EQ(yuv420_before.size(), yuv420_after.size());
|
||||
ASSERT_EQ(yuv420_before.type(), yuv420_after.type());
|
||||
|
||||
double maxDiff = cv::norm(yuv420_before, yuv420_after, cv::NORM_INF);
|
||||
std::cout << "Max difference YUV420 before vs after = " << maxDiff << std::endl;
|
||||
EXPECT_LE(maxDiff, 1.0);
|
||||
}
|
||||
|
||||
TEST(Fastcv_cvtColor, YUV444_to_YUV420_and_back_roundtrip)
|
||||
{
|
||||
const cv::Size sz(640, 480);
|
||||
|
||||
cv::Mat bgr(sz, CV_8UC3);
|
||||
fillRandom8U(bgr);
|
||||
cv::Mat rgb;
|
||||
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
|
||||
|
||||
cv::Mat yuv444_initial;
|
||||
yuv444_initial.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(rgb, yuv444_initial, cv::fastcv::COLOR_RGB2YUV444sp);
|
||||
|
||||
cv::Mat yuv420;
|
||||
yuv420.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv444_initial, yuv420, cv::fastcv::COLOR_YUV444sp2YUV_NV12);
|
||||
|
||||
cv::Mat yuv444_final;
|
||||
yuv444_final.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv420, yuv444_final, cv::fastcv::COLOR_YUV2YUV444sp_NV12);
|
||||
|
||||
ASSERT_EQ(yuv444_initial.size(), yuv444_final.size());
|
||||
ASSERT_EQ(yuv444_initial.type(), yuv444_final.type());
|
||||
|
||||
double maxDiff = cv::norm(yuv444_initial, yuv444_final, cv::NORM_INF);
|
||||
std::cout << "Max difference YUV444 before vs after roundtrip = " << maxDiff << std::endl;
|
||||
EXPECT_LE(maxDiff, 2.0);
|
||||
}
|
||||
|
||||
TEST(Fastcv_cvtColor, YUV444_to_YUV422_and_back_roundtrip)
|
||||
{
|
||||
const cv::Size sz(640, 480);
|
||||
|
||||
cv::Mat bgr(sz, CV_8UC3);
|
||||
fillRandom8U(bgr);
|
||||
cv::Mat rgb;
|
||||
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
|
||||
|
||||
cv::Mat yuv444_initial;
|
||||
yuv444_initial.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(rgb, yuv444_initial, cv::fastcv::COLOR_RGB2YUV444sp);
|
||||
|
||||
cv::Mat yuv422;
|
||||
yuv422.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv444_initial, yuv422, cv::fastcv::COLOR_YUV444sp2YUV422sp);
|
||||
|
||||
cv::Mat yuv444_final;
|
||||
yuv444_final.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv422, yuv444_final, cv::fastcv::COLOR_YUV422sp2YUV444sp);
|
||||
|
||||
ASSERT_EQ(yuv444_initial.size(), yuv444_final.size());
|
||||
ASSERT_EQ(yuv444_initial.type(), yuv444_final.type());
|
||||
|
||||
double maxDiff = cv::norm(yuv444_initial, yuv444_final, cv::NORM_INF);
|
||||
std::cout << "Max difference YUV444 before vs after roundtrip = " << maxDiff << std::endl;
|
||||
EXPECT_LE(maxDiff, 2.0);
|
||||
}
|
||||
|
||||
TEST(Fastcv_cvtColor, YUV444_to_RGB565_and_back_roundtrip)
|
||||
{
|
||||
const cv::Size sz(640, 480);
|
||||
cv::Mat bgr(sz, CV_8UC3);
|
||||
fillRandom8U(bgr);
|
||||
|
||||
cv::Mat rgb;
|
||||
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
|
||||
|
||||
cv::Mat yuv444_initial;
|
||||
yuv444_initial.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(rgb, yuv444_initial, cv::fastcv::COLOR_RGB2YUV444sp);
|
||||
|
||||
cv::Mat rgb565(sz, CV_8UC2);
|
||||
rgb565.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(yuv444_initial, rgb565, cv::fastcv::COLOR_YUV444sp2RGB565);
|
||||
|
||||
cv::Mat yuv444_roundtrip;
|
||||
yuv444_roundtrip.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::fastcv::cvtColor(rgb565, yuv444_roundtrip, cv::fastcv::COLOR_RGB5652YUV444sp);
|
||||
|
||||
ASSERT_EQ(yuv444_initial.size(), yuv444_roundtrip.size());
|
||||
ASSERT_EQ(yuv444_initial.type(), yuv444_roundtrip.type());
|
||||
|
||||
double maxDiff = cv::norm(yuv444_initial, yuv444_roundtrip, cv::NORM_INF);
|
||||
std::cout << "Max difference YUV444 after RGB565 roundtrip = " << maxDiff << std::endl;
|
||||
|
||||
EXPECT_LE(maxDiff, 2.0);
|
||||
}
|
||||
|
||||
}} // namespace opencv_test
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef testing::TestWithParam<tuple<Size, int, int, int>> Sobel;
|
||||
typedef testing::TestWithParam<tuple<Size, int>> Sobel3x3u8;
|
||||
|
||||
TEST_P(Sobel,accuracy)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ksize = get<1>(GetParam());
|
||||
int border = get<2>(GetParam());
|
||||
int borderValue = get<3>(GetParam());
|
||||
|
||||
cv::Mat dx, dy, src(srcSize, CV_8U), refx, refy;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
cv::fastcv::sobel(src, dx, dy, ksize, border, borderValue);
|
||||
|
||||
cv::Sobel(src, refx, CV_16S, 1, 0, ksize, 1.0, 0.0, border);
|
||||
cv::Sobel(src, refy, CV_16S, 0, 1, ksize, 1.0, 0.0, border);
|
||||
|
||||
cv::Mat difference_x, difference_y;
|
||||
cv::absdiff(dx, refx, difference_x);
|
||||
cv::absdiff(dy, refy, difference_y);
|
||||
|
||||
int num_diff_pixels_x = cv::countNonZero(difference_x);
|
||||
int num_diff_pixels_y = cv::countNonZero(difference_y);
|
||||
EXPECT_LT(num_diff_pixels_x, src.size().area()*0.1);
|
||||
EXPECT_LT(num_diff_pixels_y, src.size().area()*0.1);
|
||||
}
|
||||
|
||||
TEST_P(Sobel3x3u8,accuracy)
|
||||
{
|
||||
Size srcSize = get<0>(GetParam());
|
||||
int ddepth = get<1>(GetParam());
|
||||
|
||||
cv::Mat dx, dy, src(srcSize, CV_8U), refx, refy;
|
||||
RNG& rng = cv::theRNG();
|
||||
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
|
||||
|
||||
cv::fastcv::sobel3x3u8(src, dx, dy, ddepth, 0);
|
||||
cv::Sobel(src, refx, ddepth, 1, 0);
|
||||
cv::Sobel(src, refy, ddepth, 0, 1);
|
||||
|
||||
cv::Mat difference_x, difference_y;
|
||||
cv::absdiff(dx, refx, difference_x);
|
||||
cv::absdiff(dy, refy, difference_y);
|
||||
|
||||
int num_diff_pixels_x = cv::countNonZero(difference_x);
|
||||
int num_diff_pixels_y = cv::countNonZero(difference_y);
|
||||
EXPECT_LT(num_diff_pixels_x, src.size().area()*0.1);
|
||||
EXPECT_LT(num_diff_pixels_y, src.size().area()*0.1);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, Sobel, Combine(
|
||||
/*image size*/ Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
/*kernel size*/ Values(3,5,7),
|
||||
/*border*/ Values(BORDER_CONSTANT, BORDER_REPLICATE),
|
||||
/*border value*/ Values(0)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, Sobel3x3u8, Combine(
|
||||
/*image size*/ Values(perf::szVGA, perf::sz720p, perf::sz1080p),
|
||||
/*dst depth*/ Values(CV_16S, CV_32F)
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(DSP_CannyTest, accuracy)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_FASTCV_SKIP_DSP);
|
||||
|
||||
//Initialize DSP
|
||||
int initStatus = cv::fastcv::dsp::fcvdspinit();
|
||||
ASSERT_EQ(initStatus, 0) << "Failed to initialize FastCV DSP";
|
||||
|
||||
cv::Mat src;
|
||||
src.allocator = cv::fastcv::getQcAllocator();
|
||||
cv::imread(cvtest::findDataFile("cv/detectors_descriptors_evaluation/planar/box_in_scene.png"), src, cv::IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(src.empty()) << "Could not read the image file.";
|
||||
|
||||
cv::Mat dst;
|
||||
dst.allocator = cv::fastcv::getQcAllocator();
|
||||
|
||||
int lowThreshold = 0;
|
||||
int highThreshold = 150;
|
||||
|
||||
cv::fastcv::dsp::Canny(src, dst, lowThreshold, highThreshold, 3, true);
|
||||
|
||||
//De-Initialize DSP
|
||||
cv::fastcv::dsp::fcvdspdeinit();
|
||||
|
||||
EXPECT_FALSE(dst.empty());
|
||||
EXPECT_EQ(src.size(), dst.size());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef std::tuple<bool /*useScores*/, int /*barrier*/, int /*border*/, bool /*nmsEnabled*/> Fast10TestParams;
|
||||
class Fast10Test : public ::testing::TestWithParam<Fast10TestParams> {};
|
||||
|
||||
TEST_P(Fast10Test, accuracy)
|
||||
{
|
||||
auto p = GetParam();
|
||||
bool useScores = std::get<0>(p);
|
||||
int barrier = std::get<1>(p);
|
||||
int border = std::get<2>(p);
|
||||
bool nmsEnabled = std::get<3>(p);
|
||||
|
||||
cv::Mat src = imread(cvtest::findDataFile("cv/shared/baboon.png"), cv::IMREAD_GRAYSCALE);
|
||||
|
||||
std::vector<int> coords, scores;
|
||||
cv::fastcv::FAST10(src, noArray(), coords, useScores ? scores : noArray(), barrier, border, nmsEnabled);
|
||||
|
||||
std::vector<KeyPoint> ocvKeypoints;
|
||||
int thresh = barrier;
|
||||
cv::FAST(src, ocvKeypoints, thresh, nmsEnabled, FastFeatureDetector::DetectorType::TYPE_9_16 );
|
||||
|
||||
if (useScores)
|
||||
{
|
||||
ASSERT_EQ(scores.size() * 2, coords.size());
|
||||
}
|
||||
|
||||
Mat ptsMap(src.size(), CV_8U, Scalar(255));
|
||||
for(size_t i = 0; i < coords.size() / 2; ++i)
|
||||
{
|
||||
ptsMap.at<uchar>(coords[2*i + 1], coords[2*i + 0]) = 0;
|
||||
}
|
||||
Mat distTrans(src.size(), CV_8U);
|
||||
cv::distanceTransform(ptsMap, distTrans, DIST_L2, DIST_MASK_PRECISE);
|
||||
|
||||
Mat refPtsMap(src.size(), CV_8U, Scalar(255));
|
||||
for(size_t i = 0; i < ocvKeypoints.size(); ++i)
|
||||
{
|
||||
refPtsMap.at<uchar>(ocvKeypoints[i].pt) = 0;
|
||||
}
|
||||
Mat refDistTrans(src.size(), CV_8U);
|
||||
cv::distanceTransform(refPtsMap, refDistTrans, DIST_L2, DIST_MASK_PRECISE);
|
||||
|
||||
double normInf = cvtest::norm(refDistTrans, distTrans, cv::NORM_INF);
|
||||
double normL2 = cvtest::norm(refDistTrans, distTrans, cv::NORM_L2) / src.size().area();
|
||||
|
||||
EXPECT_LT(normInf, 129.7);
|
||||
EXPECT_LT(normL2, 0.067);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(FastCV_Extension, Fast10Test,
|
||||
::testing::Combine(::testing::Bool(), // useScores
|
||||
::testing::Values(10, 30, 50), // barrier
|
||||
::testing::Values( 4, 10, 32), // border
|
||||
::testing::Bool() // nonmax suppression
|
||||
));
|
||||
|
||||
}} // namespaces opencv_test, ::
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user