opencv erode

opencv   erode

 

void cv::erode( InputArray src, OutputArray dst, InputArray kernel,
                Point anchor, int iterations,
                int borderType, const Scalar& borderValue )
{
    CV_INSTRUMENT_REGION()

    morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue );
}

 

opencv morphOp

static void morphOp( int op, InputArray _src, OutputArray _dst,
                     InputArray _kernel,
                     Point anchor, int iterations,
                     int borderType, const Scalar& borderValue )
{
    CV_INSTRUMENT_REGION()

    Mat kernel = _kernel.getMat();
    Size ksize = !kernel.empty() ? kernel.size() : Size(3,3);
    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)
    {
        _src.copyTo(_dst);
        return;
    }

    if (kernel.empty())
    {
        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;
    }

    Mat src = _src.getMat();
    _dst.create( src.size(), src.type() );
    Mat dst = _dst.getMat();

    Point s_ofs;
    Size s_wsz(src.cols, src.rows);
    Point d_ofs;
    Size d_wsz(dst.cols, dst.rows);
    bool isolated = (borderType&BORDER_ISOLATED)?true:false;
    borderType = (borderType&~BORDER_ISOLATED);

    if(!isolated)
    {
        src.locateROI(s_wsz, s_ofs);
        dst.locateROI(d_wsz, d_ofs);
    }

    hal::morph(op, src.type(), dst.type(),
               src.data, src.step,
               dst.data, dst.step,
               src.cols, src.rows,
               s_wsz.width, s_wsz.height, s_ofs.x, s_ofs.y,
               d_wsz.width, d_wsz.height, d_ofs.x, d_ofs.y,
               kernel.type(), kernel.data, kernel.step, kernel.cols, kernel.rows, anchor.x, anchor.y,
               borderType, borderValue.val, iterations,
               (src.isSubmatrix() && !isolated));
}

}

 

 

 

opencv ocl_morphOp

