OpenCV中形态学操作:膨胀、腐蚀、开闭运算

1、基本概念

图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;常见图像形态学运算:腐蚀,膨胀,开运算,闭运算,骨架抽取,极线腐蚀,击中击不中变换,顶帽变换,颗粒分析,流域变换,形态学梯度等。

腐蚀和膨胀是最基本的形态学运算。

腐蚀和膨胀是针对白色部分(高亮部分)而言的。

膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;

腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。

开运算:先腐蚀再膨胀,用来消除小物体

闭运算:先膨胀再腐蚀,用于排除小型黑洞

形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。

顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。

黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。

opencv里有一个很好的函数getStructuringElement,我们只要往这个函数传相应的处理参数,就可以进行相应的操作了,使用起来非常方便。

getStructuringElement():返回指定形状和尺寸的结构元素;

格式:
getStructuringElement(int shape,Size ksize,Point anchor = Point(-1,-1));

参数:
shape:表核的形状,矩形MORPH_RECT;交叉形MORPH_CROSS;椭圆形MORPH_ELLIPSE;
ksize:核尺寸大小;
anchor:锚点的位置,锚点只影响形态学运算结果的偏移;

下面列举一下相应的操作宏定义。

2、膨胀(dilate)

膨胀就是求局部最大值的操作,从图像直观看来,就是将图像光亮部分放大,黑暗部分缩小。

OpenCV的中膨胀函数为dilate()。

dilate(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最大值;
3、将这个最大值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐增长。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	dilate(img, dst, element);
	imshow("膨胀操作", dst);
	waitKey();
	return 0;
}

3、腐蚀(erode)

腐蚀就是与膨胀相反,求局部最小值,从图像直观看来,就是将图像光亮部分缩小,黑暗部分放大。

OpenCV的中腐蚀函数为erode()。

erode(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最小值;
3、将这个最小值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐减小。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//腐蚀操作
	erode(img, dst, element);
	imshow("腐蚀操作", dst);
	waitKey();
	return 0;
}

4、形态学开运算

开操作(先腐蚀后膨胀)可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。

它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学开操作
#if 1
	morphologyEx(img, dst, MORPH_OPEN, element);
#else
	erode(img, dst, element);
	dilate(dst, dst, element);
#endif
	imshow("形态学开操作", dst);
	waitKey();
	return 0;
}

注:形态学操作可使用高级函数morphologyEx。

//形态学操作(开、闭、形态学梯度、顶帽、黑帽)
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
	//第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
	//第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
	//第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
	//MORPH_OPEN – 开运算(Opening operation):先腐蚀后膨胀,去掉小对象
	//MORPH_CLOSE – 闭运算(Closing operation):先膨胀后腐蚀,可以填充一些小的空洞(fill hole)
	//MORPH_GRADIENT - 形态学梯度(Morphological gradient):膨胀后的图减去腐蚀后的图(设置恰当的参数可以得到目标的大致边缘)
	//MORPH_TOPHAT - “顶帽”(“Top hat”):原图像与开操作之间的差值图像(可以用来观察开运算除去了哪些小目标)
	//MORPH_BLACKHAT - “黑帽”(“Black hat“):闭操作图像与源图像的差值图像(可以观察闭运算的效果)
	//第四个参数:结构元素即形态学运算的内核
	//第五个参数,Point类型的anchor,锚的位置,其有默认值( - 1, - 1),表示锚位于中心。
	//第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
	//第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
	//第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档

5、形态学闭运算

闭操作(先膨胀后腐蚀)可以消弭狭窄的间断,消除小的孔洞。先膨胀后腐蚀的操作称之为闭操作。

它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学闭操作
#if 1
	morphologyEx(img, dst, MORPH_CLOSE, element);
#else
	dilate(dst, dst, element);
	erode(img, dst, element);
#endif
	imshow("形态学闭操作", dst);
	waitKey();
	return 0;
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值