OpenCV每日函数 图像过滤模块 (15) morphologyEx函数

一、概述

        执行高级形态变换。函数 cv::morphologyEx 可以使用腐蚀和膨胀作为基本操作来执行高级形态变换。任何操作都可以就地完成。 在多通道图像的情况下,每个通道都是独立处理的。       

        支持的操作如下表

Enumerator
MORPH_ERODE 

Python: cv.MORPH_ERODE

ERODE 腐蚀

MORPH_DILATE 

Python: cv.MORPH_DILATE

DILATE 膨胀
MORPH_OPEN 

Python: cv.MORPH_OPEN

an opening operation 开运算

dst=open(src,element)=dilate(erode(src,element))

MORPH_CLOSE 

Python: cv.MORPH_CLOSE

a closing operation 闭运算

dst=close(src,element)=erode(dilate(src,element))

MORPH_GRADIENT 

Python: cv.MORPH_GRADIENT

a morphological gradient 形态学梯度

dst=morph_grad(src,element)=dilate(src,element)−erode(src,element)

MORPH_TOPHAT 

Python: cv.MORPH_TOPHAT

"top hat" 顶帽

dst=tophat(src,element)=src−open(src,element)

MORPH_BLACKHAT 

Python: cv.MORPH_BLACKHAT

"black hat" 黑帽

dst=blackhat(src,element)=close(src,element)−src

MORPH_HITMISS 

Python: cv.MORPH_HITMISS

"hit or miss" .- Only supported for CV_8UC1 binary images. A tutorial can be found in the documentation 击中击不中

二、morphologyEx函数

1、函数原型

cv::morphologyEx (InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())

2、参数详解

src 源图像。 通道的数量可以是任意的。 深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。
dst 与源图像具有相同大小和类型的目标图像。
op 形态学操作的类型,请参阅 MorphTypes
kernel 结构元素。 它可以使用 getStructuringElement 创建。
anchor 与内核的锚定位置。 负值表示锚点位于内核中心。
iterations 应用腐蚀和膨胀的次数。
borderType 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。
borderValue 边界不变的情况下的边界值。 默认值具有特殊含义。

三、OpenCV源码

1、源码路径

opencv\modules\imgproc\src\morph.dispatch.cpp

2、源码代码

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

    CV_Assert(!_src.empty());

    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();

#if !IPP_DISABLE_MORPH_ADV
    //CV_IPP_RUN_FAST(ipp_morphologyEx(op, src, dst, kernel, anchor, iterations, borderType, borderValue));
#endif

    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 MORPH_CLOSE:
        dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
        erode( dst, dst, kernel, anchor, iterations, borderType, borderValue );
        break;
    case MORPH_GRADIENT:
        erode( src, temp, kernel, anchor, iterations, borderType, borderValue );
        dilate( src, dst, kernel, anchor, iterations, borderType, borderValue );
        dst -= temp;
        break;
    case MORPH_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 MORPH_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;
    case MORPH_HITMISS:
        CV_Assert(src.type() == CV_8UC1);
        if(countNonZero(kernel) <=0)
        {
            src.copyTo(dst);
            break;
        }
        {
            Mat k1, k2, e1, e2;
            k1 = (kernel == 1);
            k2 = (kernel == -1);

            if (countNonZero(k1) <= 0)
                e1 = Mat(src.size(), src.type(), Scalar(255));
            else
                erode(src, e1, k1, anchor, iterations, borderType, borderValue);

            if (countNonZero(k2) <= 0)
                e2 = Mat(src.size(), src.type(), Scalar(255));
            else
            {
                Mat src_complement;
                bitwise_not(src, src_complement);
                erode(src_complement, e2, k2, anchor, iterations, borderType, borderValue);
            }
            dst = e1 & e2;
        }
        break;
    default:
        CV_Error( CV_StsBadArg, "unknown morphological operation" );
    }
}

四、效果图像示例

原图
开运算
形态学梯度
击中击不中运算,需要单通道源图像

五、关于图像形态学其他参考

数字图像处理 图像形态学处理_坐望云起的博客-CSDN博客_数字图像处理凸壳形态学一词通常表示生物学的一个分支,涉及动物和植物的形式和结构。 在这里在数学形态学的上下文中使用相同的词作为提取图像组件的工具,这些组件在区域形状的表示和描述中很有用,例如边界、骨架和凸包。 我们还对用于预处理或后处理的形态技术感兴趣,例如形态过滤、细化和修剪。形态学技术用称为结构元素的小形状或模板探测图像。https://blog.csdn.net/bashendixie5/article/details/108333356Opencv学习笔记 形态学重建(python)_坐望云起的博客-CSDN博客_形态学开重建在形态学梯度图像的基础上,利用形态学的开闭重建运算对梯度图像进行重建,在保留重要区域伦敦的同时去除细节和噪声。import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltimg = cv.imread("C:/Users/xiaomao/Desktop/test.jpg")# 二值化imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)imgray[imgray <https://skydance.blog.csdn.net/article/details/119835855Opencv学习笔记 形态学抽取骨架_坐望云起的博客-CSDN博客_opencv骨架提取使用OpenCV库计算形态骨架。获得的骨架并不完美,但与其他现有算法相比,这是一种非常简单的方法。仅使用两个基本的形态学运算来计算形态骨架:扩张和侵蚀。在伪代码中,该算法的工作方式如下:img = ...;while (not_empty(img)){ skel = skel | (img & !open(img)); img = erosion(img);} 在每次迭代中,图像都会再次受到侵蚀,并通过计算当前侵蚀的并集减去侵蚀的开始程度...https://skydance.blog.csdn.net/article/details/108760707数字图像处理 图像形态学处理 孔洞填充_坐望云起的博客-CSDN博客_图像处理孔洞填充孔洞定义:被前景(白色)连通域包围的封闭的背景(黑色)区域,不限于圆形。如图所示。 原理:以原图像的补集作为Mask,用来限制膨胀结果;以带有白色边框的黑色图像为初始Marker,用SE对其进行连续膨胀,直至收敛;最后对Marker取补即得到最终图像,与原图相减可得到填充图像。https://skydance.blog.csdn.net/article/details/108679506数字图像处理 图像形态学处理 细化_坐望云起的博客-CSDN博客_数字图像处理细化算法图像的细化主要是针对二值图而言,对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。假设一个像素点,我们定义该点为p1,则它的八邻域点p2->p9位置,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。https://skydance.blog.csdn.net/article/details/108333244

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125255366
今日推荐