static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel,
                        Point anchor, int iterations, int op, int borderType,
                        const Scalar &, int actual_op = -1, InputArray _extraMat = noArray())
{
    const ocl::Device & dev = ocl::Device::getDefault();
    int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
    Mat kernel = _kernel.getMat();
    Size ksize = !kernel.empty() ? kernel.size() : Size(3, 3), ssize = _src.size();

    bool doubleSupport = dev.doubleFPConfig() > 0;
    if ((depth == CV_64F && !doubleSupport) || borderType != BORDER_CONSTANT)
        return false;

    bool haveExtraMat = !_extraMat.empty();
    CV_Assert(actual_op <= 3 || haveExtraMat);

    if (kernel.empty())
    {
        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;
    }

#ifndef __APPLE__
    int esz = CV_ELEM_SIZE(type);
    // try to use OpenCL kernel adopted for small morph kernel
    if (dev.isIntel() &&
        ((ksize.width < 5 && ksize.height < 5 && esz <= 4) ||
         (ksize.width == 5 && ksize.height == 5 && cn == 1)) &&
         (iterations == 1)
         )
    {
        if (ocl_morph3x3_8UC1(_src, _dst, kernel, anchor, op, actual_op, _extraMat))
            return true;

        if (ocl_morphSmall(_src, _dst, kernel, anchor, borderType, op, actual_op, _extraMat))
            return true;
    }
#endif

    if (iterations == 0 || kernel.rows*kernel.cols == 1)
    {
        _src.copyTo(_dst);
        return true;
    }

#ifdef __ANDROID__
    size_t localThreads[2] = { 16, 8 };
#else
    size_t localThreads[2] = { 16, 16 };
#endif
    size_t globalThreads[2] = { (size_t)ssize.width, (size_t)ssize.height };

#ifdef __APPLE__
    if( actual_op != MORPH_ERODE && actual_op != MORPH_DILATE )
        localThreads[0] = localThreads[1] = 4;
#endif

    if (localThreads[0]*localThreads[1] * 2 < (localThreads[0] + ksize.width - 1) * (localThreads[1] + ksize.height - 1))
        return false;

#ifdef __ANDROID__
    if (dev.isNVidia())
        return false;
#endif

    // build processing
    String processing;
    Mat kernel8u;
    kernel.convertTo(kernel8u, CV_8U);
    for (int y = 0; y < kernel8u.rows; ++y)
        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;

    if (actual_op < 0)
        actual_op = op;

    std::vector<ocl::Kernel> kernels(iterations);
    for (int i = 0; i < iterations; i++)
    {
        int current_op = iterations == i + 1 ? actual_op : op;
        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;
    }

    UMat src = _src.getUMat(), extraMat = _extraMat.getUMat();
    _dst.create(src.size(), src.type());
    UMat dst = _dst.getUMat();

    if (iterations == 1 && src.u != dst.u)
    {
        Size wholesize;
        Point ofs;
        src.locateROI(wholesize, ofs);
        int wholecols = wholesize.width, wholerows = wholesize.height;

        if (haveExtraMat)
            kernels[0].args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnlyNoSize(dst),
                        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);
    }

    for (int i = 0; i < iterations; i++)
    {
        UMat source;
        Size wholesize;
        Point ofs;

        if (i == 0)
        {
            int cols =  src.cols, rows = src.rows;
            src.locateROI(wholesize, ofs);
            src.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x);
            if(src.u != dst.u)
                source = src;
            else
                src.copyTo(source);

            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);
        }
        else
        {
            int cols =  dst.cols, rows = dst.rows;
            dst.locateROI(wholesize, ofs);
            dst.adjustROI(ofs.y, wholesize.height - rows - ofs.y, ofs.x, wholesize.width - cols - ofs.x);
            dst.copyTo(source);
            dst.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.locateROI(wholesize, ofs);

        if (haveExtraMat && iterations == i + 1)
            kernels[i].args(ocl::KernelArg::ReadOnlyNoSize(source), ocl::KernelArg::WriteOnlyNoSize(dst),
                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))
            return false;
    }

    return true;
}

 

 

opencv cv::hal::morph

void morph(int op, int src_type, int dst_type,
           uchar * src_data, size_t src_step,
           uchar * dst_data, size_t dst_step,
           int width, int height,
           int roi_width, int roi_height, int roi_x, int roi_y,
           int roi_width2, int roi_height2, int roi_x2, int roi_y2,
           int kernel_type, uchar * kernel_data, size_t kernel_step,
           int kernel_width, int kernel_height, int anchor_x, int anchor_y,
           int borderType, const double borderValue[4], int iterations, bool isSubmatrix)
{
    {
        bool res = halMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height,
                            roi_width, roi_height, roi_x, roi_y,
                            roi_width2, roi_height2, roi_x2, roi_y2,
                            kernel_type, kernel_data, kernel_step,
                            kernel_width, kernel_height, anchor_x, anchor_y,
                            borderType, borderValue, iterations, isSubmatrix);
        if (res)
            return;
    }

    CV_IPP_RUN_FAST(ippMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height,
                            roi_width, roi_height, roi_x, roi_y,
                            roi_width2, roi_height2, roi_x2, roi_y2,
                            kernel_type, kernel_data, kernel_step,
                            kernel_width, kernel_height, anchor_x, anchor_y,
                            borderType, borderValue, iterations, isSubmatrix));

    ocvMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height,
             roi_width, roi_height, roi_x, roi_y,
             roi_width2, roi_height2, roi_x2, roi_y2,
             kernel_type, kernel_data, kernel_step,
             kernel_width, kernel_height, anchor_x, anchor_y,
             borderType, borderValue, iterations);
}

 

 

 

代码参考:opencv3_4_1\opencv-3.4.1\modules\imgproc\src\morph.cpp

##############################################

posted @ 2021-10-18 18:49  西北逍遥  阅读(86)  评论(0编辑  收藏  举报