[Opencv初探之七]:形态学处理

1. 膨胀和腐蚀

首先需要注意,腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
膨胀与腐蚀能实现多种多样的功能,主要如下:

  • 消除噪声
  • 分割(isolate)出独立的图像元素,在图像中连接(join)相邻的元素。
  • 寻找图像中的明显的极大值区域或极小值区域
  • 求出图像的梯度

1.1. 膨胀

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

void 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:输入图像,图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F其中之一。
  • OutputArray dst:目标图像,需要和源图片有一样的尺寸和类型。
  • InputArray kernel:膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数getStructuringElement配合这个参数的使用,getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵getStructuringElement函数的参数为内核的形状,尺寸以及锚点的位置。

使用dilate函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。
完整代码:

#include<opencv2/opencv.hpp>   

using namespace std;
using namespace cv;

//膨胀
int main()
{
    Mat img = imread("../logo2.jpg");
    namedWindow("original", WINDOW_NORMAL);
    imshow("original", img);
    Mat out;
    //获取自定义核
    Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的
    //膨胀操作
    dilate(img, out, element);
    namedWindow("膨胀操作", WINDOW_NORMAL);
    imshow("膨胀操作", out);
    imwrite("dilate.jpg",out);
    waitKey();
}

效果展示:
在这里插入图片描述在这里插入图片描述

2.2 腐蚀

膨胀和腐蚀是相反的一对操作,所以腐蚀就是求局部最小值的操作。
erode函数,使用像素邻域内的局部极小运算符来腐蚀一张图片,从src输入,由dst输出。支持就地(in-place)操作。

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

参数列表类比dilate函数,不赘述。
完整代码:

#include<opencv2/opencv.hpp>   

using namespace std;
using namespace cv;

//腐蚀
int main()
{
    Mat img = imread("../logo2.jpg");
    namedWindow("original", WINDOW_NORMAL);
    imshow("original", img);
    Mat out;
    //获取自定义核
    Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的
    //腐蚀操作
    erode(img, out, element);
    namedWindow("腐蚀操作", WINDOW_NORMAL);
    imshow("腐蚀操作", out);
    imwrite("erode.jpg",out);
    waitKey();
}

效果如下:

在这里插入图片描述腐蚀

2.开运算、闭运算、形态学梯度、顶帽、黑帽

2.1 开运算

开运算(Opening Operation),其实就是先腐蚀后膨胀的过程,可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
在这里插入图片描述在这里插入图片描述

2.2 闭运算

先膨胀后腐蚀的过程称为闭运算(Closing Operation),能够排除小型黑洞(黑色区域)
在这里插入图片描述在这里插入图片描述

2.3 形态学梯度

形态学梯度(Morphological Gradient)为膨胀图与腐蚀图之差,对二值图像进行这一操作可以将团块(blob)的边缘突出出来。我们可以用形态学梯度来保留物体的边缘轮廓。
在这里插入图片描述在这里插入图片描述

2.4 顶帽

顶帽运算(Top Hat)又常常被译为”礼帽“运算。为原图像与上文刚刚介绍的“开运算“的结果图之差。
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。
顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。
在这里插入图片描述在这里插入图片描述

2.5 黑帽

黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差。
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
所以,黑帽运算用来分离比邻近点暗一些的斑块。
在这里插入图片描述在这里插入图片描述
完整代码如下所示:

#include<opencv2/opencv.hpp>   

using namespace std;
using namespace cv;

//高级形态学处理
int main()
{
    Mat im = imread("../logo2.jpg");
    Mat img=im.clone();
    namedWindow("original", WINDOW_NORMAL);
    imshow("original", img);
    Mat out;
    //获取自定义核
    Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的
        
    //高级形态学处理,调用这个函数就可以了,具体要选择哪种操作,就修改第三个参数就可以了。这里演示的是形态学梯度处理
    morphologyEx(img, out, MORPH_OPEN, element);
    namedWindow("开运算", WINDOW_NORMAL);
    imshow("开运算", out);
    imwrite("open.jpg",out);
    waitKey();

    Mat img1=im.clone();
    Mat out1;
    morphologyEx(img1, out1, MORPH_CLOSE, element);
    namedWindow("闭运算", WINDOW_NORMAL);
    imshow("闭运算", out1);
    imwrite("close.jpg",out1);
    waitKey();

    Mat img2=im.clone();
    Mat out2;
    morphologyEx(img, out2, MORPH_GRADIENT, element);
    namedWindow("形态学梯度", WINDOW_NORMAL);
    imshow("形态学梯度", out2);
    imwrite("gradient.jpg",out2);
    waitKey();

    Mat img3=im.clone();
    Mat out3;
    morphologyEx(img3, out3, MORPH_TOPHAT, element);
    namedWindow("顶帽", WINDOW_NORMAL);
    imshow("顶帽", out3);
    imwrite("tophat.jpg",out3);
    waitKey();


    Mat img4=im.clone();
    Mat out4;
    morphologyEx(img4, out4, MORPH_BLACKHAT, element);
    namedWindow("黑帽", WINDOW_NORMAL);
    imshow("黑帽", out4);
    imwrite("blackhat.jpg",out4);
    waitKey();

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值