Merge pull request #1427 from SpecLad:merge-2.4
This commit is contained in:
@@ -254,19 +254,19 @@ bool CvtColorIPPLoopCopy(Mat& src, Mat& dst, const Cvt& cvt)
|
||||
return ok;
|
||||
}
|
||||
|
||||
IppStatus __stdcall ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
|
||||
static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
|
||||
IppiSize roiSize, const int *dstOrder)
|
||||
{
|
||||
return ippiSwapChannels_8u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u);
|
||||
}
|
||||
|
||||
IppStatus __stdcall ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
|
||||
static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
|
||||
IppiSize roiSize, const int *dstOrder)
|
||||
{
|
||||
return ippiSwapChannels_16u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u);
|
||||
}
|
||||
|
||||
IppStatus __stdcall ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
|
||||
static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
|
||||
IppiSize roiSize, const int *dstOrder)
|
||||
{
|
||||
return ippiSwapChannels_32f_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f);
|
||||
|
@@ -50,9 +50,73 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
static IppStatus sts = ippInit();
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize);
|
||||
typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int);
|
||||
typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int);
|
||||
typedef IppStatus (CV_STDCALL* ippiResizeSqrPixelFunc)(const void*, IppiSize, int, IppiRect, void*, int, IppiRect, double, double, double, double, int, Ipp8u *);
|
||||
|
||||
template <int channels, typename Type>
|
||||
bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func)
|
||||
{
|
||||
Type values[channels];
|
||||
for( int i = 0; i < channels; i++ )
|
||||
values[i] = (Type)value[i];
|
||||
return func(values, dataPointer, step, size) >= 0;
|
||||
}
|
||||
|
||||
bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth)
|
||||
{
|
||||
if( channels == 1 )
|
||||
{
|
||||
switch( depth )
|
||||
{
|
||||
case CV_8U:
|
||||
return ippiSet_8u_C1R((Ipp8u)value[0], (Ipp8u *)dataPointer, step, size) >= 0;
|
||||
case CV_16U:
|
||||
return ippiSet_16u_C1R((Ipp16u)value[0], (Ipp16u *)dataPointer, step, size) >= 0;
|
||||
case CV_32F:
|
||||
return ippiSet_32f_C1R((Ipp32f)value[0], (Ipp32f *)dataPointer, step, size) >= 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( channels == 3 )
|
||||
{
|
||||
switch( depth )
|
||||
{
|
||||
case CV_8U:
|
||||
return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R);
|
||||
case CV_16U:
|
||||
return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R);
|
||||
case CV_32F:
|
||||
return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R);
|
||||
}
|
||||
}
|
||||
else if( channels == 4 )
|
||||
{
|
||||
switch( depth )
|
||||
{
|
||||
case CV_8U:
|
||||
return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R);
|
||||
case CV_16U:
|
||||
return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R);
|
||||
case CV_32F:
|
||||
return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************** interpolation formulas and tables ***************/
|
||||
|
||||
const int INTER_RESIZE_COEF_BITS=11;
|
||||
@@ -1795,6 +1859,45 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec
|
||||
return k;
|
||||
}
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
class IPPresizeInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
IPPresizeInvoker(Mat &_src, Mat &_dst, double &_inv_scale_x, double &_inv_scale_y, int _mode, ippiResizeSqrPixelFunc _func, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), inv_scale_y(_inv_scale_y), mode(_mode), func(_func), ok(_ok)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
int cn = src.channels();
|
||||
IppiRect srcroi = { 0, range.start, src.cols, range.end - range.start };
|
||||
int dsty = CV_IMIN(cvRound(range.start * inv_scale_y), dst.rows);
|
||||
int dstwidth = CV_IMIN(cvRound(src.cols * inv_scale_x), dst.cols);
|
||||
int dstheight = CV_IMIN(cvRound(range.end * inv_scale_y), dst.rows);
|
||||
IppiRect dstroi = { 0, dsty, dstwidth, dstheight - dsty };
|
||||
int bufsize;
|
||||
ippiResizeGetBufSize( srcroi, dstroi, cn, mode, &bufsize );
|
||||
Ipp8u *buf;
|
||||
buf = ippsMalloc_8u( bufsize );
|
||||
IppStatus sts;
|
||||
if( func( src.data, ippiSize(src.cols, src.rows), (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, inv_scale_x, inv_scale_y, 0, 0, mode, buf ) < 0 )
|
||||
*ok = false;
|
||||
ippsFree(buf);
|
||||
}
|
||||
private:
|
||||
Mat &src;
|
||||
Mat &dst;
|
||||
double inv_scale_x;
|
||||
double inv_scale_y;
|
||||
int mode;
|
||||
ippiResizeSqrPixelFunc func;
|
||||
bool *ok;
|
||||
const IPPresizeInvoker& operator= (const IPPresizeInvoker&);
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -1937,6 +2040,34 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
|
||||
double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y;
|
||||
int k, sx, sy, dx, dy;
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int mode = interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : 0;
|
||||
int type = src.type();
|
||||
ippiResizeSqrPixelFunc ippFunc =
|
||||
type == CV_8UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C1R :
|
||||
type == CV_8UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C3R :
|
||||
type == CV_8UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C4R :
|
||||
type == CV_16UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C1R :
|
||||
type == CV_16UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C3R :
|
||||
type == CV_16UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C4R :
|
||||
type == CV_16SC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C1R :
|
||||
type == CV_16SC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C3R :
|
||||
type == CV_16SC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C4R :
|
||||
type == CV_32FC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C1R :
|
||||
type == CV_32FC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C3R :
|
||||
type == CV_32FC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C4R :
|
||||
0;
|
||||
if( ippFunc && mode != 0 )
|
||||
{
|
||||
bool ok;
|
||||
Range range(0, src.rows);
|
||||
IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, ippFunc, &ok);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
if( ok )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( interpolation == INTER_NEAREST )
|
||||
{
|
||||
resizeNN( src, dst, inv_scale_x, inv_scale_y );
|
||||
@@ -3446,6 +3577,49 @@ private:
|
||||
double *M;
|
||||
};
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
class IPPwarpAffineInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
IPPwarpAffineInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[2][3], int &_interpolation, int &_borderType, const Scalar &_borderValue, ippiWarpAffineBackFunc _func, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
IppiSize srcsize = { src.cols, src.rows };
|
||||
IppiRect srcroi = { 0, 0, src.cols, src.rows };
|
||||
IppiRect dstroi = { 0, range.start, dst.cols, range.end - range.start };
|
||||
int cnn = src.channels();
|
||||
if( borderType == BORDER_CONSTANT )
|
||||
{
|
||||
IppiSize setSize = { dst.cols, range.end - range.start };
|
||||
void *dataPointer = dst.data + dst.step[0] * range.start;
|
||||
if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) )
|
||||
{
|
||||
*ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( func( src.data, srcsize, (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, coeffs, mode ) < 0) ////Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr
|
||||
*ok = false;
|
||||
}
|
||||
private:
|
||||
Mat &src;
|
||||
Mat &dst;
|
||||
double (&coeffs)[2][3];
|
||||
int mode;
|
||||
int borderType;
|
||||
Scalar borderValue;
|
||||
ippiWarpAffineBackFunc func;
|
||||
bool *ok;
|
||||
const IPPwarpAffineInvoker& operator= (const IPPwarpAffineInvoker&);
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3492,6 +3666,50 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
|
||||
const int AB_BITS = MAX(10, (int)INTER_BITS);
|
||||
const int AB_SCALE = 1 << AB_BITS;
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int depth = src.depth();
|
||||
int channels = src.channels();
|
||||
if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) &&
|
||||
( channels == 1 || channels == 3 || channels == 4 ) &&
|
||||
( borderType == cv::BORDER_TRANSPARENT || ( borderType == cv::BORDER_CONSTANT ) ) )
|
||||
{
|
||||
int type = src.type();
|
||||
ippiWarpAffineBackFunc ippFunc =
|
||||
type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C1R :
|
||||
type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C3R :
|
||||
type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C4R :
|
||||
type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C1R :
|
||||
type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C3R :
|
||||
type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C4R :
|
||||
type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C1R :
|
||||
type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C3R :
|
||||
type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C4R :
|
||||
0;
|
||||
int mode =
|
||||
flags == INTER_LINEAR ? IPPI_INTER_LINEAR :
|
||||
flags == INTER_NEAREST ? IPPI_INTER_NN :
|
||||
flags == INTER_CUBIC ? IPPI_INTER_CUBIC :
|
||||
0;
|
||||
if( mode && ippFunc )
|
||||
{
|
||||
double coeffs[2][3];
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
coeffs[i][j] = matM.at<double>(i, j);
|
||||
}
|
||||
}
|
||||
bool ok;
|
||||
Range range(0, dst.rows);
|
||||
IPPwarpAffineInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
if( ok )
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for( x = 0; x < dst.cols; x++ )
|
||||
{
|
||||
adelta[x] = saturate_cast<int>(M[0]*x*AB_SCALE);
|
||||
@@ -3599,6 +3817,50 @@ private:
|
||||
Scalar borderValue;
|
||||
};
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
class IPPwarpPerspectiveInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
IPPwarpPerspectiveInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[3][3], int &_interpolation, int &_borderType, const Scalar &_borderValue, ippiWarpPerspectiveBackFunc _func, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
IppiSize srcsize = {src.cols, src.rows};
|
||||
IppiRect srcroi = {0, 0, src.cols, src.rows};
|
||||
IppiRect dstroi = {0, range.start, dst.cols, range.end - range.start};
|
||||
int cnn = src.channels();
|
||||
|
||||
if( borderType == BORDER_CONSTANT )
|
||||
{
|
||||
IppiSize setSize = {dst.cols, range.end - range.start};
|
||||
void *dataPointer = dst.data + dst.step[0] * range.start;
|
||||
if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) )
|
||||
{
|
||||
*ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if( func(src.data, srcsize, (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, coeffs, mode) < 0)
|
||||
*ok = false;
|
||||
}
|
||||
private:
|
||||
Mat &src;
|
||||
Mat &dst;
|
||||
double (&coeffs)[3][3];
|
||||
int mode;
|
||||
int borderType;
|
||||
const Scalar borderValue;
|
||||
ippiWarpPerspectiveBackFunc func;
|
||||
bool *ok;
|
||||
const IPPwarpPerspectiveInvoker& operator= (const IPPwarpPerspectiveInvoker&);
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
@@ -3629,6 +3891,50 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
|
||||
if( !(flags & WARP_INVERSE_MAP) )
|
||||
invert(matM, matM);
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
int depth = src.depth();
|
||||
int channels = src.channels();
|
||||
if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) &&
|
||||
( channels == 1 || channels == 3 || channels == 4 ) &&
|
||||
( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT ) )
|
||||
{
|
||||
int type = src.type();
|
||||
ippiWarpPerspectiveBackFunc ippFunc =
|
||||
type == CV_8UC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C1R :
|
||||
type == CV_8UC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C3R :
|
||||
type == CV_8UC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C4R :
|
||||
type == CV_16UC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C1R :
|
||||
type == CV_16UC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C3R :
|
||||
type == CV_16UC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C4R :
|
||||
type == CV_32FC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C1R :
|
||||
type == CV_32FC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C3R :
|
||||
type == CV_32FC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C4R :
|
||||
0;
|
||||
int mode =
|
||||
flags == INTER_LINEAR ? IPPI_INTER_LINEAR :
|
||||
flags == INTER_NEAREST ? IPPI_INTER_NN :
|
||||
flags == INTER_CUBIC ? IPPI_INTER_CUBIC :
|
||||
0;
|
||||
if( mode && ippFunc )
|
||||
{
|
||||
double coeffs[3][3];
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
coeffs[i][j] = matM.at<double>(i, j);
|
||||
}
|
||||
}
|
||||
bool ok;
|
||||
Range range(0, dst.rows);
|
||||
IPPwarpPerspectiveInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
if( ok )
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Range range(0, dst.rows);
|
||||
warpPerspectiveInvoker invoker(src, dst, M, interpolation, borderType, borderValue);
|
||||
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
|
||||
|
@@ -1213,11 +1213,10 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne
|
||||
}
|
||||
|
||||
static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
InputArray _kernel,
|
||||
const Point &anchor, int iterations,
|
||||
const Mat& _kernel, Point anchor, int iterations,
|
||||
int borderType, const Scalar &borderValue)
|
||||
{
|
||||
Mat src = _src.getMat(), kernel = _kernel.getMat();
|
||||
Mat src = _src.getMat(), kernel = _kernel;
|
||||
if( !( src.depth() == CV_8U || src.depth() == CV_32F ) || ( iterations > 1 ) ||
|
||||
!( borderType == cv::BORDER_REPLICATE || (borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue()) )
|
||||
|| !( op == MORPH_DILATE || op == MORPH_ERODE) )
|
||||
@@ -1248,9 +1247,6 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
|
||||
}
|
||||
Size ksize = kernel.data ? kernel.size() : Size(3,3);
|
||||
Point normanchor = normalizeAnchor(anchor, ksize);
|
||||
|
||||
CV_Assert( normanchor.inside(Rect(0, 0, ksize.width, ksize.height)) );
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
@@ -1265,7 +1261,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
if( !kernel.data )
|
||||
{
|
||||
ksize = Size(1+iterations*2,1+iterations*2);
|
||||
normanchor = Point(iterations, iterations);
|
||||
anchor = Point(iterations, iterations);
|
||||
rectKernel = true;
|
||||
iterations = 1;
|
||||
}
|
||||
@@ -1273,7 +1269,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
{
|
||||
ksize = Size(ksize.width + (iterations-1)*(ksize.width-1),
|
||||
ksize.height + (iterations-1)*(ksize.height-1)),
|
||||
normanchor = Point(normanchor.x*iterations, normanchor.y*iterations);
|
||||
anchor = Point(anchor.x*iterations, anchor.y*iterations);
|
||||
kernel = Mat();
|
||||
rectKernel = true;
|
||||
iterations = 1;
|
||||
@@ -1283,7 +1279,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
|
||||
if( iterations > 1 )
|
||||
return false;
|
||||
|
||||
return IPPMorphReplicate( op, src, dst, kernel, ksize, normanchor, rectKernel );
|
||||
return IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel );
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1292,18 +1288,19 @@ static void morphOp( int op, InputArray _src, OutputArray _dst,
|
||||
Point anchor, int iterations,
|
||||
int borderType, const Scalar& borderValue )
|
||||
{
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( IPPMorphOp(op, _src, _dst, _kernel, anchor, iterations, borderType, borderValue) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
Mat src = _src.getMat(), kernel = _kernel.getMat();
|
||||
Mat kernel = _kernel.getMat();
|
||||
Size ksize = kernel.data ? kernel.size() : Size(3,3);
|
||||
anchor = normalizeAnchor(anchor, ksize);
|
||||
|
||||
CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) );
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
|
@@ -1879,6 +1879,41 @@ private:
|
||||
float *space_weight, *color_weight;
|
||||
};
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
class IPPBilateralFilter_8u_Invoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
IPPBilateralFilter_8u_Invoker(Mat &_src, Mat &_dst, double _sigma_color, double _sigma_space, int _radius, bool *_ok) :
|
||||
ParallelLoopBody(), src(_src), dst(_dst), sigma_color(_sigma_color), sigma_space(_sigma_space), radius(_radius), ok(_ok)
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
|
||||
virtual void operator() (const Range& range) const
|
||||
{
|
||||
int d = radius * 2 + 1;
|
||||
IppiSize kernel = {d, d};
|
||||
IppiSize roi={dst.cols, range.end - range.start};
|
||||
int bufsize=0;
|
||||
ippiFilterBilateralGetBufSize_8u_C1R( ippiFilterBilateralGauss, roi, kernel, &bufsize);
|
||||
AutoBuffer<uchar> buf(bufsize);
|
||||
IppiFilterBilateralSpec *pSpec = (IppiFilterBilateralSpec *)alignPtr(&buf[0], 32);
|
||||
ippiFilterBilateralInit_8u_C1R( ippiFilterBilateralGauss, kernel, (Ipp32f)sigma_color, (Ipp32f)sigma_space, 1, pSpec );
|
||||
if( ippiFilterBilateral_8u_C1R( src.ptr<uchar>(range.start) + radius * ((int)src.step[0] + 1), (int)src.step[0], dst.ptr<uchar>(range.start), (int)dst.step[0], roi, kernel, pSpec ) < 0)
|
||||
*ok = false;
|
||||
}
|
||||
private:
|
||||
Mat &src;
|
||||
Mat &dst;
|
||||
double sigma_color;
|
||||
double sigma_space;
|
||||
int radius;
|
||||
bool *ok;
|
||||
const IPPBilateralFilter_8u_Invoker& operator= (const IPPBilateralFilter_8u_Invoker&);
|
||||
};
|
||||
#endif
|
||||
|
||||
static void
|
||||
bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
double sigma_color, double sigma_space,
|
||||
@@ -1908,32 +1943,19 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
radius = MAX(radius, 1);
|
||||
d = radius*2 + 1;
|
||||
|
||||
#if 0 && defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7)
|
||||
if(cn == 1)
|
||||
{
|
||||
IppiSize kernel = {d, d};
|
||||
IppiSize roi={src.cols, src.rows};
|
||||
int bufsize=0;
|
||||
ippiFilterBilateralGetBufSize_8u_C1R( ippiFilterBilateralGauss, roi, kernel, &bufsize);
|
||||
AutoBuffer<uchar> buf(bufsize+128);
|
||||
IppiFilterBilateralSpec *pSpec = (IppiFilterBilateralSpec *)alignPtr(&buf[0], 32);
|
||||
ippiFilterBilateralInit_8u_C1R( ippiFilterBilateralGauss, kernel, sigma_color*sigma_color, sigma_space*sigma_space, 1, pSpec );
|
||||
Mat tsrc;
|
||||
const Mat* psrc = &src;
|
||||
if( src.data == dst.data )
|
||||
{
|
||||
src.copyTo(tsrc);
|
||||
psrc = &tsrc;
|
||||
}
|
||||
if( ippiFilterBilateral_8u_C1R(psrc->data, (int)psrc->step[0],
|
||||
dst.data, (int)dst.step[0],
|
||||
roi, kernel, pSpec) >= 0 )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Mat temp;
|
||||
copyMakeBorder( src, temp, radius, radius, radius, radius, borderType );
|
||||
|
||||
#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7)
|
||||
if( cn == 1 )
|
||||
{
|
||||
bool ok;
|
||||
IPPBilateralFilter_8u_Invoker body(temp, dst, sigma_color * sigma_color, sigma_space * sigma_space, radius, &ok );
|
||||
parallel_for_(Range(0, dst.rows), body, dst.total()/(double)(1<<16));
|
||||
if( ok ) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<float> _color_weight(cn*256);
|
||||
std::vector<float> _space_weight(d*d);
|
||||
std::vector<int> _space_ofs(d*d);
|
||||
@@ -2258,6 +2280,236 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
"Bilateral filtering is only implemented for 8u and 32f images" );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Adaptive Bilateral Filtering
|
||||
\****************************************************************************************/
|
||||
|
||||
namespace cv
|
||||
{
|
||||
#define CALCVAR 1
|
||||
#define FIXED_WEIGHT 0
|
||||
|
||||
class adaptiveBilateralFilter_8u_Invoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
adaptiveBilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, Size _ksize, double _sigma_space, Point _anchor) :
|
||||
temp(&_temp), dest(&_dest), ksize(_ksize), sigma_space(_sigma_space), anchor(_anchor)
|
||||
{
|
||||
if( sigma_space <= 0 )
|
||||
sigma_space = 1;
|
||||
CV_Assert((ksize.width & 1) && (ksize.height & 1));
|
||||
space_weight.resize(ksize.width * ksize.height);
|
||||
double sigma2 = sigma_space * sigma_space;
|
||||
int idx = 0;
|
||||
int w = ksize.width / 2;
|
||||
int h = ksize.height / 2;
|
||||
for(int y=-h; y<=h; y++)
|
||||
for(int x=-w; x<=w; x++)
|
||||
{
|
||||
space_weight[idx++] = (float)(sigma2 / (sigma2 + x * x + y * y));
|
||||
}
|
||||
}
|
||||
virtual void operator()(const Range& range) const
|
||||
{
|
||||
int cn = dest->channels();
|
||||
int anX = anchor.x;
|
||||
|
||||
const uchar *tptr;
|
||||
|
||||
for(int i = range.start;i < range.end; i++)
|
||||
{
|
||||
int startY = i;
|
||||
if(cn == 1)
|
||||
{
|
||||
float var;
|
||||
int currVal;
|
||||
int sumVal = 0;
|
||||
int sumValSqr = 0;
|
||||
int currValCenter;
|
||||
int currWRTCenter;
|
||||
float weight;
|
||||
float totalWeight = 0.;
|
||||
float tmpSum = 0.;
|
||||
|
||||
for(int j = 0;j < dest->cols *cn; j+=cn)
|
||||
{
|
||||
sumVal = 0;
|
||||
sumValSqr= 0;
|
||||
totalWeight = 0.;
|
||||
tmpSum = 0.;
|
||||
|
||||
// Top row: don't sum the very last element
|
||||
int startLMJ = 0;
|
||||
int endLMJ = ksize.width - 1;
|
||||
int howManyAll = (anX *2 +1)*(ksize.width );
|
||||
#if CALCVAR
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
currVal = tptr[cn*(y+anX)];
|
||||
sumVal += currVal;
|
||||
sumValSqr += (currVal *currVal);
|
||||
}
|
||||
}
|
||||
var = ( (sumValSqr * howManyAll)- sumVal * sumVal ) / ( (float)(howManyAll*howManyAll));
|
||||
#else
|
||||
var = 900.0;
|
||||
#endif
|
||||
startLMJ = 0;
|
||||
endLMJ = ksize.width;
|
||||
tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2);
|
||||
currValCenter =tptr[j+cn*anX];
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
#if FIXED_WEIGHT
|
||||
weight = 1.0;
|
||||
#else
|
||||
currVal = tptr[cn*(y+anX)];
|
||||
currWRTCenter = currVal - currValCenter;
|
||||
|
||||
weight = var / ( var + (currWRTCenter * currWRTCenter) ) * space_weight[x*ksize.width+y+anX];;
|
||||
#endif
|
||||
tmpSum += ((float)tptr[cn*(y+anX)] * weight);
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
tmpSum /= totalWeight;
|
||||
|
||||
dest->at<uchar>(startY ,j)= static_cast<uchar>(tmpSum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(cn == 3);
|
||||
float var_b, var_g, var_r;
|
||||
int currVal_b, currVal_g, currVal_r;
|
||||
int sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
|
||||
int sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
|
||||
int currValCenter_b= 0, currValCenter_g= 0, currValCenter_r= 0;
|
||||
int currWRTCenter_b, currWRTCenter_g, currWRTCenter_r;
|
||||
float weight_b, weight_g, weight_r;
|
||||
float totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
|
||||
float tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
|
||||
|
||||
for(int j = 0;j < dest->cols *cn; j+=cn)
|
||||
{
|
||||
sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
|
||||
sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
|
||||
totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
|
||||
tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
|
||||
|
||||
// Top row: don't sum the very last element
|
||||
int startLMJ = 0;
|
||||
int endLMJ = ksize.width - 1;
|
||||
int howManyAll = (anX *2 +1)*(ksize.width);
|
||||
#if CALCVAR
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
currVal_b = tptr[cn*(y+anX)], currVal_g = tptr[cn*(y+anX)+1], currVal_r =tptr[cn*(y+anX)+2];
|
||||
sumVal_b += currVal_b;
|
||||
sumVal_g += currVal_g;
|
||||
sumVal_r += currVal_r;
|
||||
sumValSqr_b += (currVal_b *currVal_b);
|
||||
sumValSqr_g += (currVal_g *currVal_g);
|
||||
sumValSqr_r += (currVal_r *currVal_r);
|
||||
}
|
||||
}
|
||||
var_b = ( (sumValSqr_b * howManyAll)- sumVal_b * sumVal_b ) / ( (float)(howManyAll*howManyAll));
|
||||
var_g = ( (sumValSqr_g * howManyAll)- sumVal_g * sumVal_g ) / ( (float)(howManyAll*howManyAll));
|
||||
var_r = ( (sumValSqr_r * howManyAll)- sumVal_r * sumVal_r ) / ( (float)(howManyAll*howManyAll));
|
||||
#else
|
||||
var_b = 900.0; var_g = 900.0;var_r = 900.0;
|
||||
#endif
|
||||
startLMJ = 0;
|
||||
endLMJ = ksize.width;
|
||||
tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2) + j;
|
||||
currValCenter_b =tptr[cn*anX], currValCenter_g =tptr[cn*anX+1], currValCenter_r =tptr[cn*anX+2];
|
||||
for(int x = startLMJ; x< endLMJ; x++)
|
||||
{
|
||||
tptr = temp->ptr(startY + x) +j;
|
||||
for(int y=-anX; y<=anX; y++)
|
||||
{
|
||||
#if FIXED_WEIGHT
|
||||
weight_b = 1.0;
|
||||
weight_g = 1.0;
|
||||
weight_r = 1.0;
|
||||
#else
|
||||
currVal_b = tptr[cn*(y+anX)];currVal_g=tptr[cn*(y+anX)+1];currVal_r=tptr[cn*(y+anX)+2];
|
||||
currWRTCenter_b = currVal_b - currValCenter_b;
|
||||
currWRTCenter_g = currVal_g - currValCenter_g;
|
||||
currWRTCenter_r = currVal_r - currValCenter_r;
|
||||
|
||||
float cur_spw = space_weight[x*ksize.width+y+anX];
|
||||
weight_b = var_b / ( var_b + (currWRTCenter_b * currWRTCenter_b) ) * cur_spw;
|
||||
weight_g = var_g / ( var_g + (currWRTCenter_g * currWRTCenter_g) ) * cur_spw;
|
||||
weight_r = var_r / ( var_r + (currWRTCenter_r * currWRTCenter_r) ) * cur_spw;
|
||||
#endif
|
||||
tmpSum_b += ((float)tptr[cn*(y+anX)] * weight_b);
|
||||
tmpSum_g += ((float)tptr[cn*(y+anX)+1] * weight_g);
|
||||
tmpSum_r += ((float)tptr[cn*(y+anX)+2] * weight_r);
|
||||
totalWeight_b += weight_b, totalWeight_g += weight_g, totalWeight_r += weight_r;
|
||||
}
|
||||
}
|
||||
tmpSum_b /= totalWeight_b;
|
||||
tmpSum_g /= totalWeight_g;
|
||||
tmpSum_r /= totalWeight_r;
|
||||
|
||||
dest->at<uchar>(startY,j )= static_cast<uchar>(tmpSum_b);
|
||||
dest->at<uchar>(startY,j+1)= static_cast<uchar>(tmpSum_g);
|
||||
dest->at<uchar>(startY,j+2)= static_cast<uchar>(tmpSum_r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Mat *temp;
|
||||
Mat *dest;
|
||||
Size ksize;
|
||||
double sigma_space;
|
||||
Point anchor;
|
||||
std::vector<float> space_weight;
|
||||
};
|
||||
static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, Point anchor, int borderType )
|
||||
{
|
||||
Size size = src.size();
|
||||
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) &&
|
||||
src.type() == dst.type() && src.size() == dst.size() &&
|
||||
src.data != dst.data );
|
||||
Mat temp;
|
||||
copyMakeBorder(src, temp, anchor.x, anchor.y, anchor.x, anchor.y, borderType);
|
||||
|
||||
adaptiveBilateralFilter_8u_Invoker body(dst, temp, ksize, sigmaSpace, anchor);
|
||||
parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16));
|
||||
}
|
||||
}
|
||||
void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize,
|
||||
double sigmaSpace, Point anchor, int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3);
|
||||
|
||||
anchor = normalizeAnchor(anchor,ksize);
|
||||
if( src.depth() == CV_8U )
|
||||
adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, anchor, borderType );
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat,
|
||||
"Adaptive Bilateral filtering is only implemented for 8u images" );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_IMPL void
|
||||
|
Reference in New Issue
Block a user