mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 05:11:04 -05:00
Merge pull request #29409 from Prasadayus:bilateral_filter_refactor
Refactoring and moving IPP functions to HAL for bilateral_filter in Imgproc - #29409 **Performance Numbers on Intel(R) Core(TM) i9-11900K:** https://docs.google.com/spreadsheets/d/1hnH2aGmc3D88HGnvM34xczQbRZUgsKsAHorcB-DpLq4/edit?usp=sharing ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
committed by
GitHub
parent
67824754cb
commit
390c4fdcb9
@@ -27,6 +27,7 @@ add_library(ipphal STATIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/canny_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/threshold_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/distancetransform_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/bilateral_filter_ipp.cpp"
|
||||
)
|
||||
|
||||
#TODO: HAVE_IPP_ICV and HAVE_IPP_IW added as private macro till OpenCV itself is
|
||||
|
||||
@@ -86,6 +86,15 @@ int ipp_hal_filter2D(const uchar * src_data, size_t src_step, int src_type,
|
||||
#define cv_hal_filter_stateless ipp_hal_filter2D
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
|
||||
#if defined(HAVE_IPP_IW)
|
||||
int ipp_hal_bilateralFilter_offset(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn,
|
||||
int margin_left, int margin_top, int margin_right, int margin_bottom,
|
||||
int d, double sigma_color, double sigma_space, int border_type);
|
||||
#undef cv_hal_bilateralFilter_offset
|
||||
#define cv_hal_bilateralFilter_offset ipp_hal_bilateralFilter_offset
|
||||
#endif
|
||||
|
||||
#endif //IPP_VERSION_X100 >= 810
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
169
hal/ipp/src/bilateral_filter_ipp.cpp
Normal file
169
hal/ipp/src/bilateral_filter_ipp.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
// 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 "precomp_ipp.hpp"
|
||||
|
||||
#define IPP_BILATERAL_PARALLEL 1
|
||||
|
||||
namespace {
|
||||
|
||||
class ipp_bilateralFilterParallel : public cv::ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ipp_bilateralFilterParallel(::ipp::IwiImage &_src, ::ipp::IwiImage &_dst, int _radius, Ipp32f _valSquareSigma, Ipp32f _posSquareSigma, ::ipp::IwiBorderType _borderType, bool *_ok):
|
||||
src(_src), dst(_dst)
|
||||
{
|
||||
pOk = _ok;
|
||||
|
||||
radius = _radius;
|
||||
valSquareSigma = _valSquareSigma;
|
||||
posSquareSigma = _posSquareSigma;
|
||||
borderType = _borderType;
|
||||
|
||||
*pOk = true;
|
||||
}
|
||||
~ipp_bilateralFilterParallel() {}
|
||||
|
||||
virtual void operator() (const cv::Range& range) const CV_OVERRIDE
|
||||
{
|
||||
if(*pOk == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start);
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile);
|
||||
}
|
||||
catch(const ::ipp::IwException &)
|
||||
{
|
||||
*pOk = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
private:
|
||||
::ipp::IwiImage &src;
|
||||
::ipp::IwiImage &dst;
|
||||
|
||||
int radius;
|
||||
Ipp32f valSquareSigma;
|
||||
Ipp32f posSquareSigma;
|
||||
::ipp::IwiBorderType borderType;
|
||||
|
||||
bool *pOk;
|
||||
const ipp_bilateralFilterParallel& operator= (const ipp_bilateralFilterParallel&);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int ipp_hal_bilateralFilter_offset(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn,
|
||||
int margin_left, int margin_top, int margin_right, int margin_bottom,
|
||||
int d, double sigma_color, double sigma_space, int border_type)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
if(!((depth == CV_8U || depth == CV_32F) && (cn == 1 || cn == 3)))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Map cv border to IPP; include BORDER_REFLECT_101 (the default) which the shared
|
||||
// plugin ippiGetBorderType does not cover.
|
||||
int bt = border_type & ~cv::BORDER_ISOLATED;
|
||||
IppiBorderType ippBorderType = bt == cv::BORDER_CONSTANT ? ippBorderConst :
|
||||
bt == cv::BORDER_REPLICATE ? ippBorderRepl :
|
||||
bt == cv::BORDER_REFLECT_101 ? ippBorderMirror :
|
||||
bt == cv::BORDER_TRANSPARENT ? ippBorderTransp :
|
||||
(IppiBorderType)-1;
|
||||
if((int)ippBorderType == -1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
int radius = std::max((d <= 0) ? cvRound(sigma_space*1.5) : d/2, 1);
|
||||
Ipp32f valSquareSigma = (Ipp32f)(sigma_color*sigma_color);
|
||||
Ipp32f posSquareSigma = (Ipp32f)(sigma_space*sigma_space);
|
||||
|
||||
IwSize marginLeft = margin_left;
|
||||
IwSize marginTop = margin_top;
|
||||
IwSize marginRight = margin_right;
|
||||
IwSize marginBottom = margin_bottom;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiBorderSize inMemBorder(marginLeft, marginTop, marginRight, marginBottom);
|
||||
|
||||
::ipp::IwiImage iwSrc;
|
||||
iwSrc.Init(IwiSize{width, height}, ippiGetDataType(depth), cn, inMemBorder, (void*)src_data, IwSize(src_step));
|
||||
::ipp::IwiImage iwDst;
|
||||
iwDst.Init(IwiSize{width, height}, ippiGetDataType(depth), cn, ::ipp::IwiBorderSize(), dst_data, IwSize(dst_step));
|
||||
|
||||
// already have physical border
|
||||
int inMemFlags = 0;
|
||||
if(!(border_type & cv::BORDER_ISOLATED))
|
||||
{
|
||||
if(marginLeft)
|
||||
{
|
||||
if(marginLeft >= radius) inMemFlags |= ippBorderInMemLeft;
|
||||
else return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if(marginTop)
|
||||
{
|
||||
if(marginTop >= radius) inMemFlags |= ippBorderInMemTop;
|
||||
else return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if(marginRight)
|
||||
{
|
||||
if(marginRight >= radius) inMemFlags |= ippBorderInMemRight;
|
||||
else return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if(marginBottom)
|
||||
{
|
||||
if(marginBottom >= radius) inMemFlags |= ippBorderInMemBottom;
|
||||
else return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
::ipp::IwiBorderType ippBorder((IppiBorderType)(ippBorderType | inMemFlags));
|
||||
|
||||
const int threads = ippiSuggestThreadsNum(iwDst, 2);
|
||||
if(IPP_BILATERAL_PARALLEL && threads > 1)
|
||||
{
|
||||
bool ok = true;
|
||||
cv::Range range(0, (int)iwDst.m_size.height);
|
||||
ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok);
|
||||
if(!ok)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Tile height can't be smaller than the radius.
|
||||
// Otherwise, the second tile has mixed top border (pixels from both
|
||||
// inmem and outside should be used), which is not supported in IPP.
|
||||
int maxTiles = (int)iwDst.m_size.height / radius;
|
||||
int numTiles = threads * 4;
|
||||
if(numTiles > maxTiles)
|
||||
{
|
||||
// Keep the tiles number as multiple of threads for the better workload balance.
|
||||
numTiles = (maxTiles / threads) * threads;
|
||||
}
|
||||
cv::parallel_for_(range, invoker, numTiles);
|
||||
|
||||
if(!ok)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder);
|
||||
}
|
||||
}
|
||||
catch(const ::ipp::IwException &)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -58,6 +58,12 @@
|
||||
|
||||
namespace cv {
|
||||
|
||||
static inline int bilateralRadius(int d, double sigmaSpace)
|
||||
{
|
||||
int radius = (d <= 0) ? cvRound(sigmaSpace * 1.5) : d / 2;
|
||||
return std::max(radius, 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
|
||||
@@ -76,21 +82,10 @@ static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
|
||||
if (depth != CV_8U || cn > 4)
|
||||
return false;
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigma_color <= eps || sigma_space <= eps )
|
||||
{
|
||||
_src.copyTo(_dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
double gauss_color_coeff = -0.5 / (sigma_color * sigma_color);
|
||||
double gauss_space_coeff = -0.5 / (sigma_space * sigma_space);
|
||||
|
||||
if ( d <= 0 )
|
||||
radius = cvRound(sigma_space * 1.5);
|
||||
else
|
||||
radius = d / 2;
|
||||
radius = MAX(radius, 1);
|
||||
radius = bilateralRadius(d, sigma_space);
|
||||
d = radius * 2 + 1;
|
||||
|
||||
UMat src = _src.getUMat(), dst = _dst.getUMat(), temp;
|
||||
@@ -168,21 +163,10 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data );
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigma_color <= eps || sigma_space <= eps )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
float gauss_color_coeff = (float)(-0.5/(sigma_color*sigma_color));
|
||||
float gauss_space_coeff = (float)(-0.5/(sigma_space*sigma_space));
|
||||
|
||||
if( d <= 0 )
|
||||
radius = cvRound(sigma_space*1.5);
|
||||
else
|
||||
radius = d/2;
|
||||
radius = MAX(radius, 1);
|
||||
radius = bilateralRadius(d, sigma_space);
|
||||
d = radius*2 + 1;
|
||||
|
||||
Mat temp;
|
||||
@@ -248,26 +232,14 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d,
|
||||
double minValSrc=-1, maxValSrc=1;
|
||||
const int kExpNumBinsPerChannel = 1 << 12;
|
||||
int kExpNumBins = 0;
|
||||
float lastExpVal = 1.f;
|
||||
float len, scale_index;
|
||||
|
||||
CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data );
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigma_color <= eps || sigma_space <= eps )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
return;
|
||||
}
|
||||
|
||||
double gauss_color_coeff = -0.5/(sigma_color*sigma_color);
|
||||
double gauss_space_coeff = -0.5/(sigma_space*sigma_space);
|
||||
|
||||
if( d <= 0 )
|
||||
radius = cvRound(sigma_space*1.5);
|
||||
else
|
||||
radius = d/2;
|
||||
radius = MAX(radius, 1);
|
||||
radius = bilateralRadius(d, sigma_space);
|
||||
d = radius*2 + 1;
|
||||
// compute the min/max range for the input image (even if multichannel)
|
||||
|
||||
@@ -297,16 +269,27 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d,
|
||||
scale_index = kExpNumBins/len;
|
||||
|
||||
// initialize the exp LUT
|
||||
for( i = 0; i < kExpNumBins+2; i++ )
|
||||
i = 0;
|
||||
#if (CV_SIMD || CV_SIMD_SCALABLE)
|
||||
int nlanes = VTraits<v_float32>::vlanes();
|
||||
v_float32 v_scale_index = vx_setall_f32((float)scale_index);
|
||||
v_float32 v_gauss_color_coeff = vx_setall_f32((float)gauss_color_coeff);
|
||||
float counter[16] = {0., 1., 2., 3., 4., 5., 6., 7.,
|
||||
8., 9., 10., 11., 12., 13., 14., 15.};
|
||||
v_float32 v_i = vx_load(counter);
|
||||
v_float32 v_inc = vx_setall_f32(float(nlanes));
|
||||
|
||||
for( ; i < (kExpNumBins+2) - nlanes; i += nlanes )
|
||||
{
|
||||
if( lastExpVal > 0.f )
|
||||
{
|
||||
double val = i / scale_index;
|
||||
expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
|
||||
lastExpVal = expLUT[i];
|
||||
}
|
||||
else
|
||||
expLUT[i] = 0.f;
|
||||
v_float32 v_val = v_div(v_i, v_scale_index);
|
||||
v_store(expLUT + i, v_exp(v_mul(v_mul(v_val, v_val), v_gauss_color_coeff)));
|
||||
v_i = v_add(v_i, v_inc);
|
||||
}
|
||||
#endif
|
||||
for( ; i < kExpNumBins+2; i++ )
|
||||
{
|
||||
double val = i / scale_index;
|
||||
expLUT[i] = (float)std::exp(val * val * gauss_color_coeff);
|
||||
}
|
||||
|
||||
// initialize space-related bilateral filter coefficients
|
||||
@@ -325,120 +308,6 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d,
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
#define IPP_BILATERAL_PARALLEL 1
|
||||
|
||||
#ifdef HAVE_IPP_IW
|
||||
class ipp_bilateralFilterParallel: public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
ipp_bilateralFilterParallel(::ipp::IwiImage &_src, ::ipp::IwiImage &_dst, int _radius, Ipp32f _valSquareSigma, Ipp32f _posSquareSigma, ::ipp::IwiBorderType _borderType, bool *_ok):
|
||||
src(_src), dst(_dst)
|
||||
{
|
||||
pOk = _ok;
|
||||
|
||||
radius = _radius;
|
||||
valSquareSigma = _valSquareSigma;
|
||||
posSquareSigma = _posSquareSigma;
|
||||
borderType = _borderType;
|
||||
|
||||
*pOk = true;
|
||||
}
|
||||
~ipp_bilateralFilterParallel() {}
|
||||
|
||||
virtual void operator() (const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
if(*pOk == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start);
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile);
|
||||
}
|
||||
catch(const ::ipp::IwException &)
|
||||
{
|
||||
*pOk = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
private:
|
||||
::ipp::IwiImage &src;
|
||||
::ipp::IwiImage &dst;
|
||||
|
||||
int radius;
|
||||
Ipp32f valSquareSigma;
|
||||
Ipp32f posSquareSigma;
|
||||
::ipp::IwiBorderType borderType;
|
||||
|
||||
bool *pOk;
|
||||
const ipp_bilateralFilterParallel& operator= (const ipp_bilateralFilterParallel&);
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, double sigmaSpace, int borderType)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigmaColor <= eps || sigmaSpace <= eps )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
int radius = IPP_MAX(((d <= 0)?cvRound(sigmaSpace*1.5):d/2), 1);
|
||||
Ipp32f valSquareSigma = (Ipp32f)(sigmaColor*sigmaColor);
|
||||
Ipp32f posSquareSigma = (Ipp32f)(sigmaSpace*sigmaSpace);
|
||||
|
||||
// Acquire data and begin processing
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc = ippiGetImage(src);
|
||||
::ipp::IwiImage iwDst = ippiGetImage(dst);
|
||||
::ipp::IwiBorderSize borderSize(radius);
|
||||
::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
|
||||
if(!ippBorder)
|
||||
return false;
|
||||
|
||||
const int threads = ippiSuggestThreadsNum(iwDst, 2);
|
||||
if(IPP_BILATERAL_PARALLEL && threads > 1) {
|
||||
bool ok = true;
|
||||
Range range(0, (int)iwDst.m_size.height);
|
||||
ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok);
|
||||
if(!ok)
|
||||
return false;
|
||||
|
||||
// Tile height can't be smaller than the radius.
|
||||
// Otherwise, the second tile has mixed top border (pixels from both
|
||||
// inmem and outside should be used), which is not supported in IPP.
|
||||
int maxTiles = (int)iwDst.m_size.height / radius;
|
||||
int numTiles = threads * 4;
|
||||
if (numTiles > maxTiles) {
|
||||
// Keep the tiles number as multiple of threads for the better workload balance.
|
||||
numTiles = (maxTiles / threads) * threads;
|
||||
}
|
||||
parallel_for_(range, invoker, numTiles);
|
||||
|
||||
if(!ok)
|
||||
return false;
|
||||
} else {
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder);
|
||||
}
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(d); CV_UNUSED(sigmaColor); CV_UNUSED(sigmaSpace); CV_UNUSED(borderType);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
double sigmaColor, double sigmaSpace,
|
||||
int borderType )
|
||||
@@ -449,15 +318,32 @@ void bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
|
||||
_dst.create( _src.size(), _src.type() );
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigmaColor <= eps || sigmaSpace <= eps )
|
||||
{
|
||||
_src.copyTo(_dst);
|
||||
return;
|
||||
}
|
||||
|
||||
CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
|
||||
ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
CALL_HAL(bilateralFilter, cv_hal_bilateralFilter, src.data, src.step, dst.data, dst.step, src.cols, src.rows, src.depth(),
|
||||
src.channels(), d, sigmaColor, sigmaSpace, borderType);
|
||||
{
|
||||
Point ofs;
|
||||
Size wsz(src.cols, src.rows);
|
||||
if( !(borderType & BORDER_ISOLATED) )
|
||||
src.locateROI( wsz, ofs );
|
||||
|
||||
CV_IPP_RUN_FAST(ipp_bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType));
|
||||
CALL_HAL(bilateralFilter, cv_hal_bilateralFilter_offset, src.data, src.step, dst.data, dst.step,
|
||||
src.cols, src.rows, src.depth(), src.channels(),
|
||||
ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y,
|
||||
d, sigmaColor, sigmaSpace, borderType & (~BORDER_ISOLATED));
|
||||
}
|
||||
|
||||
CALL_HAL(bilateralFilter, cv_hal_bilateralFilter, src.data, src.step, dst.data, dst.step,
|
||||
src.cols, src.rows, src.depth(), src.channels(), d, sigmaColor, sigmaSpace, borderType);
|
||||
|
||||
if( src.depth() == CV_8U )
|
||||
bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType );
|
||||
|
||||
@@ -1182,6 +1182,35 @@ inline int hal_ni_bilateralFilter(const uchar* src_data, size_t src_step, uchar*
|
||||
#define cv_hal_bilateralFilter hal_ni_bilateralFilter
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Calculate bilateral filter for input tile with optional margins for submatrix. See https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
|
||||
@param src_data Source image data
|
||||
@param src_step Source image step
|
||||
@param dst_data Destination image data
|
||||
@param dst_step Destination image step
|
||||
@param width Source image width
|
||||
@param height Source image height
|
||||
@param depth Depths of source and destination image. Should support CV_8U and CV_32F
|
||||
@param cn Number of channels
|
||||
@param margin_left Left margins for source image
|
||||
@param margin_top Top margins for source image
|
||||
@param margin_right Right margins for source image
|
||||
@param margin_bottom Bottom margins for source image
|
||||
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive, it is computed from sigmaSpace
|
||||
@param sigma_color Filter sigma in the color space
|
||||
@param sigma_space Filter sigma in the coordinate space. When d>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is proportional to sigmaSpace
|
||||
@param border_type border mode used to extrapolate pixels outside of the image
|
||||
*/
|
||||
inline int hal_ni_bilateralFilter_offset(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn,
|
||||
int margin_left, int margin_top, int margin_right, int margin_bottom,
|
||||
int d, double sigma_color, double sigma_space, int border_type)
|
||||
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_bilateralFilter_offset hal_ni_bilateralFilter_offset
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief Calculates adaptive threshold
|
||||
@param src_data Source image data
|
||||
|
||||
Reference in New Issue
Block a user