OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

一.形态学操作概念

图像形态学操作是指基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学对图像进行处理。

形态学有四个基本操作:腐蚀、膨胀、开操作、闭操作,膨胀与腐蚀是图像处理中最常用的形态学操作手段。

二.形态学操作-膨胀

跟卷积操作类似,假设有图像A和结构元素B,结构元素B在图像A上面移动,其中结构元素B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。

膨胀的原理:

膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为图像A)与结构元素(我们称之为卷积核B)进行卷积。核可以是任何的形状和大小,拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoin)。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,可以把核视为模板或者掩码。

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

膨胀就是求局部最大值的操作,核B与图形卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。

膨胀和腐蚀操作的核心内容是结构元素。一般来说结构元素是由元素为1或者0的矩阵组成。结构元素为1的区域定义了图像的领域,领域内的像素在进行膨胀和腐蚀等形态学操作时要进行考虑。

膨胀函数API接口:

dst=cv2.dilate(
        InputArray src,
        OutputArray dst,
        InputArray kernel,
        Point anchor=Point(-1,-1),
        int iterations=1,
        int borderType=BORDER_CONSTANT,
        const Scalar& borderValue=morphologyDefaultBorderValue()
    );
参数详解:
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。

第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。

第三个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。
我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。

其中,getStructuringElement函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:

矩形: MORPH_RECT
交叉形: MORPH_CROSS
椭圆形: MORPH_ELLIPSE
而getStructuringElement函数的第二和第三个参数分别是内核的尺寸以及锚点的位置。

我们一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形的element形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。

getStructuringElement函数相关的调用示例代码如下:
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
 //获取自定义核
Mat element = getStructuringElement(MORPH_RECT,
    Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),
    Point( g_nStructElementSize, g_nStructElementSize ));

第四个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。

第五个参数,int类型的iterations,迭代使用erode()函数的次数,默认值为1。

第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

第七个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。

使用erode函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。而且往往结合getStructuringElement一起使用。

结构元素的API函数接口

cv::Mat kernel = getStructuringElement(int shape,Size ksize,Point anchor);
//返回值:返回指定形状和尺寸的结构元素

//结构元素的定义:形状 (MORPH_RECT(矩形核)
//MORPH_CROSS(十字交叉形核)
//MORPH_ELLIPSE(椭圆形核));结构元素大小;锚点 默认是Point(-1, -1)意思就是中心像素,也可以自己指定

//函数接口示例
cv::Mat elementRect,elementCross,elementEllipse;

    elementRect = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3),cv::Point(-1,-1));

    elementCross =
    cv::getStructuringElement(cv::MORPH_CROSS,cv::Size(3,3),cv::Point(-1,-1));

    elementEllipse =
    cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(5,5),cv::Point(-1,-1));

此外,我们也可以自定义结构元素,如下:
使用Mat_模板类自定义5×5大小十字形、菱形、方形、x形结构元素:

 //自定义核(结构元素)
    cv::Mat_<uchar> cross(5,5);
    cv::Mat_<uchar> diamond(5,5);
    cv::Mat_<uchar> x(5,5);
    cv::Mat_<uchar> square(5,5);

    // Creating the cross-shaped structuring element
    cross <<
            0, 0, 1, 0, 0,
            0, 0, 1, 0, 0,
            1, 1, 1, 1, 1,
            0, 0, 1, 0, 0,
            0, 0, 1, 0, 0;

    // Creating the diamond-shaped structuring element
    diamond <<
            0, 0, 1, 0, 0,
            0, 1, 1, 1, 0,
            1, 1, 1, 1, 1,
            0, 1, 1, 1, 0,
            0, 0, 1, 0, 0;

    // Creating the x-shaped structuring element
    x <<
            1, 0, 0, 0, 1,
            0, 1, 0, 1, 0,
            0, 0, 1, 0, 0,
            0, 1, 0, 1, 0,
            1, 0, 0, 0, 1;

    // Creating the square-shaped structuring element
    square <<
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1,
            1, 1, 1, 1, 1;

    int xnr = x.rows;
    int xnl = x.cols;
    for(int j = 0;j<xnr;j++) { char *data="x.ptr<char">(j);
        for(int i = 0; i<xnl; i++) { int value="data[i];" std::cout<<value<<" "; } std::cout<<std::endl; }< code></xnl;></xnr;j++)></uchar></uchar></uchar></uchar>

