diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 845e001249..f024a521c7 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -43,6 +43,7 @@ #include "precomp.hpp" #include #include +#include "opencl_kernels.hpp" /****************************************************************************************\ Basic Morphological Operations: Erosion & Dilation @@ -1283,11 +1284,132 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, } #endif +static const char* op2str[] = {"ERODE", "DILATE"}; + +static bool ocl_morphology_op(InputArray _src, OutputArray _dst, InputArray _kernel, Size &ksize, const Point anchor, int iterations, int op) +{ + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if (_src.depth() == CV_64F && !doubleSupport) + return false; + + UMat kernel8U; + _kernel.getUMat().convertTo(kernel8U, CV_8U); + UMat kernel = kernel8U.reshape(1, 1); + + bool rectKernel = true; + for(int i = 0; i < kernel.rows * kernel.cols; ++i) + if(kernel.getMat(ACCESS_READ).at(i) != 1) + rectKernel = false; + + UMat src = _src.getUMat(); + +#ifdef ANDROID + size_t localThreads[3] = {16, 8, 1}; +#else + size_t localThreads[3] = {16, 16, 1}; +#endif + size_t globalThreads[3] = {(src.cols + localThreads[0] - 1) / localThreads[0] *localThreads[0], (src.rows + localThreads[1] - 1) / localThreads[1] *localThreads[1], 1}; + + if(localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1)) + return false; + + char compile_option[128]; + sprintf(compile_option, "-D RADIUSX=%d -D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D %s %s %s -D GENTYPE=%s -D DEPTH_%d", + anchor.x, anchor.y, (int)localThreads[0], (int)localThreads[1], op2str[op], doubleSupport?"-D DOUBLE_SUPPORT" :"", rectKernel?"-D RECTKERNEL":"", + ocl::typeToStr(_src.type()), _src.depth() ); + + std::vector kernels; + for(int i = 0; i= (r_edge) ? (elem1) : (elem2) + +__kernel void morph(__global const uchar * restrict srcptr, int src_step, int src_offset, + __global uchar * dstptr, int dst_step, int dst_offset, + int src_offset_x, int src_offset_y, + int cols, int rows, + __constant uchar * mat_kernel, + int src_whole_cols, int src_whole_rows) +{ + int l_x = get_local_id(0); + int l_y = get_local_id(1); + int x = get_group_id(0)*LSIZE0; + int y = get_group_id(1)*LSIZE1; + int start_x = x+src_offset_x-RADIUSX; + int end_x = x + src_offset_x+LSIZE0+RADIUSX; + int width = end_x -(x+src_offset_x-RADIUSX)+1; + int start_y = y+src_offset_y-RADIUSY; + int point1 = mad24(l_y,LSIZE0,l_x); + int point2 = point1 + LSIZE0*LSIZE1; + int tl_x = point1 % width; + int tl_y = point1 / width; + int tl_x2 = point2 % width; + int tl_y2 = point2 / width; + int cur_x = start_x + tl_x; + int cur_y = start_y + tl_y; + int cur_x2 = start_x + tl_x2; + int cur_y2 = start_y + tl_y2; + int start_addr = mad24(cur_y,src_step, cur_x*(int)sizeof(GENTYPE)); + int start_addr2 = mad24(cur_y2,src_step, cur_x2*(int)sizeof(GENTYPE)); + GENTYPE temp0,temp1; + __local GENTYPE LDS_DAT[2*LSIZE1*LSIZE0]; + + int end_addr = mad24(src_whole_rows - 1,src_step,src_whole_cols*(int)sizeof(GENTYPE)); + //read pixels from src + start_addr = ((start_addr < end_addr) && (start_addr > 0)) ? start_addr : 0; + start_addr2 = ((start_addr2 < end_addr) && (start_addr2 > 0)) ? start_addr2 : 0; + __global const GENTYPE * src; + src = (__global const GENTYPE *)(srcptr+start_addr); + temp0 = src[0]; + src = (__global const GENTYPE *)(srcptr+start_addr2); + temp1 = src[0]; + //judge if read out of boundary + temp0= ELEM(cur_x,0,src_whole_cols,(GENTYPE)VAL,temp0); + temp0= ELEM(cur_y,0,src_whole_rows,(GENTYPE)VAL,temp0); + + temp1= ELEM(cur_x2,0,src_whole_cols,(GENTYPE)VAL,temp1); + temp1= ELEM(cur_y2,0,src_whole_rows,(GENTYPE)VAL,temp1); + + LDS_DAT[point1] = temp0; + LDS_DAT[point2] = temp1; + barrier(CLK_LOCAL_MEM_FENCE); + GENTYPE res = (GENTYPE)VAL; + for(int i=0; i<2*RADIUSY+1; i++) + for(int j=0; j<2*RADIUSX+1; j++) + { + res = +#ifndef RECTKERNEL + mat_kernel[i*(2*RADIUSX+1)+j] ? +#endif + MORPH_OP(res,LDS_DAT[mad24(l_y+i,width,l_x+j)]) +#ifndef RECTKERNEL + :res +#endif + ; + } + int gidx = get_global_id(0); + int gidy = get_global_id(1); + if(gidx