|
|
|
@ -40,7 +40,9 @@ |
|
|
|
|
//M*/
|
|
|
|
|
|
|
|
|
|
#include "precomp.hpp" |
|
|
|
|
|
|
|
|
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) |
|
|
|
|
static IppStatus sts = ippInit(); |
|
|
|
|
#endif |
|
|
|
|
/****************************************************************************************/ |
|
|
|
|
|
|
|
|
|
/* lightweight convolution with 3x3 kernel */ |
|
|
|
@ -237,9 +239,245 @@ Ptr<FilterEngine> createDerivFilter(int srcType, int dstType, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) |
|
|
|
|
|
|
|
|
|
static bool IPPDerivScharr(const Mat& src, Mat& dst, int ddepth, int dx, int dy, double scale) |
|
|
|
|
{ |
|
|
|
|
int bufSize = 0; |
|
|
|
|
cv::AutoBuffer<char> buffer; |
|
|
|
|
IppiSize roi = ippiSize(src.cols, src.rows); |
|
|
|
|
|
|
|
|
|
if( ddepth < 0 ) |
|
|
|
|
ddepth = src.depth(); |
|
|
|
|
|
|
|
|
|
dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); |
|
|
|
|
|
|
|
|
|
switch(src.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_8U: |
|
|
|
|
{ |
|
|
|
|
if(scale != 1) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
switch(dst.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_16S: |
|
|
|
|
{ |
|
|
|
|
if((dx == 1) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterScharrVertGetBufferSize_8u16s_C1R(roi,&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterScharrVertBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 1)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterScharrHorizGetBufferSize_8u16s_C1R(roi,&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterScharrHorizBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case CV_32F: |
|
|
|
|
{ |
|
|
|
|
switch(dst.type()) |
|
|
|
|
{ |
|
|
|
|
case CV_32F: |
|
|
|
|
if((dx == 1) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterScharrVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterScharrVertBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
/* IPP is fast, so MulC produce very little perf degradation */ |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f*)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 1)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterScharrHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterScharrHorizBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int ksize, double scale) |
|
|
|
|
{ |
|
|
|
|
int bufSize = 0; |
|
|
|
|
cv::AutoBuffer<char> buffer; |
|
|
|
|
|
|
|
|
|
if(ksize == 3 || ksize == 5) |
|
|
|
|
{ |
|
|
|
|
if( ddepth < 0 ) |
|
|
|
|
ddepth = src.depth(); |
|
|
|
|
|
|
|
|
|
dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); |
|
|
|
|
|
|
|
|
|
if(src.type() == CV_8U && dst.type() == CV_16S && scale == 1) |
|
|
|
|
{ |
|
|
|
|
if((dx == 1) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelNegVertBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 1)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelHorizGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelHorizBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 2) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelVertSecondBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 2)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelHorizSecondBorder_8u16s_C1R((const Ipp8u*)src.data, src.step, |
|
|
|
|
(Ipp16s*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(src.type() == CV_32F && dst.type() == CV_32F) |
|
|
|
|
{ |
|
|
|
|
if((dx == 1) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelNegVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelNegVertBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 1)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelHorizBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 2) && (dy == 0)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelVertSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelVertSecondBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((dx == 0) && (dy == 2)) |
|
|
|
|
{ |
|
|
|
|
ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize); |
|
|
|
|
buffer.allocate(bufSize); |
|
|
|
|
|
|
|
|
|
ippiFilterSobelHorizSecondBorder_32f_C1R((const Ipp32f*)src.data, src.step, |
|
|
|
|
(Ipp32f*)dst.data, dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), |
|
|
|
|
ippBorderRepl, 0, (Ipp8u*)(char*)buffer); |
|
|
|
|
if(scale != 1) |
|
|
|
|
ippiMulC_32f_C1IR((Ipp32f)scale,(Ipp32f *)dst.data,dst.step,ippiSize(dst.cols*dst.channels(),dst.rows)); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(ksize <= 0) |
|
|
|
|
return IPPDerivScharr(src, dst, ddepth, dx, dy, scale); |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, |
|
|
|
|
int ksize, double scale, double delta, int borderType ) |
|
|
|
|
{ |
|
|
|
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) |
|
|
|
|
if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) |
|
|
|
|
{ |
|
|
|
|
if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale) == true) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); |
|
|
|
|
|
|
|
|
|
Mat kx, ky; |
|
|
|
@ -260,6 +498,13 @@ void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, |
|
|
|
|
void Scharr( const Mat& src, Mat& dst, int ddepth, int dx, int dy, |
|
|
|
|
double scale, double delta, int borderType ) |
|
|
|
|
{ |
|
|
|
|
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) |
|
|
|
|
if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) |
|
|
|
|
{ |
|
|
|
|
if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale) == true) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); |
|
|
|
|
|
|
|
|
|
Mat kx, ky; |
|
|
|
|