=========================================================================

三.形态学操作—腐蚀

腐蚀就是清除掉图像的一些毛刺和细节,腐蚀一般可以用来消除噪点,分割出独立的图像元素等。其本质上也是一种空间滤波,设定一个掩模,掩模中心逐次滑过每一个像素点,当前像素点(即掩模中心所对应的位置)的值设为掩模覆盖区域中像素的最小值。

腐蚀原理:

膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为图像A)与结构元素(我们称之为卷积核B)进行卷积。核可以是任何的形状和大小,拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoin)。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,可以把核视为模板或者掩码。掩膜中心位置的像素点是否与周围领域的像素点颜色一样(即是否是白色点,即像素值是否为255),若一致,则保留,不一致则该点变为黑色(值即为0)。

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

腐蚀函数API接口:

dst=cv2.erode(
        InputArray src,
        OutputArray dst,
        InputArray kernel,
        Point anchor=Point(-1,-1),
        int iterations=1,
        int borderType=BORDER_CONSTANT,
        const Scalar& borderValue=morphologyDefaultBorderValue()
     );

&#x53C2;&#x6570;&#x8BF4;&#x660E;&#xFF1A;
&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;InputArray&#x7C7B;&#x578B;&#x7684;src&#xFF0C;&#x8F93;&#x5165;&#x56FE;&#x50CF;&#xFF0C;&#x5373;&#x6E90;&#x56FE;&#x50CF;&#xFF0C;&#x586B;Mat&#x7C7B;&#x7684;&#x5BF9;&#x8C61;&#x5373;&#x53EF;&#x3002;&#x56FE;&#x50CF;&#x901A;&#x9053;&#x7684;&#x6570;&#x91CF;&#x53EF;&#x4EE5;&#x662F;&#x4EFB;&#x610F;&#x7684;&#xFF0C;&#x4F46;&#x56FE;&#x50CF;&#x6DF1;&#x5EA6;&#x5E94;&#x4E3A;CV_8U&#xFF0C;CV_16U&#xFF0C;CV_16S&#xFF0C;CV_32F&#x6216; CV_64F&#x5176;&#x4E2D;&#x4E4B;&#x4E00;&#x3002;
&#x7B2C;&#x4E8C;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;OutputArray&#x7C7B;&#x578B;&#x7684;dst&#xFF0C;&#x5373;&#x76EE;&#x6807;&#x56FE;&#x50CF;&#xFF0C;&#x9700;&#x8981;&#x548C;&#x6E90;&#x56FE;&#x7247;&#x6709;&#x4E00;&#x6837;&#x7684;&#x5C3A;&#x5BF8;&#x548C;&#x7C7B;&#x578B;&#x3002;
&#x7B2C;&#x4E09;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;InputArray&#x7C7B;&#x578B;&#x7684;kernel&#xFF0C;&#x81A8;&#x80C0;&#x64CD;&#x4F5C;&#x7684;&#x6838;&#x3002;&#x82E5;&#x4E3A;NULL&#x65F6;&#xFF0C;&#x8868;&#x793A;&#x7684;&#x662F;&#x4F7F;&#x7528;&#x53C2;&#x8003;&#x70B9;&#x4F4D;&#x4E8E;&#x4E2D;&#x5FC3;3x3&#x7684;&#x6838;&#x3002;
&#x6211;&#x4EEC;&#x4E00;&#x822C;&#x4F7F;&#x7528;&#x51FD;&#x6570; getStructuringElement&#x914D;&#x5408;&#x8FD9;&#x4E2A;&#x53C2;&#x6570;&#x7684;&#x4F7F;&#x7528;&#x3002;getStructuringElement&#x51FD;&#x6570;&#x4F1A;&#x8FD4;&#x56DE;&#x6307;&#x5B9A;&#x5F62;&#x72B6;&#x548C;&#x5C3A;&#x5BF8;&#x7684;&#x7ED3;&#x6784;&#x5143;&#x7D20;&#xFF08;&#x5185;&#x6838;&#x77E9;&#x9635;&#xFF09;&#x3002;

&#x5176;&#x4E2D;&#xFF0C;getStructuringElement&#x51FD;&#x6570;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x8868;&#x793A;&#x5185;&#x6838;&#x7684;&#x5F62;&#x72B6;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x9009;&#x62E9;&#x5982;&#x4E0B;&#x4E09;&#x79CD;&#x5F62;&#x72B6;&#x4E4B;&#x4E00;:

