|
|
@ -1333,69 +1333,98 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, |
|
|
|
if( iterations > 1 ) |
|
|
|
if( iterations > 1 ) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
if (IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel )) |
|
|
|
return IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel ); |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|
|
|
|
|
|
|
|
static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, |
|
|
|
static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, |
|
|
|
const Size & ksize, const Point & anchor, int iterations, int op) |
|
|
|
Point anchor, int iterations, int op, int borderType, |
|
|
|
|
|
|
|
const Scalar &, int actual_op = -1, InputArray _extraMat = noArray()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Assert(op == MORPH_ERODE || op == MORPH_DILATE); |
|
|
|
const ocl::Device & dev = ocl::Device::getDefault(); |
|
|
|
|
|
|
|
|
|
|
|
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); |
|
|
|
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); |
|
|
|
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; |
|
|
|
bool doubleSupport = dev.doubleFPConfig() > 0; |
|
|
|
|
|
|
|
|
|
|
|
if (depth == CV_64F && !doubleSupport) |
|
|
|
if ((depth == CV_64F && !doubleSupport) || borderType != BORDER_CONSTANT) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
UMat kernel8U; |
|
|
|
Mat kernel = _kernel.getMat(); |
|
|
|
kernel.convertTo(kernel8U, CV_8U); |
|
|
|
bool haveExtraMat = !_extraMat.empty(); |
|
|
|
kernel8U = kernel8U.reshape(1, 1); |
|
|
|
Size ksize = kernel.data ? kernel.size() : Size(3, 3), ssize = _src.size(); |
|
|
|
|
|
|
|
CV_Assert(actual_op <= 3 || haveExtraMat); |
|
|
|
|
|
|
|
|
|
|
|
bool rectKernel = true; |
|
|
|
if (iterations == 0 || kernel.rows*kernel.cols == 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Mat m = kernel.reshape(1, 1); |
|
|
|
_src.copyTo(_dst); |
|
|
|
for (int i = 0; i < m.size().area(); ++i) |
|
|
|
return true; |
|
|
|
if (m.at<uchar>(i) != 1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
rectKernel = false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UMat src = _src.getUMat(); |
|
|
|
if (!kernel.data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2)); |
|
|
|
|
|
|
|
anchor = Point(iterations, iterations); |
|
|
|
|
|
|
|
iterations = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
anchor = Point(anchor.x*iterations, anchor.y*iterations); |
|
|
|
|
|
|
|
kernel = getStructuringElement(MORPH_RECT, |
|
|
|
|
|
|
|
Size(ksize.width + (iterations-1)*(ksize.width-1), |
|
|
|
|
|
|
|
ksize.height + (iterations-1)*(ksize.height-1)), |
|
|
|
|
|
|
|
anchor); |
|
|
|
|
|
|
|
iterations = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ANDROID |
|
|
|
#ifdef ANDROID |
|
|
|
size_t localThreads[3] = {16, 8, 1}; |
|
|
|
size_t localThreads[2] = { 16, 8 }; |
|
|
|
#else |
|
|
|
#else |
|
|
|
size_t localThreads[3] = {16, 16, 1}; |
|
|
|
size_t localThreads[2] = { 16, 16 }; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1}; |
|
|
|
size_t globalThreads[2] = { ssize.width, ssize.height }; |
|
|
|
|
|
|
|
|
|
|
|
if (localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)) |
|
|
|
if (localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
static const char * const op2str[] = { "ERODE", "DILATE" }; |
|
|
|
// build processing
|
|
|
|
String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s%s" |
|
|
|
String processing; |
|
|
|
" -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s", anchor.x, anchor.y, |
|
|
|
Mat kernel8u; |
|
|
|
(int)localThreads[0], (int)localThreads[1], op2str[op], |
|
|
|
kernel.convertTo(kernel8u, CV_8U); |
|
|
|
doubleSupport ? " -D DOUBLE_SUPPORT" : "", rectKernel ? " -D RECTKERNEL" : "", |
|
|
|
for (int y = 0; y < kernel8u.rows; ++y) |
|
|
|
ocl::typeToStr(_src.type()), _src.depth(), cn, ocl::typeToStr(depth)); |
|
|
|
for (int x = 0; x < kernel8u.cols; ++x) |
|
|
|
|
|
|
|
if (kernel8u.at<uchar>(y, x) != 0) |
|
|
|
|
|
|
|
processing += format("PROCESS(%d,%d)", y, x); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * const op2str[] = { "OP_ERODE", "OP_DILATE", NULL, NULL, "OP_GRADIENT", "OP_TOPHAT", "OP_BLACKHAT" }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char cvt[2][50]; |
|
|
|
|
|
|
|
int wdepth = std::max(depth, CV_32F), scalarcn = cn == 3 ? 4 : cn; |
|
|
|
|
|
|
|
|
|
|
|
std::vector<ocl::Kernel> kernels; |
|
|
|
if (actual_op < 0) |
|
|
|
|
|
|
|
actual_op = op; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<ocl::Kernel> kernels(iterations); |
|
|
|
for (int i = 0; i < iterations; i++) |
|
|
|
for (int i = 0; i < iterations; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ocl::Kernel k("morph", ocl::imgproc::morph_oclsrc, buildOptions); |
|
|
|
int current_op = iterations == i + 1 ? actual_op : op; |
|
|
|
if (k.empty()) |
|
|
|
String buildOptions = format("-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s%s" |
|
|
|
|
|
|
|
" -D PROCESS_ELEMS=%s -D T=%s -D DEPTH_%d -D cn=%d -D T1=%s" |
|
|
|
|
|
|
|
" -D convertToWT=%s -D convertToT=%s -D ST=%s%s", |
|
|
|
|
|
|
|
anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], |
|
|
|
|
|
|
|
doubleSupport ? " -D DOUBLE_SUPPORT" : "", processing.c_str(), |
|
|
|
|
|
|
|
ocl::typeToStr(type), depth, cn, ocl::typeToStr(depth), |
|
|
|
|
|
|
|
ocl::convertTypeStr(depth, wdepth, cn, cvt[0]), |
|
|
|
|
|
|
|
ocl::convertTypeStr(wdepth, depth, cn, cvt[1]), |
|
|
|
|
|
|
|
ocl::typeToStr(CV_MAKE_TYPE(depth, scalarcn)), |
|
|
|
|
|
|
|
current_op == op ? "" : cv::format(" -D %s", op2str[current_op]).c_str()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kernels[i].create("morph", ocl::imgproc::morph_oclsrc, buildOptions); |
|
|
|
|
|
|
|
if (kernels[i].empty()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
kernels.push_back(k); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UMat src = _src.getUMat(), extraMat = _extraMat.getUMat(); |
|
|
|
_dst.create(src.size(), src.type()); |
|
|
|
_dst.create(src.size(), src.type()); |
|
|
|
UMat dst = _dst.getUMat(); |
|
|
|
UMat dst = _dst.getUMat(); |
|
|
|
|
|
|
|
|
|
|
@ -1406,9 +1435,13 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, |
|
|
|
src.locateROI(wholesize, ofs); |
|
|
|
src.locateROI(wholesize, ofs); |
|
|
|
int wholecols = wholesize.width, wholerows = wholesize.height; |
|
|
|
int wholecols = wholesize.width, wholerows = wholesize.height; |
|
|
|
|
|
|
|
|
|
|
|
kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
if (haveExtraMat) |
|
|
|
ofs.x, ofs.y, src.cols, src.rows, ocl::KernelArg::PtrReadOnly(kernel8U), |
|
|
|
kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
wholecols, wholerows); |
|
|
|
ofs.x, ofs.y, src.cols, src.rows, wholecols, wholerows, |
|
|
|
|
|
|
|
ocl::KernelArg::ReadOnlyNoSize(extraMat)); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
|
|
|
|
ofs.x, ofs.y, src.cols, src.rows, wholecols, wholerows); |
|
|
|
|
|
|
|
|
|
|
|
return kernels[0].run(2, globalThreads, localThreads, false); |
|
|
|
return kernels[0].run(2, globalThreads, localThreads, false); |
|
|
|
} |
|
|
|
} |
|
|
@ -1422,19 +1455,20 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, |
|
|
|
if (i == 0) |
|
|
|
if (i == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cols = src.cols, rows = src.rows; |
|
|
|
int cols = src.cols, rows = src.rows; |
|
|
|
src.locateROI(wholesize,ofs); |
|
|
|
src.locateROI(wholesize, ofs); |
|
|
|
src.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); |
|
|
|
src.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); |
|
|
|
if(src.u != dst.u) |
|
|
|
if(src.u != dst.u) |
|
|
|
source = src; |
|
|
|
source = src; |
|
|
|
else |
|
|
|
else |
|
|
|
src.copyTo(source); |
|
|
|
src.copyTo(source); |
|
|
|
|
|
|
|
|
|
|
|
src.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
|
src.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
|
source.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
|
source.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cols = dst.cols, rows = dst.rows; |
|
|
|
int cols = dst.cols, rows = dst.rows; |
|
|
|
dst.locateROI(wholesize,ofs); |
|
|
|
dst.locateROI(wholesize, ofs); |
|
|
|
dst.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); |
|
|
|
dst.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x); |
|
|
|
dst.copyTo(source); |
|
|
|
dst.copyTo(source); |
|
|
|
dst.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
|
dst.adjustROI(-ofs.y, -wholesize.height + rows + ofs.y, -ofs.x, -wholesize.width + cols + ofs.x); |
|
|
@ -1442,13 +1476,18 @@ static bool ocl_morphology_op(InputArray _src, OutputArray _dst, Mat kernel, |
|
|
|
} |
|
|
|
} |
|
|
|
source.locateROI(wholesize, ofs); |
|
|
|
source.locateROI(wholesize, ofs); |
|
|
|
|
|
|
|
|
|
|
|
kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
if (haveExtraMat && iterations == i + 1) |
|
|
|
ofs.x, ofs.y, source.cols, source.rows, ocl::KernelArg::PtrReadOnly(kernel8U), |
|
|
|
kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
wholesize.width, wholesize.height); |
|
|
|
ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height, |
|
|
|
|
|
|
|
ocl::KernelArg::ReadOnlyNoSize(extraMat)); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst), |
|
|
|
|
|
|
|
ofs.x, ofs.y, source.cols, source.rows, wholesize.width, wholesize.height); |
|
|
|
|
|
|
|
|
|
|
|
if (!kernels[i].run(2, globalThreads, localThreads, false)) |
|
|
|
if (!kernels[i].run(2, globalThreads, localThreads, false)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1459,15 +1498,16 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, |
|
|
|
Point anchor, int iterations, |
|
|
|
Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|
|
|
|
int src_type = _src.type(), |
|
|
|
|
|
|
|
src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Mat kernel = _kernel.getMat(); |
|
|
|
Mat kernel = _kernel.getMat(); |
|
|
|
Size ksize = kernel.data ? kernel.size() : Size(3,3); |
|
|
|
Size ksize = kernel.data ? kernel.size() : Size(3,3); |
|
|
|
anchor = normalizeAnchor(anchor, ksize); |
|
|
|
anchor = normalizeAnchor(anchor, ksize); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && |
|
|
|
|
|
|
|
borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && |
|
|
|
|
|
|
|
(op == MORPH_ERODE || op == MORPH_DILATE) && |
|
|
|
|
|
|
|
anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1, |
|
|
|
|
|
|
|
ocl_morphOp(_src, _dst, kernel, anchor, iterations, op, borderType, borderValue) ) |
|
|
|
|
|
|
|
|
|
|
|
if (iterations == 0 || kernel.rows*kernel.cols == 1) |
|
|
|
if (iterations == 0 || kernel.rows*kernel.cols == 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
_src.copyTo(_dst); |
|
|
|
_src.copyTo(_dst); |
|
|
@ -1490,12 +1530,6 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, |
|
|
|
iterations = 1; |
|
|
|
iterations = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && src_cn <= 4 && |
|
|
|
|
|
|
|
(src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && |
|
|
|
|
|
|
|
borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue() && |
|
|
|
|
|
|
|
(op == MORPH_ERODE || op == MORPH_DILATE), |
|
|
|
|
|
|
|
ocl_morphology_op(_src, _dst, kernel, ksize, anchor, iterations, op) ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if IPP_VERSION_X100 >= 801 |
|
|
|
#if IPP_VERSION_X100 >= 801 |
|
|
|
if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) ) |
|
|
|
if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) ) |
|
|
|
return; |
|
|
|
return; |
|
|
@ -1515,13 +1549,6 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, |
|
|
|
|
|
|
|
|
|
|
|
parallel_for_(Range(0, nStripes), |
|
|
|
parallel_for_(Range(0, nStripes), |
|
|
|
MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue)); |
|
|
|
MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue)); |
|
|
|
|
|
|
|
|
|
|
|
//Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(),
|
|
|
|
|
|
|
|
// kernel, anchor, borderType, borderType, borderValue );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//f->apply( src, dst );
|
|
|
|
|
|
|
|
//for( int i = 1; i < iterations; i++ )
|
|
|
|
|
|
|
|
// f->apply( dst, dst );
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
@ -1541,97 +1568,122 @@ void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, |
|
|
|
morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace cv { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, |
|
|
|
|
|
|
|
InputArray kernel, Point anchor, int iterations, |
|
|
|
|
|
|
|
int borderType, const Scalar& borderValue) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
_dst.createSameSize(_src, _src.type()); |
|
|
|
|
|
|
|
bool submat = _dst.isSubmatrix(); |
|
|
|
|
|
|
|
UMat temp; |
|
|
|
|
|
|
|
_OutputArray _temp = submat ? _dst : _OutputArray(temp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch( op ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case MORPH_ERODE: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_DILATE: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_OPEN: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_CLOSE: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_GRADIENT: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue, MORPH_GRADIENT, temp )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_TOPHAT: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue, MORPH_TOPHAT, _src )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MORPH_BLACKHAT: |
|
|
|
|
|
|
|
if (!ocl_morphOp( _src, _temp, kernel, anchor, iterations, MORPH_DILATE, borderType, borderValue )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (!ocl_morphOp( _temp, _dst, kernel, anchor, iterations, MORPH_ERODE, borderType, borderValue, MORPH_BLACKHAT, _src )) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
CV_Error( CV_StsBadArg, "unknown morphological operation" ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, |
|
|
|
void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, |
|
|
|
InputArray kernel, Point anchor, int iterations, |
|
|
|
InputArray kernel, Point anchor, int iterations, |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
int borderType, const Scalar& borderValue ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int src_type = _src.type(), dst_type = _dst.type(), |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
src_cn = CV_MAT_CN(src_type), src_depth = CV_MAT_DEPTH(src_type); |
|
|
|
Size ksize = kernel.size(); |
|
|
|
|
|
|
|
anchor = normalizeAnchor(anchor, ksize); |
|
|
|
|
|
|
|
|
|
|
|
bool use_opencl = cv::ocl::useOpenCL() && _src.isUMat() && _src.size() == _dst.size() && src_type == dst_type && |
|
|
|
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 && |
|
|
|
_src.dims()<=2 && (src_cn == 1 || src_cn == 4) && (anchor.x == -1) && (anchor.y == -1) && |
|
|
|
anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1 && |
|
|
|
(src_depth == CV_8U || src_depth == CV_32F || src_depth == CV_64F ) && |
|
|
|
borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue(), |
|
|
|
(borderType == cv::BORDER_CONSTANT) && (borderValue == morphologyDefaultBorderValue()); |
|
|
|
ocl_morphologyEx(_src, _dst, op, kernel, anchor, iterations, borderType, borderValue)) |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
_dst.create(_src.size(), _src.type()); |
|
|
|
Mat src = _src.getMat(), temp; |
|
|
|
Mat src, dst, temp; |
|
|
|
_dst.create(src.size(), src.type()); |
|
|
|
UMat usrc, udst, utemp; |
|
|
|
Mat dst = _dst.getMat(); |
|
|
|
|
|
|
|
|
|
|
|
switch( op ) |
|
|
|
switch( op ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case MORPH_ERODE: |
|
|
|
case MORPH_ERODE: |
|
|
|
erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
erode( src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case MORPH_DILATE: |
|
|
|
case MORPH_DILATE: |
|
|
|
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case MORPH_OPEN: |
|
|
|
case MORPH_OPEN: |
|
|
|
erode( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
erode( src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( _dst, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case CV_MOP_CLOSE: |
|
|
|
case CV_MOP_CLOSE: |
|
|
|
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
erode( _dst, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
erode( dst, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case CV_MOP_GRADIENT: |
|
|
|
case CV_MOP_GRADIENT: |
|
|
|
erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
erode( src, temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( _src, _dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
dilate( src, dst, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
if(use_opencl) |
|
|
|
dst -= temp; |
|
|
|
{ |
|
|
|
|
|
|
|
udst = _dst.getUMat(); |
|
|
|
|
|
|
|
subtract(udst, utemp, udst); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
dst = _dst.getMat(); |
|
|
|
|
|
|
|
dst -= temp; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
case CV_MOP_TOPHAT: |
|
|
|
case CV_MOP_TOPHAT: |
|
|
|
if(use_opencl) |
|
|
|
if( src.data != dst.data ) |
|
|
|
{ |
|
|
|
temp = dst; |
|
|
|
usrc = _src.getUMat(); |
|
|
|
erode( src, temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
udst = _dst.getUMat(); |
|
|
|
dilate( temp, temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
if( usrc.u != udst.u ) |
|
|
|
dst = src - temp; |
|
|
|
utemp = udst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
src = _src.getMat(); |
|
|
|
|
|
|
|
dst = _dst.getMat(); |
|
|
|
|
|
|
|
if( src.data != dst.data ) |
|
|
|
|
|
|
|
temp = dst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
erode( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
|
|
|
|
dilate( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, |
|
|
|
|
|
|
|
anchor, iterations, borderType, borderValue ); |
|
|
|
|
|
|
|
if(use_opencl) |
|
|
|
|
|
|
|
subtract(usrc, utemp, udst); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
dst = src - temp; |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
case CV_MOP_BLACKHAT: |
|
|
|
case CV_MOP_BLACKHAT: |
|
|
|
if(use_opencl) |
|
|
|
if( src.data != dst.data ) |
|
|
|
{ |
|
|
|
temp = dst; |
|
|
|
usrc = _src.getUMat(); |
|
|
|
dilate( src, temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
udst = _dst.getUMat(); |
|
|
|
erode( temp, temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
if( usrc.u != udst.u ) |
|
|
|
dst = temp - src; |
|
|
|
utemp = udst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
src = _src.getMat(); |
|
|
|
|
|
|
|
dst = _dst.getMat(); |
|
|
|
|
|
|
|
if( src.data != dst.data ) |
|
|
|
|
|
|
|
temp = dst; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
dilate( _src, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, anchor, iterations, borderType, borderValue ); |
|
|
|
|
|
|
|
erode( use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, use_opencl ? (cv::OutputArray)utemp : (cv::OutputArray)temp, kernel, |
|
|
|
|
|
|
|
anchor, iterations, borderType, borderValue ); |
|
|
|
|
|
|
|
if(use_opencl) |
|
|
|
|
|
|
|
subtract(utemp, usrc, udst); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
dst = temp - src; |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
CV_Error( CV_StsBadArg, "unknown morphological operation" ); |
|
|
|
CV_Error( CV_StsBadArg, "unknown morphological operation" ); |
|
|
|