形态学滤波

来源:互联网 发布:小学免费教学软件 编辑:程序博客网 时间:2024/05/20 20:43

基本形态学滤波:膨胀,腐蚀

膨胀腐蚀功能:消除噪声,分割出独立的图像元素,在图像中连接相邻的元素,寻找图像中的明显的极大值区域或极小值区域,求出图像的梯度。

膨胀是向着高亮部分进行膨胀,腐蚀亮度腐蚀,呈现暗区域。


膨胀:求局部最大值,就是将图像(图像某一区域A)与核(B)进行卷积,有有一参考点(锚点)。核B与图形卷积,即计算核B覆盖的区域的像素点最大值,并把这个最大值赋给参考点指定的像素。

腐蚀是与膨胀相反的过程。


相关源码:

腐蚀:

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

static void morphOp( int op, InputArray _src, OutputArray _dst,                     InputArray _kernel,                     Point anchor, int iterations,                     int borderType, const Scalar& borderValue ){    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;    }#if IPP_VERSION_X100 >= 801    CV_IPP_CHECK()    {        if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) )        {            CV_IMPL_ADD(CV_IMPL_IPP);            return;        }    }#endif    Mat src = _src.getMat();    _dst.create( src.size(), src.type() );    Mat dst = _dst.getMat();    int nStripes = 1;#if defined HAVE_TEGRA_OPTIMIZATION    if (src.data != dst.data && iterations == 1 &&  //NOTE: threads are not used for inplace processing        (borderType & BORDER_ISOLATED) == 0 && //TODO: check border types        src.rows >= 64 ) //NOTE: just heuristics        nStripes = 4;#endif    parallel_for_(Range(0, nStripes),                  MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue));}

膨胀(dilate):

void cv::dilate( InputArray src, OutputArray dst, InputArray kernel,                 Point anchor, int iterations,                 int borderType, const Scalar& borderValue ){    morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue );}


高级形态学滤波:开运算、闭运算、形态学梯度、顶帽、黑帽

1、开运算

     先腐蚀后膨胀,可用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积,但放大了裂缝或者局部低亮度区域。

2、闭运算

    先膨胀后腐蚀,排除小型黑洞(黑色区域)。

3、形态学梯度

    膨胀图与腐蚀图之差,保留物体的边缘轮廓

4、顶帽

    原图像与开运算的结果图之差。得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且与选择核的大小相关。顶帽运算往往用来分离比邻近点亮一些的斑点。在一幅图像具有大幅的背景而微小物品比较有规律的情况下,可用其进行背景提取

5、黑帽

    闭运算与原图像之差,突出了比原图像轮廓周围的更暗区域,与选择核有关。黑帽运算用来分离比邻近点暗一些的斑点,有着非常完美的轮廓。

源码:

void cv::morphologyEx( InputArray _src, OutputArray _dst, int op,                       InputArray _kernel, Point anchor, int iterations,                       int borderType, const Scalar& borderValue ){    Mat kernel = _kernel.getMat();    if (kernel.empty())    {        kernel = getStructuringElement(MORPH_RECT, Size(3,3), Point(1,1));    }#ifdef HAVE_OPENCL    Size ksize = kernel.size();    anchor = normalizeAnchor(anchor, ksize);    CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && _src.channels() <= 4 &&        anchor.x == ksize.width >> 1 && anchor.y == ksize.height >> 1 &&        borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue(),        ocl_morphologyEx(_src, _dst, op, kernel, anchor, iterations, borderType, borderValue))#endif    Mat src = _src.getMat(), temp;    _dst.create(src.size(), src.type());    Mat dst = _dst.getMat();    switch( op )    {    case MORPH_ERODE:        erode( src, dst, kernel, anchor, iterations, borderType, borderValue );        break;    case MORPH_DILATE:        dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );        break;    case MORPH_OPEN:        erode( src, dst, kernel, anchor, iterations, borderType, borderValue );        dilate( dst, dst, kernel, anchor, iterations, borderType, borderValue );        break;    case CV_MOP_CLOSE:        dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );        erode( dst, dst, kernel, anchor, iterations, borderType, borderValue );        break;    case CV_MOP_GRADIENT:        erode( src, temp, kernel, anchor, iterations, borderType, borderValue );        dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );        dst -= temp;        break;    case CV_MOP_TOPHAT:        if( src.data != dst.data )            temp = dst;        erode( src, temp, kernel, anchor, iterations, borderType, borderValue );        dilate( temp, temp, kernel, anchor, iterations, borderType, borderValue );        dst = src - temp;        break;    case CV_MOP_BLACKHAT:        if( src.data != dst.data )            temp = dst;        dilate( src, temp, kernel, anchor, iterations, borderType, borderValue );        erode( temp, temp, kernel, anchor, iterations, borderType, borderValue );        dst = temp - src;        break;    default:        CV_Error( CV_StsBadArg, "unknown morphological operation" );    }}




0 0