&#x77E9;&#x5F62;: MORPH_RECT
&#x4EA4;&#x53C9;&#x5F62;: MORPH_CROSS
&#x692D;&#x5706;&#x5F62;: MORPH_ELLIPSE
&#x800C;getStructuringElement&#x51FD;&#x6570;&#x7684;&#x7B2C;&#x4E8C;&#x548C;&#x7B2C;&#x4E09;&#x4E2A;&#x53C2;&#x6570;&#x5206;&#x522B;&#x662F;&#x5185;&#x6838;&#x7684;&#x5C3A;&#x5BF8;&#x4EE5;&#x53CA;&#x951A;&#x70B9;&#x7684;&#x4F4D;&#x7F6E;&#x3002;

&#x6211;&#x4EEC;&#x4E00;&#x822C;&#x5728;&#x8C03;&#x7528;erode&#x4EE5;&#x53CA;dilate&#x51FD;&#x6570;&#x4E4B;&#x524D;&#xFF0C;&#x5148;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;Mat&#x7C7B;&#x578B;&#x7684;&#x53D8;&#x91CF;&#x6765;&#x83B7;&#x5F97;getStructuringElement&#x51FD;&#x6570;&#x7684;&#x8FD4;&#x56DE;&#x503C;&#x3002;&#x5BF9;&#x4E8E;&#x951A;&#x70B9;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x6709;&#x9ED8;&#x8BA4;&#x503C;Point(-1,-1)&#xFF0C;&#x8868;&#x793A;&#x951A;&#x70B9;&#x4F4D;&#x4E8E;&#x4E2D;&#x5FC3;&#x3002;&#x4E14;&#x9700;&#x8981;&#x6CE8;&#x610F;&#xFF0C;&#x5341;&#x5B57;&#x5F62;&#x7684;element&#x5F62;&#x72B6;&#x552F;&#x4E00;&#x4F9D;&#x8D56;&#x4E8E;&#x951A;&#x70B9;&#x7684;&#x4F4D;&#x7F6E;&#x3002;&#x800C;&#x5728;&#x5176;&#x4ED6;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x951A;&#x70B9;&#x53EA;&#x662F;&#x5F71;&#x54CD;&#x4E86;&#x5F62;&#x6001;&#x5B66;&#x8FD0;&#x7B97;&#x7ED3;&#x679C;&#x7684;&#x504F;&#x79FB;&#x3002;

getStructuringElement&#x51FD;&#x6570;&#x76F8;&#x5173;&#x7684;&#x8C03;&#x7528;&#x793A;&#x4F8B;&#x4EE3;&#x7801;&#x5982;&#x4E0B;&#xFF1A;

&#x8C03;&#x7528;&#x8FD9;&#x6837;&#x4E4B;&#x540E;&#xFF0C;&#x6211;&#x4EEC;&#x4FBF;&#x53EF;&#x4EE5;&#x5728;&#x63A5;&#x4E0B;&#x6765;&#x8C03;&#x7528;erode&#x6216;dilate&#x51FD;&#x6570;&#x65F6;&#xFF0C;&#x7B2C;&#x4E09;&#x4E2A;&#x53C2;&#x6570;&#x586B;&#x4FDD;&#x5B58;&#x4E86;getStructuringElement&#x8FD4;&#x56DE;&#x503C;&#x7684;Mat&#x7C7B;&#x578B;&#x53D8;&#x91CF;&#x3002;&#x5BF9;&#x5E94;&#x4E8E;&#x6211;&#x4EEC;&#x4E0A;&#x9762;&#x7684;&#x793A;&#x4F8B;&#xFF0C;&#x5C31;&#x662F;&#x586B;element&#x53D8;&#x91CF;&#x3002;

