opencv学习(8)形态学图像处理

本博文内容和代码均来自《opencv3编程入门》这本书;

形态学图像处理多的方式主要有:
1、膨胀与腐蚀
2、开运算、闭运算、形态学梯度、顶帽、黑帽

膨胀与腐蚀能实现多种多样的功能,主要如下:
1)消除噪声
2)分割(isolate)出独立的图像元素,在图像中连接(join)相邻的元素。
3)寻找图像中的明显的极大值区域或极小值区域
4)求出图像的梯度

首先需要注意,腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
膨胀就是求局部最大值的操作。
按数学方面来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与核(我们称之为B)进行卷积。
核可以是任何的形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点(anchorpoint)。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,其实,我们可以把核视为模板或者掩码。
而膨胀就是求局部最大值的操作,核B与图形卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。
这里写图片描述

膨胀和腐蚀是相反的一对操作,所以腐蚀就是求局部最小值的操作。
这里写图片描述

膨胀和腐蚀的源码:

void cv::erode( InputArray src, OutputArraydst, InputArray kernel,Point anchor, int iterations, int borderType, constScalar& borderValue )  
{  
//调用morphOp函数,并设定标识符为MORPH_ERODE  
   morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType,borderValue );  
}  
void cv::dilate( InputArray src,OutputArray dst, InputArray kernel, Point anchor, int iterations, int borderType, constScalar& borderValue )  
{  
//调用morphOp函数,并设定标识符为MORPH_DILATE  
   morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType,borderValue );  
}  

可以发现erode和dilate这两个函数内部就是调用了一下morphOp,只是他们调用morphOp时,第一个参数标识符不同,一个为MORPH_ERODE(腐蚀),一个为MORPH_DILATE(膨胀)。

1、膨胀——dilate函数

原型:

C++: void dilate(  
    InputArray src,  
    OutputArray dst,  
    InputArray kernel,  
    Point anchor=Point(-1,-1),  
    int iterations=1,  
    int borderType=BORDER_CONSTANT,  
    const Scalar& borderValue=morphologyDefaultBorderValue()   
); 

dilate函数,使用像素邻域内的局部极大运算符来膨胀一张图片,从src输入,由dst输出。支持就地(in-place)操作。
参数详解:
第一个参数,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()函数得到更详细的解释。

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

#include <opencv2/core/core.hpp>  
#include<opencv2/highgui/highgui.hpp>  
#include<opencv2/imgproc/imgproc.hpp>  
#include <iostream>  

//-----------------------------------【命名空间声明部分】---------------------------------------  
//     描述:包含程序所使用的命名空间  
//-----------------------------------------------------------------------------------------------   
using namespace std;  
using namespace cv;  

//-----------------------------------【main( )函数】--------------------------------------------  
//     描述:控制台应用程序的入口函数,我们的程序从这里开始  
//-----------------------------------------------------------------------------------------------  
int main(  )  
{  

       //载入原图   
       Mat image = imread("1.jpg");  

       //创建窗口   
       namedWindow("【原图】膨胀操作");  
       namedWindow("【效果图】膨胀操作");  

       //显示原图  
       imshow("【原图】膨胀操作",
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值