mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge branch 4.x
This commit is contained in:
@@ -81,7 +81,7 @@ pass in terms of square size).
|
||||
|
||||
So to find pattern in chess board, we can use the function, **cv.findChessboardCorners()**. We also
|
||||
need to pass what kind of pattern we are looking for, like 8x8 grid, 5x5 grid etc. In this example, we
|
||||
use 7x6 grid. (Normally a chess board has 8x8 squares and 7x7 internal corners). It returns the
|
||||
use 6x7 grid. (Normally a chess board has 8x8 squares and 7x7 internal corners). It returns the
|
||||
corner points and retval which will be True if pattern is obtained. These corners will be placed in
|
||||
an order (from left-to-right, top-to-bottom)
|
||||
|
||||
@@ -107,9 +107,11 @@ import glob
|
||||
# termination criteria
|
||||
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
|
||||
|
||||
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
|
||||
objp = np.zeros((6*7,3), np.float32)
|
||||
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
|
||||
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(5,6,0)
|
||||
cols = 6
|
||||
rows = 7
|
||||
objp = np.zeros((cols*rows,3), np.float32)
|
||||
objp[:,:2] = np.mgrid[0:cols,0:rows].T.reshape(-1,2)
|
||||
|
||||
# Arrays to store object points and image points from all the images.
|
||||
objpoints = [] # 3d point in real world space
|
||||
@@ -122,7 +124,7 @@ for fname in images:
|
||||
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
|
||||
# Find the chess board corners
|
||||
ret, corners = cv.findChessboardCorners(gray, (7,6), None)
|
||||
ret, corners = cv.findChessboardCorners(gray, (cols, rows), None)
|
||||
|
||||
# If found, add object points, image points (after refining them)
|
||||
if ret == True:
|
||||
@@ -132,7 +134,7 @@ for fname in images:
|
||||
imgpoints.append(corners2)
|
||||
|
||||
# Draw and display the corners
|
||||
cv.drawChessboardCorners(img, (7,6), corners2, ret)
|
||||
cv.drawChessboardCorners(img, (cols, rows), corners2, ret)
|
||||
cv.imshow('img', img)
|
||||
cv.waitKey(500)
|
||||
|
||||
|
||||
@@ -50,12 +50,14 @@ our X axis is drawn from (0,0,0) to (3,0,0), so for Y axis. For Z axis, it is dr
|
||||
(0,0,-3). Negative denotes it is drawn towards the camera.
|
||||
@code{.py}
|
||||
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
|
||||
objp = np.zeros((6*7,3), np.float32)
|
||||
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
|
||||
cols = 6
|
||||
rows = 7
|
||||
objp = np.zeros((cols*rows,3), np.float32)
|
||||
objp[:,:2] = np.mgrid[0:cols,0:rows].T.reshape(-1,2)
|
||||
|
||||
axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)
|
||||
@endcode
|
||||
Now, as usual, we load each image. Search for 7x6 grid. If found, we refine it with subcorner
|
||||
Now, as usual, we load each image. Search for 6x7 grid. If found, we refine it with subcorner
|
||||
pixels. Then to calculate the rotation and translation, we use the function,
|
||||
**cv.solvePnPRansac()**. Once we those transformation matrices, we use them to project our **axis
|
||||
points** to the image plane. In simple words, we find the points on image plane corresponding to
|
||||
@@ -65,7 +67,7 @@ to each of these points using our generateImage() function. Done !!!
|
||||
for fname in glob.glob('left*.jpg'):
|
||||
img = cv.imread(fname)
|
||||
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
|
||||
ret, corners = cv.findChessboardCorners(gray, (7,6),None)
|
||||
ret, corners = cv.findChessboardCorners(gray, (cols, rows), None)
|
||||
|
||||
if ret == True:
|
||||
corners2 = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
|
||||
|
||||
@@ -23,6 +23,10 @@ add_library(ipphal STATIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/matchtemplate_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/canny_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/threshold_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/distancetransform_ipp.cpp"
|
||||
)
|
||||
|
||||
#TODO: HAVE_IPP_ICV and HAVE_IPP_IW added as private macro till OpenCV itself is
|
||||
@@ -49,6 +53,7 @@ target_include_directories(ipphal PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||
${CMAKE_SOURCE_DIR}/modules/core/include
|
||||
${CMAKE_SOURCE_DIR}/modules/imgproc/include
|
||||
${CMAKE_SOURCE_DIR}/modules/geometry/include
|
||||
${IPP_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
@@ -52,13 +52,6 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 202600
|
||||
|
||||
int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height,
|
||||
uchar *dst_data, size_t dst_step, int dst_width, int dst_height,
|
||||
float* mapx, size_t mapx_step, float* mapy, size_t mapy_step,
|
||||
int interpolation, int border_type, const double border_value[4]);
|
||||
#undef cv_hal_remap32f
|
||||
#define cv_hal_remap32f ipp_hal_remap32f
|
||||
|
||||
#if defined(HAVE_IPP_IW)
|
||||
int ipp_hal_resize(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height,
|
||||
uchar *dst_data, size_t dst_step, int dst_width, int dst_height,
|
||||
@@ -77,6 +70,13 @@ int ipp_hal_boxFilter(const uchar* src_data, size_t src_step, uchar* dst_data, s
|
||||
#define cv_hal_boxFilter ipp_hal_boxFilter
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_BOX_FILTER
|
||||
|
||||
int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height,
|
||||
uchar *dst_data, size_t dst_step, int dst_width, int dst_height,
|
||||
float* mapx, size_t mapx_step, float* mapy, size_t mapy_step,
|
||||
int interpolation, int border_type, const double border_value[4]);
|
||||
#undef cv_hal_remap32f
|
||||
#define cv_hal_remap32f ipp_hal_remap32f
|
||||
|
||||
#if defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
int ipp_hal_filter2D(const uchar * src_data, size_t src_step, int src_type,
|
||||
uchar * dst_data, size_t dst_step, int dst_type,
|
||||
@@ -174,6 +174,42 @@ int ipp_hal_cvtLabtoBGR(const uchar * src_data, size_t src_step, uchar * dst_dat
|
||||
#define cv_hal_cvtLabtoBGR ipp_hal_cvtLabtoBGR
|
||||
#endif // !IPP_DISABLE_LAB_RGB
|
||||
|
||||
#endif //IPP_VERSION_X100 >= 700
|
||||
int ipp_hal_cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height);
|
||||
#undef cv_hal_cvtRGBAtoMultipliedRGBA
|
||||
#define cv_hal_cvtRGBAtoMultipliedRGBA ipp_hal_cvtRGBAtoMultipliedRGBA
|
||||
|
||||
int ipp_hal_matchTemplate(const uchar* src_data, size_t src_step, int src_width, int src_height,
|
||||
const uchar* templ_data, size_t templ_step, int templ_width, int templ_height,
|
||||
float* result_data, size_t result_step, int depth, int cn, int method);
|
||||
#undef cv_hal_matchTemplate
|
||||
#define cv_hal_matchTemplate ipp_hal_matchTemplate
|
||||
|
||||
int ipp_hal_threshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn, double thresh, double maxValue, int thresholdType);
|
||||
#undef cv_hal_threshold
|
||||
#define cv_hal_threshold ipp_hal_threshold
|
||||
|
||||
int ipp_hal_distanceTransform(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int dst_type, int dist_type, int mask_size);
|
||||
#undef cv_hal_distanceTransform
|
||||
#define cv_hal_distanceTransform ipp_hal_distanceTransform
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 700
|
||||
|
||||
#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better
|
||||
|
||||
#if defined(HAVE_IPP_IW)
|
||||
int ipp_hal_canny(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int cn,
|
||||
double lowThreshold, double highThreshold, int ksize, bool L2gradient);
|
||||
#undef cv_hal_canny
|
||||
#define cv_hal_canny ipp_hal_canny
|
||||
|
||||
int ipp_hal_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step,
|
||||
uchar* dst_data, size_t dst_step, int width, int height, int cn,
|
||||
double lowThreshold, double highThreshold, bool L2gradient);
|
||||
#undef cv_hal_canny_deriv
|
||||
#define cv_hal_canny_deriv ipp_hal_canny_deriv
|
||||
#endif
|
||||
|
||||
#endif //__IPP_HAL_IMGPROC_HPP__
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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
|
||||
// Copyright (C) 2026, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "ipp_hal_imgproc.hpp"
|
||||
|
||||
#ifdef HAVE_IPP_IW
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "precomp_ipp.hpp"
|
||||
|
||||
int ipp_hal_canny(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int cn,
|
||||
double lowThreshold, double highThreshold, int ksize, bool L2gradient)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
#if IPP_DISABLE_PERF_CANNY_MT
|
||||
if(cv::getNumThreads() > 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
if(width <= 3 || height <= 3)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(cn != 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
IppiMaskSize kernel;
|
||||
if(ksize == 3)
|
||||
kernel = ippMskSize3x3;
|
||||
else if(ksize == 5)
|
||||
kernel = ippMskSize5x5;
|
||||
else
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
IppNormType norm = L2gradient ? ippNormL2 : ippNormL1;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc, iwDst;
|
||||
iwSrc.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), (void*)src_data, IwSize(src_step));
|
||||
iwDst.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), dst_data, IwSize(dst_step));
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCanny, iwSrc, iwDst, (float)lowThreshold, (float)highThreshold,
|
||||
::ipp::IwiFilterCannyParams(ippFilterSobel, kernel, norm), ippBorderRepl);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int ipp_hal_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step,
|
||||
uchar* dst_data, size_t dst_step, int width, int height, int cn,
|
||||
double lowThreshold, double highThreshold, bool L2gradient)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
#if IPP_DISABLE_PERF_CANNY_MT
|
||||
if(cv::getNumThreads() > 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
if(width <= 3 || height <= 3)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(cn != 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
IppNormType norm = L2gradient ? ippNormL2 : ippNormL1;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrcDx, iwSrcDy, iwDst;
|
||||
iwSrcDx.Init(IwiSize{width, height}, ipp16s, cn, ::ipp::IwiBorderSize(), (void*)dx_data, IwSize(dx_step));
|
||||
iwSrcDy.Init(IwiSize{width, height}, ipp16s, cn, ::ipp::IwiBorderSize(), (void*)dy_data, IwSize(dy_step));
|
||||
iwDst.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), dst_data, IwSize(dst_step));
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCannyDeriv, iwSrcDx, iwSrcDy, iwDst, (float)lowThreshold, (float)highThreshold,
|
||||
::ipp::IwiFilterCannyDerivParams(norm));
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
// 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
|
||||
// Copyright (C) 2026, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "ipp_hal_imgproc.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/geometry.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
// Mirrors CV_IPP_MALLOC from modules/core/include/opencv2/core/private.hpp: ippicv (IPP >= 2017)
|
||||
// exposes only the 64-bit ippMalloc_L.
|
||||
#if IPP_VERSION_X100 >= 201700
|
||||
#define IPP_HAL_MALLOC(SIZE) ippMalloc_L(SIZE)
|
||||
#else
|
||||
#define IPP_HAL_MALLOC(SIZE) ippMalloc((int)(SIZE))
|
||||
#endif
|
||||
|
||||
#ifndef IPP_DISABLE_PERF_TRUE_DIST_MT
|
||||
#define IPP_DISABLE_PERF_TRUE_DIST_MT 1
|
||||
#endif
|
||||
|
||||
// Fixed distance-transform mask weights, mirroring getDistanceTransformMask() in
|
||||
// modules/imgproc/src/distransform.cpp. maskType == distTypeIndex + mask_size*10.
|
||||
static bool ippGetDistanceTransformMask(int dist_type, int mask_size, float *metrics)
|
||||
{
|
||||
int maskType = (dist_type == cv::DIST_C ? 0 : dist_type == cv::DIST_L1 ? 1 : 2) + mask_size * 10;
|
||||
switch (maskType)
|
||||
{
|
||||
case 30: metrics[0] = 1.0f; metrics[1] = 1.0f; break;
|
||||
case 31: metrics[0] = 1.0f; metrics[1] = 2.0f; break;
|
||||
case 32: metrics[0] = 0.955f; metrics[1] = 1.3693f; break;
|
||||
case 50: metrics[0] = 1.0f; metrics[1] = 1.0f; metrics[2] = 2.0f; break;
|
||||
case 51: metrics[0] = 1.0f; metrics[1] = 2.0f; metrics[2] = 3.0f; break;
|
||||
case 52: metrics[0] = 1.0f; metrics[1] = 1.4f; metrics[2] = 2.1969f; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ipp_hal_distanceTransform(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int dst_type, int dist_type, int mask_size)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
IppiSize roi = { width, height };
|
||||
|
||||
// DIST_L1 with 8-bit output: fixed L1 / 3x3 metrics.
|
||||
if (dst_type == CV_8U)
|
||||
{
|
||||
Ipp32s pMetrics[2] = { 1, 2 }; // L1, 3x3 mask
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u_C1R, src_data, (int)src_step,
|
||||
dst_data, (int)dst_step, roi, pMetrics) >= 0)
|
||||
{
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// All remaining paths produce a 32-bit float distance map.
|
||||
if (dst_type != CV_32F)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if (mask_size == cv::DIST_MASK_PRECISE)
|
||||
{
|
||||
// 4097 can't square into a float.
|
||||
#if IPP_DISABLE_PERF_TRUE_DIST_MT
|
||||
if (!((cv::getNumThreads() <= 1 || ((size_t)width * height < (size_t)(1 << 14))) &&
|
||||
height < 4097 && width < 4097))
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
int bufSize = 0;
|
||||
if (ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(roi, &bufSize) < 0)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
Ipp8u *pBuffer = (Ipp8u *)IPP_HAL_MALLOC(bufSize);
|
||||
if (!pBuffer)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiTrueDistanceTransform_8u32f_C1R, src_data, (int)src_step,
|
||||
(Ipp32f *)dst_data, (int)dst_step, roi, pBuffer);
|
||||
ippFree(pBuffer);
|
||||
if (status < 0)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// https://github.com/opencv/opencv/issues/24082
|
||||
// There is probably a rounding issue that leads to non-deterministic behavior
|
||||
// between runs on positions closer to zeros by x-axis in straight direction.
|
||||
// As a workaround, we detect the distances that expected to be exact
|
||||
// number of pixels and round manually.
|
||||
static const float correctionDiff = 1.0f / (1 << 11);
|
||||
for (int i = 0; i < height; ++i)
|
||||
{
|
||||
float* row = (float*)(dst_data + (size_t)i * dst_step);
|
||||
for (int j = 0; j < width; ++j)
|
||||
{
|
||||
float rounded = static_cast<float>(cvRound(row[j]));
|
||||
if (std::fabs(row[j] - rounded) <= correctionDiff)
|
||||
row[j] = rounded;
|
||||
}
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
// DIST_MASK_3 / DIST_MASK_5 chamfer distances.
|
||||
if (mask_size != cv::DIST_MASK_3 && mask_size != cv::DIST_MASK_5)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// IPP uses 32-bit signed intermediates; bail out when the image is too large.
|
||||
bool has_int_overflow = (int64)width * height >= INT_MAX;
|
||||
if (has_int_overflow)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
float metrics[5] = {0};
|
||||
if (!ippGetDistanceTransformMask(dist_type, mask_size, metrics))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if (mask_size == cv::DIST_MASK_3)
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src_data, (int)src_step,
|
||||
(Ipp32f *)dst_data, (int)dst_step, roi, metrics) >= 0)
|
||||
{
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
}
|
||||
else // DIST_MASK_5
|
||||
{
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src_data, (int)src_step,
|
||||
(Ipp32f *)dst_data, (int)dst_step, roi, metrics) >= 0)
|
||||
{
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 700
|
||||
@@ -0,0 +1,144 @@
|
||||
// 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
|
||||
// Copyright (C) 2026, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "ipp_hal_imgproc.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "precomp_ipp.hpp"
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
using namespace cv;
|
||||
|
||||
#if IPP_VERSION_X100 >= 201700
|
||||
#define IPP_HAL_MALLOC(SIZE) ippMalloc_L(SIZE)
|
||||
#else
|
||||
#define IPP_HAL_MALLOC(SIZE) ippMalloc((int)(SIZE))
|
||||
#endif
|
||||
|
||||
typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*);
|
||||
|
||||
static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst, bool normed)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
IppiSize srcRoiSize = {src.cols,src.rows};
|
||||
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
|
||||
|
||||
int bufSize=0;
|
||||
|
||||
int depth = src.depth();
|
||||
|
||||
ippimatchTemplate ippiCrossCorrNorm =
|
||||
depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R:
|
||||
depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0;
|
||||
|
||||
if (ippiCrossCorrNorm==0)
|
||||
return false;
|
||||
|
||||
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid);
|
||||
if(normed)
|
||||
funCfg |= ippiNorm;
|
||||
else
|
||||
funCfg |= ippiNormNone;
|
||||
|
||||
status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
|
||||
if ( status < 0 )
|
||||
return false;
|
||||
|
||||
Ipp8u* buffer = bufSize > 0 ? (Ipp8u*)IPP_HAL_MALLOC(bufSize) : 0;
|
||||
if (bufSize > 0 && buffer == 0)
|
||||
return false;
|
||||
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
|
||||
|
||||
if (buffer)
|
||||
ippFree(buffer);
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst)
|
||||
{
|
||||
IppStatus status;
|
||||
|
||||
IppiSize srcRoiSize = {src.cols,src.rows};
|
||||
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
|
||||
|
||||
int bufSize=0;
|
||||
|
||||
int depth = src.depth();
|
||||
|
||||
ippimatchTemplate ippiSqrDistanceNorm =
|
||||
depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R:
|
||||
depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0;
|
||||
|
||||
if (ippiSqrDistanceNorm==0)
|
||||
return false;
|
||||
|
||||
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid | ippiNormNone);
|
||||
status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
|
||||
if ( status < 0 )
|
||||
return false;
|
||||
|
||||
Ipp8u* buffer = bufSize > 0 ? (Ipp8u*)IPP_HAL_MALLOC(bufSize) : 0;
|
||||
if (bufSize > 0 && buffer == 0)
|
||||
return false;
|
||||
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
|
||||
|
||||
if (buffer)
|
||||
ippFree(buffer);
|
||||
dst = cv::max(dst, 0); // handle edge case from rounding in variance computation which can result in negative values
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
int ipp_hal_matchTemplate(const uchar* src_data, size_t src_step, int src_width, int src_height,
|
||||
const uchar* templ_data, size_t templ_step, int templ_width, int templ_height,
|
||||
float* result_data, size_t result_step, int depth, int cn, int method)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
if(cn != 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
if(depth != CV_8U && depth != CV_32F)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
Mat img(src_height, src_width, CV_MAKETYPE(depth, cn), (void*)src_data, src_step);
|
||||
Mat templ(templ_height, templ_width, CV_MAKETYPE(depth, cn), (void*)templ_data, templ_step);
|
||||
Mat result(src_height - templ_height + 1, src_width - templ_width + 1, CV_32FC1, (void*)result_data, result_step);
|
||||
|
||||
// These functions are not efficient if template size is comparable with image size
|
||||
if(templ.size().area()*4 > img.size().area())
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// CV_8U SQDIFF/SQDIFF_NORMED suffer from float32 catastrophic cancellation
|
||||
// in IPP's internal accumulators; fall through to the double-precision path instead.
|
||||
if(depth == CV_8U && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(method == cv::TM_SQDIFF)
|
||||
{
|
||||
if(ipp_sqrDistance(img, templ, result))
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
else if(method == cv::TM_CCORR_NORMED)
|
||||
{
|
||||
if(ipp_crossCorr(img, templ, result, true))
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
else if(method == cv::TM_SQDIFF_NORMED || method == cv::TM_CCORR ||
|
||||
method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
|
||||
{
|
||||
// Raw cross-correlation; caller finishes SQDIFF_NORMED/CCOEFF/CCOEFF_NORMED via
|
||||
// common_matchTemplate (TM_CCORR is already final).
|
||||
if(ipp_crossCorr(img, templ, result, false))
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 700
|
||||
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
// Copyright (C) 2026, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "ipp_hal_imgproc.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "precomp_ipp.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
int ipp_hal_threshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn, double thresh, double maxValue,
|
||||
int thresholdType)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
CV_UNUSED(maxValue);
|
||||
|
||||
// IPP only implements these three types and depths; everything else falls back to OpenCV.
|
||||
if (thresholdType != cv::THRESH_TRUNC && thresholdType != cv::THRESH_TOZERO &&
|
||||
thresholdType != cv::THRESH_TOZERO_INV)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
if (depth != CV_8U && depth != CV_16S && depth != CV_32F)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
int roi_width = width * cn; // threshold is elementwise, so channels fold into the width
|
||||
int roi_height = height;
|
||||
int elemSize1 = (depth == CV_8U) ? 1 : (depth == CV_16S) ? 2 : 4;
|
||||
|
||||
if (src_step == (size_t)roi_width * elemSize1 && dst_step == (size_t)roi_width * elemSize1)
|
||||
{
|
||||
roi_width *= roi_height;
|
||||
roi_height = 1;
|
||||
src_step = dst_step = (size_t)roi_width * elemSize1;
|
||||
}
|
||||
|
||||
IppiSize sz = { roi_width, roi_height };
|
||||
const bool inplace = (src_data == dst_data);
|
||||
IppStatus status = ippStsErr;
|
||||
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
switch (depth)
|
||||
{
|
||||
case CV_8U:
|
||||
{
|
||||
Ipp8u t = (Ipp8u)thresh;
|
||||
switch (thresholdType)
|
||||
{
|
||||
case cv::THRESH_TRUNC:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1IR, dst_data, (int)dst_step, sz, t);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t);
|
||||
break;
|
||||
case cv::THRESH_TOZERO:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1IR, dst_data, (int)dst_step, sz, t + 1, 0);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t + 1, 0);
|
||||
break;
|
||||
case cv::THRESH_TOZERO_INV:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1IR, dst_data, (int)dst_step, sz, t, 0);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CV_16S:
|
||||
{
|
||||
const Ipp16s* src = (const Ipp16s*)src_data;
|
||||
Ipp16s* dst = (Ipp16s*)dst_data;
|
||||
Ipp16s t = (Ipp16s)thresh;
|
||||
switch (thresholdType)
|
||||
{
|
||||
case cv::THRESH_TRUNC:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1IR, dst, (int)dst_step, sz, t);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t);
|
||||
break;
|
||||
case cv::THRESH_TOZERO:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1IR, dst, (int)dst_step, sz, t + 1, 0);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t + 1, 0);
|
||||
break;
|
||||
case cv::THRESH_TOZERO_INV:
|
||||
if (inplace)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1IR, dst, (int)dst_step, sz, t, 0);
|
||||
if (!inplace || status < 0)
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CV_32F:
|
||||
{
|
||||
const Ipp32f* src = (const Ipp32f*)src_data;
|
||||
Ipp32f* dst = (Ipp32f*)dst_data;
|
||||
Ipp32f t = (Ipp32f)thresh;
|
||||
switch (thresholdType)
|
||||
{
|
||||
case cv::THRESH_TRUNC:
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, t);
|
||||
break;
|
||||
case cv::THRESH_TOZERO:
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, nextafterf(t, std::numeric_limits<float>::infinity()), 0);
|
||||
break;
|
||||
case cv::THRESH_TOZERO_INV:
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, t, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
|
||||
return status >= 0 ? CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 700
|
||||
@@ -235,7 +235,7 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 1}}, //16U
|
||||
{{1, 1}, {0, 0}, {1, 0}, {1, 1}}, //16S
|
||||
{{1, 1}, {0, 0}, {1, 0}, {1, 1}}, //32S
|
||||
{{0, 0}, {0, 0}, {0, 0}, {1, 0}}, //32F
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //32F
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}}; //64F
|
||||
#endif
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@ template<> struct rvv<RVV_U8M1>
|
||||
{
|
||||
static inline vfloat32m4_t vcvt0(vuint8m1_t a, size_t b) { return __riscv_vfcvt_f(__riscv_vzext_vf4(a, b), b); }
|
||||
static inline vuint8m1_t vcvt1(vfloat32m4_t a, size_t b) { return __riscv_vnclipu(__riscv_vfncvt_xu(a, b), 0, __RISCV_VXRM_RNU, b); }
|
||||
static inline vint32m4_t vwiden(vuint8m1_t a, size_t b) { return __riscv_vreinterpret_v_u32m4_i32m4(__riscv_vzext_vf4(a, b)); }
|
||||
static inline vuint8m1_t vnarrow(vint32m4_t a, size_t b) { return __riscv_vncvt_x(__riscv_vncvt_x(__riscv_vreinterpret_v_i32m4_u32m4(a), b), b); }
|
||||
static inline vuint8m1_t vloxei(const uchar* a, vuint16m2_t b, size_t c) { return __riscv_vloxei16_v_u8m1(a, b, c); }
|
||||
static inline void vloxseg2ei(const uchar* a, vuint16m2_t b, size_t c, vuint8m1_t& x, vuint8m1_t& y) { auto src = __riscv_vloxseg2ei16_v_u8m1x2(a, b, c); x = __riscv_vget_v_u8m1x2_u8m1(src, 0); y = __riscv_vget_v_u8m1x2_u8m1(src, 1); }
|
||||
static inline void vloxseg3ei(const uchar* a, vuint16m2_t b, size_t c, vuint8m1_t& x, vuint8m1_t& y, vuint8m1_t& z) { auto src = __riscv_vloxseg3ei16_v_u8m1x3(a, b, c); x = __riscv_vget_v_u8m1x3_u8m1(src, 0); y = __riscv_vget_v_u8m1x3_u8m1(src, 1); z = __riscv_vget_v_u8m1x3_u8m1(src, 2); }
|
||||
@@ -165,6 +167,8 @@ template<> struct rvv<RVV_U8MF2>
|
||||
{
|
||||
static inline vfloat32m2_t vcvt0(vuint8mf2_t a, size_t b) { return __riscv_vfcvt_f(__riscv_vzext_vf4(a, b), b); }
|
||||
static inline vuint8mf2_t vcvt1(vfloat32m2_t a, size_t b) { return __riscv_vnclipu(__riscv_vfncvt_xu(a, b), 0, __RISCV_VXRM_RNU, b); }
|
||||
static inline vint32m2_t vwiden(vuint8mf2_t a, size_t b) { return __riscv_vreinterpret_v_u32m2_i32m2(__riscv_vzext_vf4(a, b)); }
|
||||
static inline vuint8mf2_t vnarrow(vint32m2_t a, size_t b) { return __riscv_vncvt_x(__riscv_vncvt_x(__riscv_vreinterpret_v_i32m2_u32m2(a), b), b); }
|
||||
static inline vuint8mf2_t vloxei(const uchar* a, vuint16m1_t b, size_t c) { return __riscv_vloxei16_v_u8mf2(a, b, c); }
|
||||
static inline void vloxseg2ei(const uchar* a, vuint16m1_t b, size_t c, vuint8mf2_t& x, vuint8mf2_t& y) { auto src = __riscv_vloxseg2ei16_v_u8mf2x2(a, b, c); x = __riscv_vget_v_u8mf2x2_u8mf2(src, 0); y = __riscv_vget_v_u8mf2x2_u8mf2(src, 1); }
|
||||
static inline void vloxseg3ei(const uchar* a, vuint16m1_t b, size_t c, vuint8mf2_t& x, vuint8mf2_t& y, vuint8mf2_t& z) { auto src = __riscv_vloxseg3ei16_v_u8mf2x3(a, b, c); x = __riscv_vget_v_u8mf2x3_u8mf2(src, 0); y = __riscv_vget_v_u8mf2x3_u8mf2(src, 1); z = __riscv_vget_v_u8mf2x3_u8mf2(src, 2); }
|
||||
@@ -332,6 +336,150 @@ static inline int resizeLinear(int start, int end, const uchar *src_data, size_t
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
static const int INTER_RESIZE_COEF_BITS = 11;
|
||||
static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
|
||||
|
||||
// Bit-exact fixed-point vertical+horizontal linear combine for one channel, matching the reference
|
||||
// HResizeLinear<uchar,int,short,INTER_RESIZE_COEF_SCALE> + VResizeLinear<uchar,int,short,
|
||||
// FixedPtCast<int,uchar,INTER_RESIZE_COEF_BITS*2>> in modules/imgproc/src/resize.cpp.
|
||||
// Sxy are the four widened (int32) source corners; a0/a1 the horizontal weights (per column),
|
||||
// b0/b1 the vertical weights (per row). The staged >>4 / >>16 / >>2 shifts (total 22) reproduce the
|
||||
// reference exactly and keep the intermediates within int32.
|
||||
template<typename VI>
|
||||
static inline VI resizeLinearU8Combine(VI S00, VI S01, VI S10, VI S11, VI a0, VI a1, int b0, int b1, size_t vl)
|
||||
{
|
||||
VI h0 = __riscv_vmacc(__riscv_vmul(S00, a0, vl), S01, a1, vl); // S[y0][x0]*a0 + S[y0][x1]*a1
|
||||
VI h1 = __riscv_vmacc(__riscv_vmul(S10, a0, vl), S11, a1, vl); // S[y1][x0]*a0 + S[y1][x1]*a1
|
||||
h0 = __riscv_vsra(__riscv_vmul(__riscv_vsra(h0, 4, vl), b0, vl), 16, vl); // (b0*(h0>>4))>>16
|
||||
h1 = __riscv_vsra(__riscv_vmul(__riscv_vsra(h1, 4, vl), b1, vl), 16, vl); // (b1*(h1>>4))>>16
|
||||
return __riscv_vsra(__riscv_vadd(__riscv_vadd(h0, h1, vl), 2, vl), 2, vl); // (t0 + t1 + 2) >> 2
|
||||
}
|
||||
|
||||
// the algorithm is copied from imgproc/src/resize.cpp, HResizeLinear + VResizeLinear for uchar.
|
||||
// The generic resizeLinear<> above computes in float, which is bit-exact only for 16U/32F; 8U
|
||||
// INTER_LINEAR must use this fixed-point path to match the reference (float drift breaks tight
|
||||
// consumers such as DNN blobFromImage preprocessing, issue #28870).
|
||||
template<typename helper, int cn>
|
||||
static inline int resizeLinearU8(int start, int end, const uchar *src_data, size_t src_step, int src_height, uchar *dst_data, size_t dst_step, int dst_width, double scale_y, const ushort* x_ofs0, const ushort* x_ofs1, const int* ialpha0, const int* ialpha1)
|
||||
{
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
float my = (i + 0.5) * scale_y - 0.5;
|
||||
int y_ofs = static_cast<int>(std::floor(my));
|
||||
my -= y_ofs;
|
||||
|
||||
int y_ofs0 = std::min(std::max(y_ofs , 0), src_height - 1);
|
||||
int y_ofs1 = std::min(std::max(y_ofs + 1, 0), src_height - 1);
|
||||
int b0 = saturate_cast<short>((1.f - my) * INTER_RESIZE_COEF_SCALE);
|
||||
int b1 = saturate_cast<short>(my * INTER_RESIZE_COEF_SCALE);
|
||||
|
||||
const uchar* S0 = src_data + y_ofs0 * src_step;
|
||||
const uchar* S1 = src_data + y_ofs1 * src_step;
|
||||
|
||||
int vl;
|
||||
switch (cn)
|
||||
{
|
||||
case 1:
|
||||
for (int j = 0; j < dst_width; j += vl)
|
||||
{
|
||||
vl = helper::setvl(dst_width - j);
|
||||
auto ptr0 = RVV_SameLen<ushort, helper>::vload(x_ofs0 + j, vl);
|
||||
auto ptr1 = RVV_SameLen<ushort, helper>::vload(x_ofs1 + j, vl);
|
||||
auto a0 = RVV_SameLen<int, helper>::vload(ialpha0 + j, vl);
|
||||
auto a1 = RVV_SameLen<int, helper>::vload(ialpha1 + j, vl);
|
||||
|
||||
auto v00 = rvv<helper>::vwiden(rvv<helper>::vloxei(S0, ptr0, vl), vl);
|
||||
auto v01 = rvv<helper>::vwiden(rvv<helper>::vloxei(S0, ptr1, vl), vl);
|
||||
auto v02 = rvv<helper>::vwiden(rvv<helper>::vloxei(S1, ptr0, vl), vl);
|
||||
auto v03 = rvv<helper>::vwiden(rvv<helper>::vloxei(S1, ptr1, vl), vl);
|
||||
|
||||
auto d0 = resizeLinearU8Combine(v00, v01, v02, v03, a0, a1, b0, b1, vl);
|
||||
helper::vstore(reinterpret_cast<typename helper::ElemType*>(dst_data + i * dst_step) + j, rvv<helper>::vnarrow(d0, vl), vl);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (int j = 0; j < dst_width; j += vl)
|
||||
{
|
||||
vl = helper::setvl(dst_width - j);
|
||||
auto ptr0 = RVV_SameLen<ushort, helper>::vload(x_ofs0 + j, vl);
|
||||
auto ptr1 = RVV_SameLen<ushort, helper>::vload(x_ofs1 + j, vl);
|
||||
auto a0 = RVV_SameLen<int, helper>::vload(ialpha0 + j, vl);
|
||||
auto a1 = RVV_SameLen<int, helper>::vload(ialpha1 + j, vl);
|
||||
|
||||
typename helper::VecType s0, s1;
|
||||
rvv<helper>::vloxseg2ei(S0, ptr0, vl, s0, s1);
|
||||
auto v00 = rvv<helper>::vwiden(s0, vl), v10 = rvv<helper>::vwiden(s1, vl);
|
||||
rvv<helper>::vloxseg2ei(S0, ptr1, vl, s0, s1);
|
||||
auto v01 = rvv<helper>::vwiden(s0, vl), v11 = rvv<helper>::vwiden(s1, vl);
|
||||
rvv<helper>::vloxseg2ei(S1, ptr0, vl, s0, s1);
|
||||
auto v02 = rvv<helper>::vwiden(s0, vl), v12 = rvv<helper>::vwiden(s1, vl);
|
||||
rvv<helper>::vloxseg2ei(S1, ptr1, vl, s0, s1);
|
||||
auto v03 = rvv<helper>::vwiden(s0, vl), v13 = rvv<helper>::vwiden(s1, vl);
|
||||
|
||||
auto d0 = resizeLinearU8Combine(v00, v01, v02, v03, a0, a1, b0, b1, vl);
|
||||
auto d1 = resizeLinearU8Combine(v10, v11, v12, v13, a0, a1, b0, b1, vl);
|
||||
rvv<helper>::vsseg2e(reinterpret_cast<typename helper::ElemType*>(dst_data + i * dst_step) + j * 2, vl, rvv<helper>::vnarrow(d0, vl), rvv<helper>::vnarrow(d1, vl));
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (int j = 0; j < dst_width; j += vl)
|
||||
{
|
||||
vl = helper::setvl(dst_width - j);
|
||||
auto ptr0 = RVV_SameLen<ushort, helper>::vload(x_ofs0 + j, vl);
|
||||
auto ptr1 = RVV_SameLen<ushort, helper>::vload(x_ofs1 + j, vl);
|
||||
auto a0 = RVV_SameLen<int, helper>::vload(ialpha0 + j, vl);
|
||||
auto a1 = RVV_SameLen<int, helper>::vload(ialpha1 + j, vl);
|
||||
|
||||
typename helper::VecType s0, s1, s2;
|
||||
rvv<helper>::vloxseg3ei(S0, ptr0, vl, s0, s1, s2);
|
||||
auto v00 = rvv<helper>::vwiden(s0, vl), v10 = rvv<helper>::vwiden(s1, vl), v20 = rvv<helper>::vwiden(s2, vl);
|
||||
rvv<helper>::vloxseg3ei(S0, ptr1, vl, s0, s1, s2);
|
||||
auto v01 = rvv<helper>::vwiden(s0, vl), v11 = rvv<helper>::vwiden(s1, vl), v21 = rvv<helper>::vwiden(s2, vl);
|
||||
rvv<helper>::vloxseg3ei(S1, ptr0, vl, s0, s1, s2);
|
||||
auto v02 = rvv<helper>::vwiden(s0, vl), v12 = rvv<helper>::vwiden(s1, vl), v22 = rvv<helper>::vwiden(s2, vl);
|
||||
rvv<helper>::vloxseg3ei(S1, ptr1, vl, s0, s1, s2);
|
||||
auto v03 = rvv<helper>::vwiden(s0, vl), v13 = rvv<helper>::vwiden(s1, vl), v23 = rvv<helper>::vwiden(s2, vl);
|
||||
|
||||
auto d0 = resizeLinearU8Combine(v00, v01, v02, v03, a0, a1, b0, b1, vl);
|
||||
auto d1 = resizeLinearU8Combine(v10, v11, v12, v13, a0, a1, b0, b1, vl);
|
||||
auto d2 = resizeLinearU8Combine(v20, v21, v22, v23, a0, a1, b0, b1, vl);
|
||||
rvv<helper>::vsseg3e(reinterpret_cast<typename helper::ElemType*>(dst_data + i * dst_step) + j * 3, vl, rvv<helper>::vnarrow(d0, vl), rvv<helper>::vnarrow(d1, vl), rvv<helper>::vnarrow(d2, vl));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (int j = 0; j < dst_width; j += vl)
|
||||
{
|
||||
vl = helper::setvl(dst_width - j);
|
||||
auto ptr0 = RVV_SameLen<ushort, helper>::vload(x_ofs0 + j, vl);
|
||||
auto ptr1 = RVV_SameLen<ushort, helper>::vload(x_ofs1 + j, vl);
|
||||
auto a0 = RVV_SameLen<int, helper>::vload(ialpha0 + j, vl);
|
||||
auto a1 = RVV_SameLen<int, helper>::vload(ialpha1 + j, vl);
|
||||
|
||||
typename helper::VecType s0, s1, s2, s3;
|
||||
rvv<helper>::vloxseg4ei(S0, ptr0, vl, s0, s1, s2, s3);
|
||||
auto v00 = rvv<helper>::vwiden(s0, vl), v10 = rvv<helper>::vwiden(s1, vl), v20 = rvv<helper>::vwiden(s2, vl), v30 = rvv<helper>::vwiden(s3, vl);
|
||||
rvv<helper>::vloxseg4ei(S0, ptr1, vl, s0, s1, s2, s3);
|
||||
auto v01 = rvv<helper>::vwiden(s0, vl), v11 = rvv<helper>::vwiden(s1, vl), v21 = rvv<helper>::vwiden(s2, vl), v31 = rvv<helper>::vwiden(s3, vl);
|
||||
rvv<helper>::vloxseg4ei(S1, ptr0, vl, s0, s1, s2, s3);
|
||||
auto v02 = rvv<helper>::vwiden(s0, vl), v12 = rvv<helper>::vwiden(s1, vl), v22 = rvv<helper>::vwiden(s2, vl), v32 = rvv<helper>::vwiden(s3, vl);
|
||||
rvv<helper>::vloxseg4ei(S1, ptr1, vl, s0, s1, s2, s3);
|
||||
auto v03 = rvv<helper>::vwiden(s0, vl), v13 = rvv<helper>::vwiden(s1, vl), v23 = rvv<helper>::vwiden(s2, vl), v33 = rvv<helper>::vwiden(s3, vl);
|
||||
|
||||
auto d0 = resizeLinearU8Combine(v00, v01, v02, v03, a0, a1, b0, b1, vl);
|
||||
auto d1 = resizeLinearU8Combine(v10, v11, v12, v13, a0, a1, b0, b1, vl);
|
||||
auto d2 = resizeLinearU8Combine(v20, v21, v22, v23, a0, a1, b0, b1, vl);
|
||||
auto d3 = resizeLinearU8Combine(v30, v31, v32, v33, a0, a1, b0, b1, vl);
|
||||
rvv<helper>::vsseg4e(reinterpret_cast<typename helper::ElemType*>(dst_data + i * dst_step) + j * 4, vl, rvv<helper>::vnarrow(d0, vl), rvv<helper>::vnarrow(d1, vl), rvv<helper>::vnarrow(d2, vl), rvv<helper>::vnarrow(d3, vl));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
template<int cn>
|
||||
static inline int resizeLinearExact(int start, int end, const uchar *src_data, size_t src_step, int src_height, uchar *dst_data, size_t dst_step, int dst_width, double scale_y, const ushort* x_ofs0, const ushort* x_ofs1, const ushort* x_val)
|
||||
{
|
||||
@@ -833,6 +981,37 @@ static inline int resizeLinear(int src_type, const uchar *src_data, size_t src_s
|
||||
return invoke(dst_height, {resizeLinearExact<4>}, src_data, src_step, src_height, dst_data, dst_step, dst_width, scale_y, x_ofs0.data(), x_ofs1.data(), x_val.data());
|
||||
}
|
||||
}
|
||||
else if (CV_MAT_DEPTH(src_type) == CV_8U)
|
||||
{
|
||||
// 8U INTER_LINEAR must be bit-exact fixed-point to match the reference implementation;
|
||||
// computing it in float drifts and breaks tight consumers (e.g. DNN preprocessing, #28870).
|
||||
std::vector<int> ialpha0(dst_width), ialpha1(dst_width);
|
||||
for (int i = 0; i < dst_width; i++)
|
||||
{
|
||||
float fx = (float)((i + 0.5) * scale_x - 0.5);
|
||||
int x_ofs = static_cast<int>(std::floor(fx));
|
||||
fx -= x_ofs;
|
||||
if (x_ofs < 0) { fx = 0; x_ofs = 0; }
|
||||
if (x_ofs >= src_width - 1) { fx = 0; x_ofs = src_width - 1; }
|
||||
|
||||
x_ofs0[i] = static_cast<ushort>(x_ofs) * cn;
|
||||
x_ofs1[i] = static_cast<ushort>(std::min(x_ofs + 1, src_width - 1)) * cn;
|
||||
ialpha0[i] = saturate_cast<short>((1.f - fx) * INTER_RESIZE_COEF_SCALE);
|
||||
ialpha1[i] = saturate_cast<short>(fx * INTER_RESIZE_COEF_SCALE);
|
||||
}
|
||||
|
||||
switch (src_type)
|
||||
{
|
||||
case CV_8UC1:
|
||||
return invoke(dst_height, {resizeLinearU8<RVV_U8M1, 1>}, src_data, src_step, src_height, dst_data, dst_step, dst_width, scale_y, x_ofs0.data(), x_ofs1.data(), ialpha0.data(), ialpha1.data());
|
||||
case CV_8UC2:
|
||||
return invoke(dst_height, {resizeLinearU8<RVV_U8M1, 2>}, src_data, src_step, src_height, dst_data, dst_step, dst_width, scale_y, x_ofs0.data(), x_ofs1.data(), ialpha0.data(), ialpha1.data());
|
||||
case CV_8UC3:
|
||||
return invoke(dst_height, {resizeLinearU8<RVV_U8MF2, 3>}, src_data, src_step, src_height, dst_data, dst_step, dst_width, scale_y, x_ofs0.data(), x_ofs1.data(), ialpha0.data(), ialpha1.data());
|
||||
case CV_8UC4:
|
||||
return invoke(dst_height, {resizeLinearU8<RVV_U8MF2, 4>}, src_data, src_step, src_height, dst_data, dst_step, dst_width, scale_y, x_ofs0.data(), x_ofs1.data(), ialpha0.data(), ialpha1.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<float> x_val(dst_width);
|
||||
|
||||
@@ -197,7 +197,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); }
|
||||
// Temporary disabled named IPP region. Performance
|
||||
#define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations
|
||||
#define IPP_DISABLE_PERF_TRUE_DIST_MT 1 // cv::distanceTransform OpenCV MT performance is better
|
||||
#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#include "ippversion.h"
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
#include "opencv2/core/mat.hpp"
|
||||
#include "opencl_kernels_core.hpp"
|
||||
|
||||
#undef HAVE_IPP
|
||||
#undef CV_IPP_RUN_FAST
|
||||
#define CV_IPP_RUN_FAST(f, ...)
|
||||
#undef CV_IPP_RUN
|
||||
#define CV_IPP_RUN(c, f, ...)
|
||||
#define IPP_DISABLE_REDUCE 1
|
||||
#define IPP_DISABLE_SORT 0
|
||||
|
||||
/*************************************************************************************************\
|
||||
Matrix Operations
|
||||
@@ -498,7 +495,7 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
|
||||
#define reduceMinR32f reduceR_<float, float, OpMin<float> >
|
||||
#define reduceMinR64f reduceR_<double,double,OpMin<double> >
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
|
||||
static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
|
||||
{
|
||||
int sstep = (int)srcmat.step, stype = srcmat.type(),
|
||||
@@ -587,7 +584,7 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
|
||||
#define reduceSum2C32f32f reduceC_<float, float, OpAddSqr<float>, OpSqr<float> >
|
||||
#define reduceSum2C64f64f reduceC_<double,double,OpAddSqr<double>,OpSqr<double> >
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
|
||||
#define reduceSumC8u64f reduceSumC_8u16u16s32f_64f
|
||||
#define reduceSumC16u64f reduceSumC_8u16u16s32f_64f
|
||||
#define reduceSumC16s64f reduceSumC_8u16u16s32f_64f
|
||||
@@ -597,14 +594,14 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
|
||||
#define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> >
|
||||
#define reduceSumC16s64f reduceC_<short, double,OpAdd<double> >
|
||||
#define reduceSumC32f64f reduceC_<float, double,OpAdd<double> >
|
||||
#endif
|
||||
|
||||
#define reduceSum2C8u64f reduceC_<uchar, double,OpAddSqr<int>, OpSqr<int> >
|
||||
#define reduceSum2C16u64f reduceC_<ushort,double,OpAddSqr<double>,OpSqr<double> >
|
||||
#define reduceSum2C16s64f reduceC_<short, double,OpAddSqr<double>,OpSqr<double> >
|
||||
#define reduceSum2C32f64f reduceC_<float, double,OpAddSqr<double>,OpSqr<double> >
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
|
||||
#define REDUCE_OP(favor, optype, type1, type2) \
|
||||
static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
|
||||
{ \
|
||||
@@ -629,7 +626,7 @@ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstm
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
|
||||
REDUCE_OP(8u, Max, uchar, uchar)
|
||||
REDUCE_OP(16u, Max, ushort, ushort)
|
||||
REDUCE_OP(16s, Max, short, short)
|
||||
@@ -642,7 +639,7 @@ REDUCE_OP(32f, Max, float, float)
|
||||
#endif
|
||||
#define reduceMaxC64f reduceC_<double,double,OpMax<double> >
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
|
||||
REDUCE_OP(8u, Min, uchar, uchar)
|
||||
REDUCE_OP(16u, Min, ushort, ushort)
|
||||
REDUCE_OP(16s, Min, short, short)
|
||||
@@ -1037,7 +1034,7 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
|
||||
typedef IppStatus (CV_STDCALL *IppSortFunc)(void *pSrcDst, int len, Ipp8u *pBuffer);
|
||||
|
||||
static IppSortFunc getSortFunc(int depth, bool sortDescending)
|
||||
@@ -1074,54 +1071,64 @@ static bool ipp_sort(const Mat& src, Mat& dst, int flags)
|
||||
if(!ippsSortRadix_I)
|
||||
return false;
|
||||
|
||||
if(sortRows)
|
||||
{
|
||||
AutoBuffer<Ipp8u> buffer;
|
||||
int bufferSize;
|
||||
if(ippsSortRadixGetBufferSize(src.cols, type, &bufferSize) < 0)
|
||||
return false;
|
||||
|
||||
buffer.allocate(bufferSize);
|
||||
|
||||
if(!inplace)
|
||||
src.copyTo(dst);
|
||||
|
||||
for(int i = 0; i < dst.rows; i++)
|
||||
{
|
||||
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer.data()) < 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int n, len;
|
||||
if( sortRows )
|
||||
n = src.rows, len = src.cols;
|
||||
else
|
||||
n = src.cols, len = src.rows;
|
||||
|
||||
int bufferSize;
|
||||
if(ippsSortRadixGetBufferSize(len, type, &bufferSize) < 0)
|
||||
return false;
|
||||
|
||||
// Each row/column sorts independently, so parallelize over n like sort_ does.
|
||||
// IPP scratch (buffer) and per-column temporaries are thread-local; a shared flag
|
||||
// records IPP failures since the lambda cannot return from ipp_sort.
|
||||
volatile bool ok = true;
|
||||
parallel_for_(Range(0, n), [&](const Range& range)
|
||||
{
|
||||
AutoBuffer<Ipp8u> buffer;
|
||||
int bufferSize;
|
||||
if(ippsSortRadixGetBufferSize(src.rows, type, &bufferSize) < 0)
|
||||
return false;
|
||||
|
||||
buffer.allocate(bufferSize);
|
||||
|
||||
Mat row(1, src.rows, src.type());
|
||||
Mat srcSub;
|
||||
Mat dstSub;
|
||||
AutoBuffer<Ipp8u> buffer(bufferSize);
|
||||
Mat row;
|
||||
Rect subRect(0,0,1,src.rows);
|
||||
if( !sortRows )
|
||||
row.create(1, src.rows, src.type());
|
||||
|
||||
for(int i = 0; i < src.cols; i++)
|
||||
for( int i = range.start; i < range.end; i++ )
|
||||
{
|
||||
subRect.x = i;
|
||||
srcSub = Mat(src, subRect);
|
||||
dstSub = Mat(dst, subRect);
|
||||
srcSub.copyTo(row);
|
||||
if( !ok )
|
||||
break;
|
||||
void* ptr;
|
||||
if( sortRows )
|
||||
{
|
||||
uchar* dptr = dst.ptr(i);
|
||||
if( !inplace )
|
||||
memcpy(dptr, src.ptr(i), src.cols * src.elemSize());
|
||||
ptr = dptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
subRect.x = i;
|
||||
Mat(src, subRect).copyTo(row);
|
||||
ptr = row.ptr();
|
||||
}
|
||||
|
||||
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer.data()) < 0)
|
||||
return false;
|
||||
if( CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, ptr, len, buffer.data()) < 0 )
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
row = row.reshape(1, dstSub.rows);
|
||||
row.copyTo(dstSub);
|
||||
if( !sortRows )
|
||||
{
|
||||
Mat dstSub(dst, subRect);
|
||||
row = row.reshape(1, dstSub.rows);
|
||||
row.copyTo(dstSub);
|
||||
row = row.reshape(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
return ok;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1185,7 +1192,7 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
|
||||
typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(const void* pSrc, Ipp32s srcStrideBytes, Ipp32s *pDstIndx, int len, Ipp8u *pBuffer);
|
||||
|
||||
static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
|
||||
@@ -1276,7 +1283,9 @@ void cv::sort( InputArray _src, OutputArray _dst, int flags )
|
||||
CV_Assert( src.dims <= 2 && src.channels() == 1 );
|
||||
_dst.createSameSize( src, src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
#if !IPP_DISABLE_SORT
|
||||
CV_IPP_RUN_FAST(ipp_sort(src, dst, flags));
|
||||
#endif
|
||||
|
||||
static SortFunc tab[CV_DEPTH_MAX] =
|
||||
{
|
||||
@@ -1301,7 +1310,9 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
|
||||
_dst.createSameSize( src, CV_32S );
|
||||
dst = _dst.getMat();
|
||||
|
||||
#if !IPP_DISABLE_SORT
|
||||
CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags));
|
||||
#endif
|
||||
|
||||
static SortFunc tab[CV_DEPTH_MAX] =
|
||||
{
|
||||
|
||||
@@ -832,7 +832,8 @@ CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mt
|
||||
@param projMatrix 3x4 input projection matrix P.
|
||||
@param cameraMatrix Output 3x3 camera intrinsic matrix \f$\cameramatrix{A}\f$.
|
||||
@param rotMatrix Output 3x3 external rotation matrix R.
|
||||
@param transVect Output 4x1 translation vector T.
|
||||
@param transVect Output 4x1 vector representing the camera position in homogeneous coordinates.
|
||||
To obtain the translation vector, use t = -rotMatrix * transVect[:3]
|
||||
@param rotMatrixX Optional 3x3 rotation matrix around x-axis.
|
||||
@param rotMatrixY Optional 3x3 rotation matrix around y-axis.
|
||||
@param rotMatrixZ Optional 3x3 rotation matrix around z-axis.
|
||||
|
||||
@@ -2178,9 +2178,11 @@ with the WARP_RELATIVE_MAP flag :
|
||||
where values of pixels with non-integer coordinates are computed using one of available
|
||||
interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps
|
||||
in \f$map_1\f$ and \f$map_2\f$ respectively, or interleaved floating-point maps of \f$(x,y)\f$ in
|
||||
\f$map_1\f$, or fixed-point maps created by using #convertMaps. The reason you might want to
|
||||
convert from floating to fixed-point representations of a map is that they can yield much faster
|
||||
(\~2x) remapping operations. In the converted case, \f$map_1\f$ contains pairs (cvFloor(x),
|
||||
\f$map_1\f$, or fixed-point maps created by using #convertMaps. Fixed-point maps
|
||||
use a more compact representation, which can reduce memory bandwidth and benefit
|
||||
repeated remap calls that reuse the same map. Performance gains vary by hardware
|
||||
and are typically modest; measure before converting. In the converted case,
|
||||
\f$map_1\f$ contains pairs (cvFloor(x),
|
||||
cvFloor(y)) and \f$map_2\f$ contains indices in a table of interpolation coefficients.
|
||||
|
||||
This function cannot operate in-place.
|
||||
@@ -2189,7 +2191,7 @@ This function cannot operate in-place.
|
||||
@param dst Destination image. It has the same size as map1 and the same type as src .
|
||||
@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2 ,
|
||||
CV_32FC1, or CV_32FC2. See #convertMaps for details on converting a floating point
|
||||
representation to fixed-point for speed.
|
||||
representation to fixed-point.
|
||||
@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map
|
||||
if map1 is (x,y) points), respectively.
|
||||
@param interpolation Interpolation method (see #InterpolationFlags). The methods #INTER_AREA
|
||||
|
||||
@@ -48,85 +48,6 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
static bool ipp_Canny(const Mat& src , const Mat& dx_, const Mat& dy_, Mat& dst, float low, float high, bool L2gradient, int aperture_size)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
#if IPP_DISABLE_PERF_CANNY_MT
|
||||
if(cv::getNumThreads()>1)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
::ipp::IwiSize size(dst.cols, dst.rows);
|
||||
IppDataType type = ippiGetDataType(dst.depth());
|
||||
int channels = dst.channels();
|
||||
IppNormType norm = (L2gradient)?ippNormL2:ippNormL1;
|
||||
|
||||
if(size.width <= 3 || size.height <= 3)
|
||||
return false;
|
||||
|
||||
if(channels != 1)
|
||||
return false;
|
||||
|
||||
if(type != ipp8u)
|
||||
return false;
|
||||
|
||||
if(src.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrcDx;
|
||||
::ipp::IwiImage iwSrcDy;
|
||||
::ipp::IwiImage iwDst;
|
||||
|
||||
ippiGetImage(dx_, iwSrcDx);
|
||||
ippiGetImage(dy_, iwSrcDy);
|
||||
ippiGetImage(dst, iwDst);
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCannyDeriv, iwSrcDx, iwSrcDy, iwDst, low, high, ::ipp::IwiFilterCannyDerivParams(norm));
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IppiMaskSize kernel;
|
||||
|
||||
if(aperture_size == 3)
|
||||
kernel = ippMskSize3x3;
|
||||
else if(aperture_size == 5)
|
||||
kernel = ippMskSize5x5;
|
||||
else
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc;
|
||||
::ipp::IwiImage iwDst;
|
||||
|
||||
ippiGetImage(src, iwSrc);
|
||||
ippiGetImage(dst, iwDst);
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCanny, iwSrc, iwDst, low, high, ::ipp::IwiFilterCannyParams(ippFilterSobel, kernel, norm), ippBorderRepl);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(dx_); CV_UNUSED(dy_); CV_UNUSED(dst); CV_UNUSED(low); CV_UNUSED(high); CV_UNUSED(L2gradient); CV_UNUSED(aperture_size);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
template <bool useCustomDeriv>
|
||||
@@ -803,8 +724,6 @@ void Canny( InputArray _src, OutputArray _dst,
|
||||
CALL_HAL(canny, cv_hal_canny, src.data, src.step, dst.data, dst.step, src.cols, src.rows, src.channels(),
|
||||
low_thresh, high_thresh, aperture_size, L2gradient);
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_Canny(src, Mat(), Mat(), dst, (float)low_thresh, (float)high_thresh, L2gradient, aperture_size))
|
||||
|
||||
if (L2gradient)
|
||||
{
|
||||
low_thresh = std::min(32767.0, low_thresh);
|
||||
@@ -879,7 +798,8 @@ void Canny( InputArray _dx, InputArray _dy, OutputArray _dst,
|
||||
Mat dx = _dx.getMat();
|
||||
Mat dy = _dy.getMat();
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_Canny(Mat(), dx, dy, dst, (float)low_thresh, (float)high_thresh, L2gradient, 0))
|
||||
CALL_HAL(canny_deriv, cv_hal_canny_deriv, dx.ptr<short>(), dx.step, dy.ptr<short>(), dy.step,
|
||||
dst.data, dst.step, dx.cols, dx.rows, dx.channels(), low_thresh, high_thresh, L2gradient);
|
||||
|
||||
if (L2gradient)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
//
|
||||
//M*/
|
||||
#include "precomp.hpp"
|
||||
#include "hal_replacement.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -1004,19 +1005,8 @@ static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst)
|
||||
_dst.create( src.size(), CV_8UC1);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
CV_IPP_CHECK()
|
||||
{
|
||||
IppiSize roi = { src.cols, src.rows };
|
||||
Ipp32s pMetrics[2] = { 1, 2 }; //L1, 3x3 mask
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<uchar>(), (int)dst.step, roi, pMetrics) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
}
|
||||
#endif
|
||||
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
|
||||
src.cols, src.rows, CV_8U, cv::DIST_L1, cv::DIST_MASK_3);
|
||||
|
||||
distanceATS_L1_8u(src, dst);
|
||||
}
|
||||
@@ -1055,53 +1045,8 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
||||
|
||||
if( maskSize == cv::DIST_MASK_PRECISE )
|
||||
{
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
CV_IPP_CHECK()
|
||||
{
|
||||
#if IPP_DISABLE_PERF_TRUE_DIST_MT
|
||||
// IPP uses floats, but 4097 cannot be squared into a float
|
||||
if((cv::getNumThreads()<=1 || (src.total()<(int)(1<<14))) &&
|
||||
src.rows < 4097 && src.cols < 4097)
|
||||
#endif
|
||||
{
|
||||
IppStatus status;
|
||||
IppiSize roi = { src.cols, src.rows };
|
||||
Ipp8u *pBuffer;
|
||||
int bufSize=0;
|
||||
|
||||
status = ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(roi, &bufSize);
|
||||
if (status>=0)
|
||||
{
|
||||
pBuffer = (Ipp8u *)CV_IPP_MALLOC( bufSize );
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiTrueDistanceTransform_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, pBuffer);
|
||||
ippFree( pBuffer );
|
||||
if (status>=0)
|
||||
{
|
||||
// https://github.com/opencv/opencv/issues/24082
|
||||
// There is probably a rounding issue that leads to non-deterministic behavior
|
||||
// between runs on positions closer to zeros by x-axis in straight direction.
|
||||
// As a workaround, we detect the distances that expected to be exact
|
||||
// number of pixels and round manually.
|
||||
static const float correctionDiff = 1.0f / (1 << 11);
|
||||
for (int i = 0; i < dst.rows; ++i)
|
||||
{
|
||||
float* row = dst.ptr<float>(i);
|
||||
for (int j = 0; j < dst.cols; ++j)
|
||||
{
|
||||
float rounded = static_cast<float>(cvRound(row[j]));
|
||||
if (fabs(row[j] - rounded) <= correctionDiff)
|
||||
row[j] = rounded;
|
||||
}
|
||||
}
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
|
||||
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_PRECISE);
|
||||
|
||||
trueDistTrans( src, dst );
|
||||
return;
|
||||
@@ -1121,38 +1066,16 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
||||
{
|
||||
if( maskSize == cv::DIST_MASK_3 )
|
||||
{
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
|
||||
bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
|
||||
if (!has_int_overflow && CV_IPP_CHECK_COND)
|
||||
{
|
||||
IppiSize roi = { src.cols, src.rows };
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
}
|
||||
#endif
|
||||
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
|
||||
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_3);
|
||||
|
||||
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
|
||||
distanceTransform_3x3(src, temp, dst, _mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
|
||||
bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
|
||||
if (!has_int_overflow && CV_IPP_CHECK_COND)
|
||||
{
|
||||
IppiSize roi = { src.cols, src.rows };
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
}
|
||||
#endif
|
||||
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
|
||||
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_5);
|
||||
|
||||
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
|
||||
distanceTransform_5x5(src, temp, dst, _mask);
|
||||
|
||||
@@ -1067,16 +1067,6 @@ inline int hal_ni_cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_ste
|
||||
*/
|
||||
inline int hal_ni_cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
/** @brief Extract Y-plane from YUV 4:2:0 image.
|
||||
@param src_data Source image data pointer (points to Y plane).
|
||||
@param src_step Source step.
|
||||
@param dst_data Destination data pointer.
|
||||
@param dst_step Destination step.
|
||||
@param width Image width.
|
||||
@param height Image height (of the Y plane, not the full YUV image).
|
||||
*/
|
||||
inline int hal_ni_cvtColorYUV2Gray(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_cvtBGRtoBGR hal_ni_cvtBGRtoBGR
|
||||
#define cv_hal_cvtBGRtoBGR5x5 hal_ni_cvtBGRtoBGR5x5
|
||||
@@ -1110,7 +1100,6 @@ inline int hal_ni_cvtColorYUV2Gray(const uchar * src_data, size_t src_step, ucha
|
||||
#define cv_hal_cvtOnePlaneBGRtoYUVApprox hal_ni_cvtOnePlaneBGRtoYUVApprox
|
||||
#define cv_hal_cvtRGBAtoMultipliedRGBA hal_ni_cvtRGBAtoMultipliedRGBA
|
||||
#define cv_hal_cvtMultipliedRGBAtoRGBA hal_ni_cvtMultipliedRGBAtoRGBA
|
||||
#define cv_hal_cvtColorYUV2Gray hal_ni_cvtColorYUV2Gray
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@@ -1252,6 +1241,24 @@ inline int hal_ni_threshold_otsu(const uchar* src_data, size_t src_step, uchar*
|
||||
#define cv_hal_threshold_otsu hal_ni_threshold_otsu
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Calculates the distance to the closest zero pixel for each pixel of the source image
|
||||
@param src_data Source image (8-bit single-channel) data
|
||||
@param src_step Source image step
|
||||
@param dst_data Destination image data
|
||||
@param dst_step Destination image step
|
||||
@param width Source image width
|
||||
@param height Source image height
|
||||
@param dst_type Type of the destination image (CV_8UC1 or CV_32FC1)
|
||||
@param dist_type Type of distance (cv::DistanceTypes: DIST_L1, DIST_L2, DIST_C)
|
||||
@param mask_size Size of the distance transform mask (cv::DistanceTransformMasks: DIST_MASK_3, DIST_MASK_5, DIST_MASK_PRECISE)
|
||||
*/
|
||||
inline int hal_ni_distanceTransform(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int dst_type, int dist_type, int mask_size) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_distanceTransform hal_ni_distanceTransform
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Calculate box filter
|
||||
@param src_data Source image data
|
||||
@@ -1531,6 +1538,27 @@ inline int hal_ni_canny(const uchar* src_data, size_t src_step, uchar* dst_data,
|
||||
#define cv_hal_canny hal_ni_canny
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Canny edge detector from image derivatives
|
||||
@param dx_data Source image x-derivative data
|
||||
@param dx_step Source image x-derivative step
|
||||
@param dy_data Source image y-derivative data
|
||||
@param dy_step Source image y-derivative step
|
||||
@param dst_data Destination image data
|
||||
@param dst_step Destination image step
|
||||
@param width Source image width
|
||||
@param height Source image height
|
||||
@param cn Number of channels
|
||||
@param lowThreshold low hresholds value
|
||||
@param highThreshold high thresholds value
|
||||
@param L2gradient Flag, indicating use L2 or L1 norma.
|
||||
*/
|
||||
inline int hal_ni_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step, uchar* dst_data, size_t dst_step, int width, int height, int cn, double lowThreshold, double highThreshold, bool L2gradient) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_canny_deriv hal_ni_canny_deriv
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Calculates a histogram of a set of arrays
|
||||
@param src_data Source imgage data
|
||||
@@ -1551,6 +1579,32 @@ inline int hal_ni_calcHist(const uchar* src_data, size_t src_step, int src_type,
|
||||
#define cv_hal_calcHist hal_ni_calcHist
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Compares a template against overlapped image regions.
|
||||
@param src_data Source image (single-channel, CV_8U or CV_32F) data
|
||||
@param src_step Source image step
|
||||
@param src_width Source image width
|
||||
@param src_height Source image height
|
||||
@param templ_data Template image data (same type as source)
|
||||
@param templ_step Template image step
|
||||
@param templ_width Template image width
|
||||
@param templ_height Template image height
|
||||
@param result_data Destination map data (single-channel CV_32F, size (src_width-templ_width+1) x (src_height-templ_height+1))
|
||||
@param result_step Destination map step
|
||||
@param depth Depth of source and template images (CV_8U or CV_32F)
|
||||
@param cn Number of channels
|
||||
@param method Comparison method (cv::TemplateMatchModes)
|
||||
@sa matchTemplate
|
||||
*/
|
||||
inline int hal_ni_matchTemplate(const uchar* src_data, size_t src_step, int src_width, int src_height,
|
||||
const uchar* templ_data, size_t templ_step, int templ_width, int templ_height,
|
||||
float* result_data, size_t result_step, int depth, int cn, int method)
|
||||
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_matchTemplate hal_ni_matchTemplate
|
||||
//! @endcond
|
||||
|
||||
//! @}
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
@@ -1034,135 +1034,6 @@ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined HAVE_IPP
|
||||
namespace cv
|
||||
{
|
||||
typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*);
|
||||
|
||||
static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst, bool normed)
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
IppStatus status;
|
||||
|
||||
IppiSize srcRoiSize = {src.cols,src.rows};
|
||||
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
|
||||
|
||||
IppAutoBuffer<Ipp8u> buffer;
|
||||
int bufSize=0;
|
||||
|
||||
int depth = src.depth();
|
||||
|
||||
ippimatchTemplate ippiCrossCorrNorm =
|
||||
depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R:
|
||||
depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0;
|
||||
|
||||
if (ippiCrossCorrNorm==0)
|
||||
return false;
|
||||
|
||||
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid);
|
||||
if(normed)
|
||||
funCfg |= ippiNorm;
|
||||
else
|
||||
funCfg |= ippiNormNone;
|
||||
|
||||
status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
|
||||
if ( status < 0 )
|
||||
return false;
|
||||
|
||||
buffer.allocate( bufSize );
|
||||
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst)
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
IppStatus status;
|
||||
|
||||
IppiSize srcRoiSize = {src.cols,src.rows};
|
||||
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
|
||||
|
||||
IppAutoBuffer<Ipp8u> buffer;
|
||||
int bufSize=0;
|
||||
|
||||
int depth = src.depth();
|
||||
|
||||
ippimatchTemplate ippiSqrDistanceNorm =
|
||||
depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R:
|
||||
depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0;
|
||||
|
||||
if (ippiSqrDistanceNorm==0)
|
||||
return false;
|
||||
|
||||
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid | ippiNormNone);
|
||||
status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
|
||||
if ( status < 0 )
|
||||
return false;
|
||||
|
||||
buffer.allocate( bufSize );
|
||||
|
||||
status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
|
||||
dst = cv::max(dst, 0); // handle edge case from rounding in variance computation which can result in negative values
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method)
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
if(img.channels() != 1)
|
||||
return false;
|
||||
|
||||
// These functions are not efficient if template size is comparable with image size
|
||||
if(templ.size().area()*4 > img.size().area())
|
||||
return false;
|
||||
|
||||
// CV_8U SQDIFF/SQDIFF_NORMED suffer from float32 catastrophic cancellation
|
||||
// in IPP's internal accumulators; fall through to the double-precision path instead.
|
||||
if(img.depth() == CV_8U && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED))
|
||||
return false;
|
||||
|
||||
if(method == cv::TM_SQDIFF)
|
||||
{
|
||||
if(ipp_sqrDistance(img, templ, result))
|
||||
return true;
|
||||
}
|
||||
else if(method == cv::TM_SQDIFF_NORMED)
|
||||
{
|
||||
if(ipp_crossCorr(img, templ, result, false))
|
||||
{
|
||||
common_matchTemplate(img, templ, result, cv::TM_SQDIFF_NORMED, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(method == cv::TM_CCORR)
|
||||
{
|
||||
if(ipp_crossCorr(img, templ, result, false))
|
||||
return true;
|
||||
}
|
||||
else if(method == cv::TM_CCORR_NORMED)
|
||||
{
|
||||
if(ipp_crossCorr(img, templ, result, true))
|
||||
return true;
|
||||
}
|
||||
else if(method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
|
||||
{
|
||||
if(ipp_crossCorr(img, templ, result, false))
|
||||
{
|
||||
common_matchTemplate(img, templ, result, method, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
|
||||
@@ -1196,7 +1067,22 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result,
|
||||
_result.create(corrSize, CV_32F);
|
||||
Mat result = _result.getMat();
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_matchTemplate(img, templ, result, method))
|
||||
{
|
||||
int hal_res = cv_hal_matchTemplate(img.data, img.step, img.cols, img.rows,
|
||||
templ.data, templ.step, templ.cols, templ.rows,
|
||||
result.ptr<float>(), result.step, depth, cn, method);
|
||||
if (hal_res == CV_HAL_ERROR_OK)
|
||||
{
|
||||
if (method == cv::TM_SQDIFF_NORMED || method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
|
||||
common_matchTemplate(img, templ, result, method, 1);
|
||||
return;
|
||||
}
|
||||
else if (hal_res != CV_HAL_ERROR_NOT_IMPLEMENTED)
|
||||
{
|
||||
CV_Error_(cv::Error::StsInternal,
|
||||
("HAL implementation matchTemplate ==> cv_hal_matchTemplate returned %d (0x%08x)", hal_res, hal_res));
|
||||
}
|
||||
}
|
||||
|
||||
bool use64f = (depth == CV_8U) && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED);
|
||||
Mat result64f;
|
||||
|
||||
@@ -193,57 +193,6 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type )
|
||||
src_step = dst_step = roi.width;
|
||||
}
|
||||
|
||||
#if defined(HAVE_IPP)
|
||||
CV_IPP_CHECK()
|
||||
{
|
||||
IppiSize sz = { roi.width, roi.height };
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
switch( type )
|
||||
{
|
||||
case THRESH_TRUNC:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh + 1, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO_INV:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
}
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
}
|
||||
#endif
|
||||
|
||||
int j = 0;
|
||||
const uchar* src = _src.ptr();
|
||||
uchar* dst = _dst.ptr();
|
||||
@@ -577,57 +526,6 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type )
|
||||
src_step = dst_step = roi.width;
|
||||
}
|
||||
|
||||
#if defined(HAVE_IPP)
|
||||
CV_IPP_CHECK()
|
||||
{
|
||||
IppiSize sz = { roi.width, roi.height };
|
||||
CV_SUPPRESS_DEPRECATED_START
|
||||
switch( type )
|
||||
{
|
||||
case THRESH_TRUNC:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO_INV:
|
||||
if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0)
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
}
|
||||
CV_SUPPRESS_DEPRECATED_END
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CV_SIMD || CV_SIMD_SCALABLE)
|
||||
int i, j;
|
||||
v_int16 thresh8 = vx_setall_s16( thresh );
|
||||
@@ -799,40 +697,6 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type )
|
||||
roi.height = 1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_IPP)
|
||||
CV_IPP_CHECK()
|
||||
{
|
||||
IppiSize sz = { roi.width, roi.height };
|
||||
switch( type )
|
||||
{
|
||||
case THRESH_TRUNC:
|
||||
if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO:
|
||||
if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, nextafterf(thresh, std::numeric_limits<float>::infinity()), 0))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
case THRESH_TOZERO_INV:
|
||||
if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_IPP);
|
||||
return;
|
||||
}
|
||||
setIppErrorStatus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CV_SIMD || CV_SIMD_SCALABLE)
|
||||
int i, j;
|
||||
v_float32 thresh4 = vx_setall_f32( thresh );
|
||||
|
||||
Reference in New Issue
Block a user