&#x7B2C;&#x56DB;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;Point&#x7C7B;&#x578B;&#x7684;anchor&#xFF0C;&#x951A;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x5176;&#x6709;&#x9ED8;&#x8BA4;&#x503C;&#xFF08;-1&#xFF0C;-1&#xFF09;&#xFF0C;&#x8868;&#x793A;&#x951A;&#x4F4D;&#x4E8E;&#x4E2D;&#x5FC3;&#x3002;
&#x7B2C;&#x4E94;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;int&#x7C7B;&#x578B;&#x7684;iterations&#xFF0C;&#x8FED;&#x4EE3;&#x4F7F;&#x7528;erode&#xFF08;&#xFF09;&#x51FD;&#x6570;&#x7684;&#x6B21;&#x6570;&#xFF0C;&#x9ED8;&#x8BA4;&#x503C;&#x4E3A;1&#x3002;
&#x7B2C;&#x516D;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;int&#x7C7B;&#x578B;&#x7684;borderType&#xFF0C;&#x7528;&#x4E8E;&#x63A8;&#x65AD;&#x56FE;&#x50CF;&#x5916;&#x90E8;&#x50CF;&#x7D20;&#x7684;&#x67D0;&#x79CD;&#x8FB9;&#x754C;&#x6A21;&#x5F0F;&#x3002;&#x6CE8;&#x610F;&#x5B83;&#x6709;&#x9ED8;&#x8BA4;&#x503C;BORDER_DEFAULT&#x3002;
&#x7B2C;&#x4E03;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;const Scalar&&#x7C7B;&#x578B;&#x7684;borderValue&#xFF0C;&#x5F53;&#x8FB9;&#x754C;&#x4E3A;&#x5E38;&#x6570;&#x65F6;&#x7684;&#x8FB9;&#x754C;&#x503C;&#xFF0C;&#x6709;&#x9ED8;&#x8BA4;&#x503C;morphologyDefaultBorderValue()&#xFF0C;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x4E0D;&#x7528;&#x53BB;&#x7BA1;&#x4ED6;&#x3002;&#x9700;&#x8981;&#x7528;&#x5230;&#x5B83;&#x65F6;&#xFF0C;&#x53EF;&#x4EE5;&#x770B;&#x5B98;&#x65B9;&#x6587;&#x6863;&#x4E2D;&#x7684;createMorphologyFilter()&#x51FD;&#x6570;&#x5F97;&#x5230;&#x66F4;&#x8BE6;&#x7EC6;&#x7684;&#x89E3;&#x91CA;&#x3002;

&#x4F7F;&#x7528;erode&#x51FD;&#x6570;&#xFF0C;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x53EA;&#x9700;&#x8981;&#x586B;&#x524D;&#x9762;&#x7684;&#x4E09;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;&#x540E;&#x9762;&#x7684;&#x56DB;&#x4E2A;&#x53C2;&#x6570;&#x90FD;&#x6709;&#x9ED8;&#x8BA4;&#x503C;&#x3002;&#x800C;&#x4E14;&#x5F80;&#x5F80;&#x7ED3;&#x5408;getStructuringElement&#x4E00;&#x8D77;&#x4F7F;&#x7528;&#x3002;

腐蚀的具体操作是:用一个结构元素(一般是3×3的大小)扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的像素做”与”操作,如果都为1,则该像素为1,否则为0。

膨胀的具体操作是:用一个结构元素(一般是3×3的大小)扫描图像中的每一个像素,用结构元素中的每一个像素与其覆盖的像素做”与”操作,如果都为0,则该像素为0,否则为1。

=========================================================================

代码实现:

#include"stdafx.h"
#include <opencv2 opencv.hpp>
#include <iostream>
#include<stdio.h>
using namespace cv;
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    Mat image1 = imread("F:/photo/qx.jpg", 1);
    namedWindow("input_picture1");
    imshow("input_picture1", image1);

    Mat image2;
    Mat image3;
    cvtColor(image1, image2, COLOR_RGB2GRAY);
    namedWindow("input_picture2");
    imshow("input_picture2", image2);

    threshold(image2, image3, 65, 255, THRESH_BINARY);
    namedWindow("input_picture3");
    imshow("input_picture3", image3);

    Mat eroded;
    erode(image3, eroded, Mat());
    namedWindow("erode");
    imshow("erode", eroded);

    Mat dilated;
    dilate(image3, dilated, Mat());
    namedWindow("dilate");
    imshow("dilate", dilated);

    waitKey(0);
    return 0;
}</stdio.h></iostream></opencv2>

图像处理效果:

原图和灰度图

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

灰度图和二值化图:

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

二值化图像腐蚀膨胀效果:

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

Original: https://blog.csdn.net/weixin_44651073/article/details/126321876
Author: 肖爱Kun
Title: OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/650269/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球